@@ -14,10 +14,10 @@ use alloy::{
1414use core:: convert:: Infallible ;
1515use revm:: {
1616 db:: { states:: bundle_state:: BundleRetention , BundleState , State } ,
17- interpreter:: gas:: CALL_STIPEND ,
17+ interpreter:: gas:: { calculate_initial_tx_gas , CALL_STIPEND } ,
1818 primitives:: {
19- AccountInfo , BlockEnv , Bytecode , EVMError , EvmState , ExecutionResult , InvalidTransaction ,
20- ResultAndState , SpecId , TxEnv , TxKind , KECCAK_EMPTY ,
19+ AccountInfo , AuthorizationList , BlockEnv , Bytecode , EVMError , Env , EvmState ,
20+ ExecutionResult , InvalidTransaction , ResultAndState , SpecId , TxEnv , TxKind , KECCAK_EMPTY ,
2121 } ,
2222 Database , DatabaseCommit , DatabaseRef , Evm ,
2323} ;
@@ -71,6 +71,30 @@ impl<'a, Ext, Db: Database + DatabaseCommit, TrevmState> Trevm<'a, Ext, Db, Trev
7171 self . inner
7272 }
7373
74+ /// Get a reference to the inner env. This contains the current
75+ /// [`BlockEnv`], [`TxEnv`], and [`CfgEnv`].
76+ ///
77+ /// These values may be meaningless, stale, or otherwise incorrect. Reading
78+ /// them should be done with caution, as it may lead to logic bugs.
79+ ///
80+ /// [`CfgEnv`]: revm::primitives::CfgEnv
81+ pub fn env_unchecked ( & self ) -> & Env {
82+ & self . inner ( ) . context . evm . inner . env
83+ }
84+
85+ /// Get a mutable reference to the inner env. This contains the current
86+ /// [`BlockEnv`], [`TxEnv`], and [`CfgEnv`].
87+ ///
88+ /// These values may be meaningless, stale, or otherwise incorrect. Reading
89+ /// them should be done with caution, as it may lead to logic bugs.
90+ /// Modifying these values may lead to inconsistent state or invalid
91+ /// execution.
92+ ///
93+ /// [`CfgEnv`]: revm::primitives::CfgEnv
94+ pub fn env_mut_unchecked ( & mut self ) -> & mut Env {
95+ & mut self . inner_mut_unchecked ( ) . context . evm . inner . env
96+ }
97+
7498 /// Get the id of the currently running hardfork spec. Convenience function
7599 /// calling [`Evm::spec_id`].
76100 pub fn spec_id ( & self ) -> SpecId {
@@ -1176,7 +1200,7 @@ impl<'a, Ext, Db: Database + DatabaseCommit, TrevmState: HasTx> Trevm<'a, Ext, D
11761200 }
11771201}
11781202
1179- // -- HAS TX with State<Db>
1203+ // -- NEEDS TX with State<Db>
11801204
11811205impl < Ext , Db : Database > EvmNeedsTx < ' _ , Ext , State < Db > > {
11821206 /// Apply block overrides to the current block.
@@ -1236,12 +1260,36 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmReady<'a, Ext, Db> {
12361260 }
12371261 }
12381262
1263+ /// Calculate the minimum gas required to start EVM execution.
1264+ ///
1265+ /// This uses [`calculate_initial_tx_gas`] to calculate the initial gas.
1266+ /// Its output is dependent on
1267+ /// - the EVM spec
1268+ /// - the input data
1269+ /// - whether the transaction is a contract creation or a call
1270+ /// - the EIP-2930 access list
1271+ /// - the number of [EIP-7702] authorizations
1272+ ///
1273+ /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
1274+ /// [EIP-7702]: https://eips.ethereum.org/EIPS/eip-7702
1275+ fn calculate_initial_gas ( & self ) -> u64 {
1276+ calculate_initial_tx_gas (
1277+ self . spec_id ( ) ,
1278+ & [ ] ,
1279+ false ,
1280+ & self . tx ( ) . access_list ,
1281+ self . tx ( ) . authorization_list . as_ref ( ) . map ( AuthorizationList :: len) . unwrap_or_default ( )
1282+ as u64 ,
1283+ )
1284+ . initial_gas
1285+ }
1286+
12391287 /// Estimate gas for a simple transfer. This will
12401288 /// - Check that the transaction has no input data.
12411289 /// - Check that the target is not a `create`.
12421290 /// - Check that the target is not a contract.
12431291 /// - Return the minimum gas required for the transfer.
1244- fn estimate_gas_simple_transfer ( & mut self ) -> Result < Option < ( ) > , EVMError < Db :: Error > > {
1292+ fn estimate_gas_simple_transfer ( & mut self ) -> Result < Option < u64 > , EVMError < Db :: Error > > {
12451293 if !self . is_transfer ( ) {
12461294 return Ok ( None ) ;
12471295 }
@@ -1254,8 +1302,9 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmReady<'a, Ext, Db> {
12541302 return Ok ( None ) ;
12551303 }
12561304
1257- // If the target is not a contract, then the gas is the minimum gas.
1258- Ok ( Some ( ( ) ) )
1305+ // delegate calculation to revm. This ensures that things like bogus
1306+ // 2930 access lists don't mess up our estimates
1307+ Ok ( Some ( self . calculate_initial_gas ( ) ) )
12591308 }
12601309
12611310 /// Convenience function to simplify nesting of [`Self::estimate_gas`].
@@ -1330,22 +1379,28 @@ impl<'a, Ext, Db: Database + DatabaseCommit> EvmReady<'a, Ext, Db> {
13301379 ///
13311380 /// [here]: https://github.com/paradigmxyz/reth/blob/ad503a08fa242b28ad3c1fea9caa83df2dfcf72d/crates/rpc/rpc-eth-api/src/helpers/estimate.rs#L35-L42
13321381 pub fn estimate_gas ( mut self ) -> Result < ( EstimationResult , Self ) , EvmErrored < ' a , Ext , Db > > {
1333- if unwrap_or_trevm_err ! ( self . estimate_gas_simple_transfer( ) , self ) . is_some ( ) {
1334- return Ok ( ( EstimationResult :: basic_transfer_success ( ) , self ) ) ;
1382+ if let Some ( est ) = unwrap_or_trevm_err ! ( self . estimate_gas_simple_transfer( ) , self ) {
1383+ return Ok ( ( EstimationResult :: basic_transfer_success ( est ) , self ) ) ;
13351384 }
13361385
13371386 // We shrink the gas limit to 64 bits, as using more than 18 quintillion
1338- // gas in a block is not likely .
1387+ // gas in a block is unlikely .
13391388 let initial_limit = self . gas_limit ( ) ;
13401389
1390+ // Start the search range at 21_000 gas.
13411391 let mut search_range = SearchRange :: new ( MIN_TRANSACTION_GAS , initial_limit) ;
1392+
1393+ // Block it to the gas cap.
13421394 search_range. maybe_lower_max ( self . block_gas_limit ( ) . saturating_to :: < u64 > ( ) ) ;
13431395
13441396 // Check that the account has enough ETH to cover the gas, and lower if
13451397 // necessary.
13461398 let allowance = unwrap_or_trevm_err ! ( self . gas_allowance( ) , self ) ;
13471399 search_range. maybe_lower_max ( allowance) ;
13481400
1401+ // Raise the floor to the amount of gas required to initialize the EVM.
1402+ search_range. maybe_raise_min ( self . calculate_initial_gas ( ) ) ;
1403+
13491404 // Run an estimate with the max gas limit.
13501405 // NB: we declare these mut as we re-use the binding throughout the
13511406 // function.
0 commit comments