loom_evm_utils/
evm_tx_env.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use alloy::consensus::Transaction as TransactionTrait;
use alloy::consensus::{TxEip4844Variant, TxEnvelope};
use alloy::primitives::private::alloy_rlp;
use alloy::primitives::{Bytes, SignatureError, TxKind, U256};
use alloy::rlp::Decodable;
use alloy::rpc::types::Transaction;
use reth_primitives::revm_primitives::{AuthorizationList, TxEnv};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum EnvError {
    #[error(transparent)]
    AlloyRplError(#[from] alloy_rlp::Error),
    #[error(transparent)]
    SignatureError(#[from] SignatureError),
    #[error("Unsupported transaction type")]
    UnsupportedTransactionType,
}

pub fn env_from_signed_tx(rpl_bytes: Bytes) -> Result<TxEnv, EnvError> {
    match TxEnvelope::decode(&mut rpl_bytes.iter().as_slice())? {
        TxEnvelope::Legacy(tx) => {
            Ok(TxEnv {
                caller: tx.recover_signer()?,
                transact_to: tx.tx().to,
                nonce: Some(tx.tx().nonce),
                data: tx.tx().input.clone(),
                value: tx.tx().value,
                gas_price: U256::from(tx.tx().gas_price),
                gas_limit: tx.tx().gas_limit,
                chain_id: tx.tx().chain_id,

                // not supported
                access_list: vec![],
                gas_priority_fee: None,
                blob_hashes: vec![],
                max_fee_per_blob_gas: None,
                authorization_list: None,
            })
        }
        TxEnvelope::Eip2930(tx) => {
            Ok(TxEnv {
                caller: tx.recover_signer()?,
                transact_to: tx.tx().to,
                nonce: Some(tx.tx().nonce),
                data: tx.tx().input.clone(),
                value: tx.tx().value,
                gas_price: U256::from(tx.tx().gas_price),
                gas_limit: tx.tx().gas_limit,
                chain_id: Some(tx.tx().chain_id),
                access_list: tx.tx().clone().access_list.0,

                // not supported
                gas_priority_fee: None,
                blob_hashes: vec![],
                max_fee_per_blob_gas: None,
                authorization_list: None,
            })
        }
        TxEnvelope::Eip1559(tx) => {
            Ok(TxEnv {
                caller: tx.recover_signer()?,
                transact_to: tx.tx().to,
                nonce: Some(tx.tx().nonce),
                data: tx.tx().input.clone(),
                value: tx.tx().value,
                gas_price: U256::from(tx.tx().max_fee_per_gas),
                gas_priority_fee: Some(U256::from(tx.tx().max_priority_fee_per_gas)),
                gas_limit: tx.tx().gas_limit,
                chain_id: Some(tx.tx().chain_id),
                access_list: tx.tx().clone().access_list.0,

                // not supported
                blob_hashes: vec![],
                max_fee_per_blob_gas: None,
                authorization_list: None,
            })
        }
        TxEnvelope::Eip4844(signed_tx) => {
            let tx = match signed_tx.tx() {
                TxEip4844Variant::TxEip4844(tx) => tx,
                TxEip4844Variant::TxEip4844WithSidecar(tx) => tx.tx(),
            };
            Ok(TxEnv {
                caller: signed_tx.recover_signer()?,
                transact_to: TxKind::Call(tx.to),
                nonce: Some(tx.nonce),
                data: tx.input.clone(),
                value: tx.value,
                gas_price: U256::from(tx.max_fee_per_gas),
                gas_priority_fee: Some(U256::from(tx.max_priority_fee_per_gas)),
                gas_limit: tx.gas_limit,
                chain_id: Some(tx.chain_id),
                access_list: tx.clone().access_list.0,
                max_fee_per_blob_gas: Some(U256::from(tx.max_fee_per_blob_gas)),
                blob_hashes: tx.blob_versioned_hashes.clone(),

                // Not supported
                authorization_list: None,
            })
        }
        TxEnvelope::Eip7702(tx) => {
            Ok(TxEnv {
                caller: tx.recover_signer()?,
                transact_to: TxKind::Call(tx.tx().to),
                nonce: Some(tx.tx().nonce),
                data: tx.tx().input.clone(),
                value: tx.tx().value,
                gas_price: U256::from(tx.tx().max_fee_per_gas),
                gas_priority_fee: Some(U256::from(tx.tx().max_priority_fee_per_gas)),
                gas_limit: tx.tx().gas_limit,
                chain_id: Some(tx.tx().chain_id),
                access_list: tx.tx().clone().access_list.0,
                authorization_list: Some(AuthorizationList::Signed(tx.tx().clone().authorization_list)),

                // Not supported
                blob_hashes: vec![],
                max_fee_per_blob_gas: None,
            })
        }
        _ => Err(EnvError::UnsupportedTransactionType),
    }
}

pub fn tx_to_evm_tx(tx: &Transaction) -> TxEnv {
    TxEnv {
        transact_to: match tx.to() {
            Some(to) => TxKind::Call(to),
            None => TxKind::Create,
        },
        nonce: Some(tx.nonce()),
        chain_id: tx.chain_id(),
        data: tx.input().clone(),
        value: tx.value(),
        caller: tx.from,
        gas_limit: tx.gas_limit(),

        // support type 1 and 2
        gas_price: U256::from(tx.max_fee_per_gas()),
        gas_priority_fee: Some(U256::from(tx.max_priority_fee_per_gas().unwrap_or_default())),

        // Not used in loom context
        blob_hashes: vec![],
        max_fee_per_blob_gas: None,
        access_list: vec![],
        authorization_list: None,
    }
}