revm_context_interface/transaction.rs
1mod alloy_types;
2pub mod eip2930;
3pub mod eip7702;
4pub mod transaction_type;
5
6pub use alloy_types::{
7 AccessList, AccessListItem, Authorization, RecoveredAuthority, RecoveredAuthorization,
8 SignedAuthorization,
9};
10pub use eip2930::AccessListItemTr;
11pub use eip7702::AuthorizationTr;
12pub use transaction_type::TransactionType;
13
14use auto_impl::auto_impl;
15use core::cmp::min;
16use core::fmt::Debug;
17use primitives::{eip4844::GAS_PER_BLOB, Address, Bytes, TxKind, B256, U256};
18
19/// Transaction validity error types.
20pub trait TransactionError: Debug + core::error::Error {}
21
22/// Main Transaction trait that abstracts and specifies all transaction currently supported by Ethereum
23///
24/// Access to any associated type is gaited behind [`tx_type`][Transaction::tx_type] function.
25///
26/// It can be extended to support new transaction types and only transaction types can be
27/// deprecated by not returning tx_type.
28#[auto_impl(&, Box, Arc, Rc)]
29pub trait Transaction {
30 type AccessListItem<'a>: AccessListItemTr
31 where
32 Self: 'a;
33 type Authorization<'a>: AuthorizationTr
34 where
35 Self: 'a;
36
37 /// Returns the transaction type.
38 ///
39 /// Depending on this field other functions should be called.
40 fn tx_type(&self) -> u8;
41
42 /// Caller aka Author aka transaction signer.
43 ///
44 /// Note : Common field for all transactions.
45 fn caller(&self) -> Address;
46
47 /// The maximum amount of gas the transaction can use.
48 ///
49 /// Note : Common field for all transactions.
50 fn gas_limit(&self) -> u64;
51
52 /// The value sent to the receiver of [`TxKind::Call`][primitives::TxKind::Call].
53 ///
54 /// Note : Common field for all transactions.
55 fn value(&self) -> U256;
56
57 /// Returns the input data of the transaction.
58 ///
59 /// Note : Common field for all transactions.
60 fn input(&self) -> &Bytes;
61
62 /// The nonce of the transaction.
63 ///
64 /// Note : Common field for all transactions.
65 fn nonce(&self) -> u64;
66
67 /// Transaction kind. It can be Call or Create.
68 ///
69 /// Kind is applicable for: Legacy, EIP-2930, EIP-1559
70 /// And is Call for EIP-4844 and EIP-7702 transactions.
71 fn kind(&self) -> TxKind;
72
73 /// Chain Id is optional for legacy transactions.
74 ///
75 /// As it was introduced in EIP-155.
76 fn chain_id(&self) -> Option<u64>;
77
78 /// Gas price for the transaction.
79 /// It is only applicable for Legacy and EIP-2930 transactions.
80 /// For Eip1559 it is max_fee_per_gas.
81 fn gas_price(&self) -> u128;
82
83 /// Access list for the transaction.
84 ///
85 /// Introduced in EIP-2930.
86 fn access_list(&self) -> Option<impl Iterator<Item = Self::AccessListItem<'_>>>;
87
88 /// Returns vector of fixed size hash(32 bytes)
89 ///
90 /// Note : EIP-4844 transaction field.
91 fn blob_versioned_hashes(&self) -> &[B256];
92
93 /// Max fee per data gas
94 ///
95 /// Note : EIP-4844 transaction field.
96 fn max_fee_per_blob_gas(&self) -> u128;
97
98 /// Total gas for all blobs. Max number of blocks is already checked
99 /// so we dont need to check for overflow.
100 fn total_blob_gas(&self) -> u64 {
101 GAS_PER_BLOB * self.blob_versioned_hashes().len() as u64
102 }
103
104 /// Calculates the maximum [EIP-4844] `data_fee` of the transaction.
105 ///
106 /// This is used for ensuring that the user has at least enough funds to pay the
107 /// `max_fee_per_blob_gas * total_blob_gas`, on top of regular gas costs.
108 ///
109 /// See EIP-4844:
110 /// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4844.md#execution-layer-validation>
111 fn calc_max_data_fee(&self) -> U256 {
112 let blob_gas = U256::from(self.total_blob_gas());
113 let max_blob_fee = U256::from(self.max_fee_per_blob_gas());
114 max_blob_fee.saturating_mul(blob_gas)
115 }
116
117 /// Returns length of the authorization list.
118 ///
119 /// # Note
120 ///
121 /// Transaction is considered invalid if list is empty.
122 fn authorization_list_len(&self) -> usize;
123
124 /// List of authorizations, that contains the signature that authorizes this
125 /// caller to place the code to signer account.
126 ///
127 /// Set EOA account code for one transaction
128 ///
129 /// [EIP-Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702)
130 fn authorization_list(&self) -> impl Iterator<Item = Self::Authorization<'_>>;
131
132 /// List of initcodes found in Initcode transaction. Initcodes can only be accessed
133 /// by TXCREATE opcode to create a new EOF contract.
134 ///
135 /// Each transaction can contain up to [`primitives::eof::MAX_INITCODE_COUNT`] initcodes,
136 /// with each initcode not exceeding [`primitives::MAX_INITCODE_SIZE`] bytes in size.
137 ///
138 /// EIP link: <https://eips.ethereum.org/EIPS/eip-7873>
139 fn initcodes(&self) -> &[Bytes];
140
141 /// Returns maximum fee that can be paid for the transaction.
142 fn max_fee_per_gas(&self) -> u128 {
143 self.gas_price()
144 }
145
146 /// Maximum priority fee per gas.
147 fn max_priority_fee_per_gas(&self) -> Option<u128>;
148
149 /// Returns effective gas price is gas price field for Legacy and Eip2930 transaction.
150 ///
151 /// While for transactions after Eip1559 it is minimum of max_fee and `base + max_priority_fee`.
152 fn effective_gas_price(&self, base_fee: u128) -> u128 {
153 if self.tx_type() == TransactionType::Legacy as u8
154 || self.tx_type() == TransactionType::Eip2930 as u8
155 {
156 return self.gas_price();
157 }
158
159 // for EIP-1559 tx and onwards gas_price represents maximum price.
160 let max_price = self.gas_price();
161 let Some(max_priority_fee) = self.max_priority_fee_per_gas() else {
162 return max_price;
163 };
164 min(max_price, base_fee.saturating_add(max_priority_fee))
165 }
166}
167
168#[auto_impl(&, &mut, Box, Arc)]
169pub trait TransactionGetter {
170 type Transaction: Transaction;
171
172 fn tx(&self) -> &Self::Transaction;
173}