@@ -118,7 +118,6 @@ use revm::{
118118 primitives:: { KECCAK_EMPTY , hardfork:: SpecId } ,
119119 state:: AccountInfo ,
120120} ;
121- use revm_inspectors:: transfer:: TransferInspector ;
122121use std:: {
123122 collections:: BTreeMap ,
124123 fmt:: Debug ,
@@ -247,6 +246,8 @@ pub struct Backend {
247246 // === wallet === //
248247 capabilities : Arc < RwLock < WalletCapabilities > > ,
249248 executor_wallet : Arc < RwLock < Option < EthereumWallet > > > ,
249+ /// Disable pool balance checks
250+ disable_pool_balance_checks : bool ,
250251}
251252
252253impl Backend {
@@ -310,9 +311,9 @@ impl Backend {
310311 states = states. disk_path ( cache_path) ;
311312 }
312313
313- let ( slots_in_an_epoch, precompile_factory) = {
314+ let ( slots_in_an_epoch, precompile_factory, disable_pool_balance_checks ) = {
314315 let cfg = node_config. read ( ) . await ;
315- ( cfg. slots_in_an_epoch , cfg. precompile_factory . clone ( ) )
316+ ( cfg. slots_in_an_epoch , cfg. precompile_factory . clone ( ) , cfg . disable_pool_balance_checks )
316317 } ;
317318
318319 let ( capabilities, executor_wallet) = if odyssey {
@@ -377,6 +378,7 @@ impl Backend {
377378 mining : Arc :: new ( tokio:: sync:: Mutex :: new ( ( ) ) ) ,
378379 capabilities : Arc :: new ( RwLock :: new ( capabilities) ) ,
379380 executor_wallet : Arc :: new ( RwLock :: new ( executor_wallet) ) ,
381+ disable_pool_balance_checks,
380382 } ;
381383
382384 if let Some ( interval_block_time) = automine_block_time {
@@ -1693,11 +1695,13 @@ impl Backend {
16931695 env. evm_env . block_env . basefee = 0 ;
16941696 }
16951697
1698+ let mut inspector = self . build_inspector ( ) ;
1699+
16961700 // transact
16971701 let ResultAndState { result, state } = if trace_transfers {
16981702 // prepare inspector to capture transfer inside the evm so they are
16991703 // recorded and included in logs
1700- let mut inspector = TransferInspector :: new ( false ) . with_logs ( true ) ;
1704+ inspector = inspector . with_transfers ( ) ;
17011705 let mut evm= self . new_evm_with_inspector_ref (
17021706 & cache_db as & dyn DatabaseRef ,
17031707 & env,
@@ -1707,7 +1711,6 @@ impl Backend {
17071711 trace ! ( target: "backend" , env=?env. evm_env, spec=?env. evm_env. spec_id( ) , "simulate evm env" ) ;
17081712 evm. transact ( env. tx ) ?
17091713 } else {
1710- let mut inspector = self . build_inspector ( ) ;
17111714 let mut evm = self . new_evm_with_inspector_ref (
17121715 & cache_db as & dyn DatabaseRef ,
17131716 & env,
@@ -1718,6 +1721,11 @@ impl Backend {
17181721 } ;
17191722 trace ! ( target: "backend" , ?result, ?request, "simulate call" ) ;
17201723
1724+ inspector. print_logs ( ) ;
1725+ if self . print_traces {
1726+ inspector. into_print_traces ( self . call_trace_decoder . clone ( ) ) ;
1727+ }
1728+
17211729 // commit the transaction
17221730 cache_db. commit ( state) ;
17231731 gas_used += result. gas_used ( ) ;
@@ -3336,22 +3344,7 @@ impl TransactionValidator for Backend {
33363344 }
33373345 }
33383346
3339- if tx. gas_limit ( ) < MIN_TRANSACTION_GAS as u64 {
3340- warn ! ( target: "backend" , "[{:?}] gas too low" , tx. hash( ) ) ;
3341- return Err ( InvalidTransactionError :: GasTooLow ) ;
3342- }
3343-
3344- // Check gas limit, iff block gas limit is set.
3345- if !env. evm_env . cfg_env . disable_block_gas_limit
3346- && tx. gas_limit ( ) > env. evm_env . block_env . gas_limit
3347- {
3348- warn ! ( target: "backend" , "[{:?}] gas too high" , tx. hash( ) ) ;
3349- return Err ( InvalidTransactionError :: GasTooHigh ( ErrDetail {
3350- detail : String :: from ( "tx.gas_limit > env.block.gas_limit" ) ,
3351- } ) ) ;
3352- }
3353-
3354- // check nonce
3347+ // Nonce validation
33553348 let is_deposit_tx =
33563349 matches ! ( & pending. transaction. transaction, TypedTransaction :: Deposit ( _) ) ;
33573350 let nonce = tx. nonce ( ) ;
@@ -3360,39 +3353,15 @@ impl TransactionValidator for Backend {
33603353 return Err ( InvalidTransactionError :: NonceTooLow ) ;
33613354 }
33623355
3363- if env. evm_env . cfg_env . spec >= SpecId :: LONDON {
3364- if tx. gas_price ( ) < env. evm_env . block_env . basefee . into ( ) && !is_deposit_tx {
3365- warn ! ( target: "backend" , "max fee per gas={}, too low, block basefee={}" , tx. gas_price( ) , env. evm_env. block_env. basefee) ;
3366- return Err ( InvalidTransactionError :: FeeCapTooLow ) ;
3367- }
3368-
3369- if let ( Some ( max_priority_fee_per_gas) , Some ( max_fee_per_gas) ) =
3370- ( tx. essentials ( ) . max_priority_fee_per_gas , tx. essentials ( ) . max_fee_per_gas )
3371- && max_priority_fee_per_gas > max_fee_per_gas
3372- {
3373- warn ! ( target: "backend" , "max priority fee per gas={}, too high, max fee per gas={}" , max_priority_fee_per_gas, max_fee_per_gas) ;
3374- return Err ( InvalidTransactionError :: TipAboveFeeCap ) ;
3375- }
3376- }
3377-
3378- // EIP-4844 Cancun hard fork validation steps
3356+ // EIP-4844 structural validation
33793357 if env. evm_env . cfg_env . spec >= SpecId :: CANCUN && tx. transaction . is_eip4844 ( ) {
3380- // Light checks first: see if the blob fee cap is too low.
3381- if let Some ( max_fee_per_blob_gas) = tx. essentials ( ) . max_fee_per_blob_gas
3382- && let Some ( blob_gas_and_price) = & env. evm_env . block_env . blob_excess_gas_and_price
3383- && max_fee_per_blob_gas < blob_gas_and_price. blob_gasprice
3384- {
3385- warn ! ( target: "backend" , "max fee per blob gas={}, too low, block blob gas price={}" , max_fee_per_blob_gas, blob_gas_and_price. blob_gasprice) ;
3386- return Err ( InvalidTransactionError :: BlobFeeCapTooLow ) ;
3387- }
3388-
33893358 // Heavy (blob validation) checks
3390- let tx = match & tx. transaction {
3359+ let blob_tx = match & tx. transaction {
33913360 TypedTransaction :: EIP4844 ( tx) => tx. tx ( ) ,
33923361 _ => unreachable ! ( ) ,
33933362 } ;
33943363
3395- let blob_count = tx . tx ( ) . blob_versioned_hashes . len ( ) ;
3364+ let blob_count = blob_tx . tx ( ) . blob_versioned_hashes . len ( ) ;
33963365
33973366 // Ensure there are blob hashes.
33983367 if blob_count == 0 {
@@ -3407,40 +3376,85 @@ impl TransactionValidator for Backend {
34073376
34083377 // Check for any blob validation errors if not impersonating.
34093378 if !self . skip_blob_validation ( Some ( * pending. sender ( ) ) )
3410- && let Err ( err) = tx . validate ( EnvKzgSettings :: default ( ) . get ( ) )
3379+ && let Err ( err) = blob_tx . validate ( EnvKzgSettings :: default ( ) . get ( ) )
34113380 {
34123381 return Err ( InvalidTransactionError :: BlobTransactionValidationError ( err) ) ;
34133382 }
34143383 }
34153384
3416- let max_cost = tx. max_cost ( ) ;
3417- let value = tx. value ( ) ;
3385+ // Balance and fee related checks
3386+ if !self . disable_pool_balance_checks {
3387+ // Gas limit validation
3388+ if tx. gas_limit ( ) < MIN_TRANSACTION_GAS as u64 {
3389+ warn ! ( target: "backend" , "[{:?}] gas too low" , tx. hash( ) ) ;
3390+ return Err ( InvalidTransactionError :: GasTooLow ) ;
3391+ }
3392+
3393+ // Check gas limit against block gas limit, if block gas limit is set.
3394+ if !env. evm_env . cfg_env . disable_block_gas_limit
3395+ && tx. gas_limit ( ) > env. evm_env . block_env . gas_limit
3396+ {
3397+ warn ! ( target: "backend" , "[{:?}] gas too high" , tx. hash( ) ) ;
3398+ return Err ( InvalidTransactionError :: GasTooHigh ( ErrDetail {
3399+ detail : String :: from ( "tx.gas_limit > env.block.gas_limit" ) ,
3400+ } ) ) ;
3401+ }
3402+
3403+ // EIP-1559 fee validation (London hard fork and later)
3404+ if env. evm_env . cfg_env . spec >= SpecId :: LONDON {
3405+ if tx. gas_price ( ) < env. evm_env . block_env . basefee . into ( ) && !is_deposit_tx {
3406+ warn ! ( target: "backend" , "max fee per gas={}, too low, block basefee={}" , tx. gas_price( ) , env. evm_env. block_env. basefee) ;
3407+ return Err ( InvalidTransactionError :: FeeCapTooLow ) ;
3408+ }
34183409
3419- match & tx. transaction {
3420- TypedTransaction :: Deposit ( deposit_tx) => {
3421- // Deposit transactions
3422- // https://specs.optimism.io/protocol/deposits.html#execution
3423- // 1. no gas cost check required since already have prepaid gas from L1
3424- // 2. increment account balance by deposited amount before checking for sufficient
3425- // funds `tx.value <= existing account value + deposited value`
3426- if value > account. balance + U256 :: from ( deposit_tx. mint ) {
3427- warn ! ( target: "backend" , "[{:?}] insufficient balance={}, required={} account={:?}" , tx. hash( ) , account. balance + U256 :: from( deposit_tx. mint) , value, * pending. sender( ) ) ;
3428- return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3410+ if let ( Some ( max_priority_fee_per_gas) , Some ( max_fee_per_gas) ) =
3411+ ( tx. essentials ( ) . max_priority_fee_per_gas , tx. essentials ( ) . max_fee_per_gas )
3412+ && max_priority_fee_per_gas > max_fee_per_gas
3413+ {
3414+ warn ! ( target: "backend" , "max priority fee per gas={}, too high, max fee per gas={}" , max_priority_fee_per_gas, max_fee_per_gas) ;
3415+ return Err ( InvalidTransactionError :: TipAboveFeeCap ) ;
34293416 }
34303417 }
3431- _ => {
3432- // check sufficient funds: `gas * price + value`
3433- let req_funds = max_cost. checked_add ( value. saturating_to ( ) ) . ok_or_else ( || {
3434- warn ! ( target: "backend" , "[{:?}] cost too high" , tx. hash( ) ) ;
3435- InvalidTransactionError :: InsufficientFunds
3436- } ) ?;
3437- if account. balance < U256 :: from ( req_funds) {
3438- warn ! ( target: "backend" , "[{:?}] insufficient allowance={}, required={} account={:?}" , tx. hash( ) , account. balance, req_funds, * pending. sender( ) ) ;
3439- return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3418+
3419+ // EIP-4844 blob fee validation
3420+ if env. evm_env . cfg_env . spec >= SpecId :: CANCUN
3421+ && tx. transaction . is_eip4844 ( )
3422+ && let Some ( max_fee_per_blob_gas) = tx. essentials ( ) . max_fee_per_blob_gas
3423+ && let Some ( blob_gas_and_price) = & env. evm_env . block_env . blob_excess_gas_and_price
3424+ && max_fee_per_blob_gas < blob_gas_and_price. blob_gasprice
3425+ {
3426+ warn ! ( target: "backend" , "max fee per blob gas={}, too low, block blob gas price={}" , max_fee_per_blob_gas, blob_gas_and_price. blob_gasprice) ;
3427+ return Err ( InvalidTransactionError :: BlobFeeCapTooLow ) ;
3428+ }
3429+
3430+ let max_cost = tx. max_cost ( ) ;
3431+ let value = tx. value ( ) ;
3432+ match & tx. transaction {
3433+ TypedTransaction :: Deposit ( deposit_tx) => {
3434+ // Deposit transactions
3435+ // https://specs.optimism.io/protocol/deposits.html#execution
3436+ // 1. no gas cost check required since already have prepaid gas from L1
3437+ // 2. increment account balance by deposited amount before checking for
3438+ // sufficient funds `tx.value <= existing account value + deposited value`
3439+ if value > account. balance + U256 :: from ( deposit_tx. mint ) {
3440+ warn ! ( target: "backend" , "[{:?}] insufficient balance={}, required={} account={:?}" , tx. hash( ) , account. balance + U256 :: from( deposit_tx. mint) , value, * pending. sender( ) ) ;
3441+ return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3442+ }
3443+ }
3444+ _ => {
3445+ // check sufficient funds: `gas * price + value`
3446+ let req_funds =
3447+ max_cost. checked_add ( value. saturating_to ( ) ) . ok_or_else ( || {
3448+ warn ! ( target: "backend" , "[{:?}] cost too high" , tx. hash( ) ) ;
3449+ InvalidTransactionError :: InsufficientFunds
3450+ } ) ?;
3451+ if account. balance < U256 :: from ( req_funds) {
3452+ warn ! ( target: "backend" , "[{:?}] insufficient allowance={}, required={} account={:?}" , tx. hash( ) , account. balance, req_funds, * pending. sender( ) ) ;
3453+ return Err ( InvalidTransactionError :: InsufficientFunds ) ;
3454+ }
34403455 }
34413456 }
34423457 }
3443-
34443458 Ok ( ( ) )
34453459 }
34463460
0 commit comments