@@ -506,11 +506,8 @@ pub struct Cheatcodes {
506506 pub wallets : Option < Wallets > ,
507507 /// Signatures identifier for decoding events and functions
508508 signatures_identifier : OnceLock < Option < SignaturesIdentifier > > ,
509- /// Used to determine whether the broadcasted call has non-fixed gas limit.
510- /// Holds values for (seen opcode GAS, seen opcode CALL) pair.
511- /// If GAS opcode is followed by CALL opcode then both flags are marked true and call
512- /// has non-fixed gas limit, otherwise the call is considered to have fixed gas limit.
513- pub dynamic_gas_limit_sequence : Option < ( bool , bool ) > ,
509+ /// Used to determine whether the broadcasted call has dynamic gas limit.
510+ pub dynamic_gas_limit : bool ,
514511 // Custom execution evm version.
515512 pub execution_evm_version : Option < SpecId > ,
516513}
@@ -569,7 +566,7 @@ impl Cheatcodes {
569566 deprecated : Default :: default ( ) ,
570567 wallets : Default :: default ( ) ,
571568 signatures_identifier : Default :: default ( ) ,
572- dynamic_gas_limit_sequence : Default :: default ( ) ,
569+ dynamic_gas_limit : Default :: default ( ) ,
573570 execution_evm_version : None ,
574571 }
575572 }
@@ -859,6 +856,11 @@ impl Cheatcodes {
859856
860857 // Apply our broadcast
861858 if let Some ( broadcast) = & self . broadcast {
859+ // Additional check as transfers in forge scripts seem to be estimated at 2300
860+ // by revm leading to "Intrinsic gas too low" failure when simulated on chain.
861+ let is_fixed_gas_limit = call. gas_limit >= 21_000 && !self . dynamic_gas_limit ;
862+ self . dynamic_gas_limit = false ;
863+
862864 // We only apply a broadcast *to a specific depth*.
863865 //
864866 // We do this because any subsequent contract calls *must* exist on chain and
@@ -886,15 +888,6 @@ impl Cheatcodes {
886888 } ) ;
887889 }
888890
889- let ( gas_seen, call_seen) =
890- self . dynamic_gas_limit_sequence . take ( ) . unwrap_or_default ( ) ;
891- // Transaction has fixed gas limit if no GAS opcode seen before CALL opcode.
892- let mut is_fixed_gas_limit = !( gas_seen && call_seen) ;
893- // Additional check as transfers in forge scripts seem to be estimated at 2300
894- // by revm leading to "Intrinsic gas too low" failure when simulated on chain.
895- if call. gas_limit < 21_000 {
896- is_fixed_gas_limit = false ;
897- }
898891 let input = TransactionInput :: new ( call. input . bytes ( ecx) ) ;
899892
900893 let account =
@@ -1122,7 +1115,7 @@ impl Inspector<EthEvmContext<&mut dyn DatabaseExt>> for Cheatcodes {
11221115 self . pc = interpreter. bytecode . pc ( ) ;
11231116
11241117 if self . broadcast . is_some ( ) {
1125- self . record_gas_limit_opcode ( interpreter) ;
1118+ self . set_gas_limit_type ( interpreter) ;
11261119 }
11271120
11281121 // `pauseGasMetering`: pause / resume interpreter gas.
@@ -1165,10 +1158,6 @@ impl Inspector<EthEvmContext<&mut dyn DatabaseExt>> for Cheatcodes {
11651158 }
11661159
11671160 fn step_end ( & mut self , interpreter : & mut Interpreter , ecx : Ecx ) {
1168- if self . broadcast . is_some ( ) {
1169- self . set_gas_limit_type ( interpreter) ;
1170- }
1171-
11721161 if self . gas_metering . paused {
11731162 self . meter_gas_end ( interpreter) ;
11741163 }
@@ -2362,38 +2351,18 @@ impl Cheatcodes {
23622351 }
23632352
23642353 #[ cold]
2365- fn record_gas_limit_opcode ( & mut self , interpreter : & mut Interpreter ) {
2354+ fn set_gas_limit_type ( & mut self , interpreter : & mut Interpreter ) {
23662355 match interpreter. bytecode . opcode ( ) {
2367- // If current opcode is CREATE2 then set non-fixed gas limit.
2368- op:: CREATE2 => self . dynamic_gas_limit_sequence = Some ( ( true , true ) ) ,
2369- op:: GAS => {
2370- if self . dynamic_gas_limit_sequence . is_none ( ) {
2371- // If current opcode is GAS then mark as seen.
2372- self . dynamic_gas_limit_sequence = Some ( ( true , false ) ) ;
2373- }
2356+ op:: CREATE2 => self . dynamic_gas_limit = true ,
2357+ op:: CALL => {
2358+ // If first element of the stack is close to current remaining gas then assume
2359+ // dynamic gas limit.
2360+ self . dynamic_gas_limit =
2361+ try_or_return ! ( interpreter. stack. peek( 0 ) ) >= interpreter. gas . remaining ( ) - 100
23742362 }
2375- _ => { }
2363+ _ => self . dynamic_gas_limit = false ,
23762364 }
23772365 }
2378-
2379- #[ cold]
2380- fn set_gas_limit_type ( & mut self , interpreter : & mut Interpreter ) {
2381- // Early exit in case we already determined is non-fixed gas limit.
2382- if matches ! ( self . dynamic_gas_limit_sequence, Some ( ( true , true ) ) ) {
2383- return ;
2384- }
2385-
2386- // Record CALL opcode if GAS opcode was seen.
2387- if matches ! ( self . dynamic_gas_limit_sequence, Some ( ( true , false ) ) )
2388- && interpreter. bytecode . opcode ( ) == op:: CALL
2389- {
2390- self . dynamic_gas_limit_sequence = Some ( ( true , true ) ) ;
2391- return ;
2392- }
2393-
2394- // Reset dynamic gas limit sequence if GAS opcode was not followed by a CALL opcode.
2395- self . dynamic_gas_limit_sequence = None ;
2396- }
23972366}
23982367
23992368/// Helper that expands memory, stores a revert string pertaining to a disallowed memory write,
0 commit comments