@@ -499,10 +499,10 @@ pub struct Cheatcodes {
499
499
pub wallets : Option < Wallets > ,
500
500
/// Signatures identifier for decoding events and functions
501
501
pub signatures_identifier : Option < SignaturesIdentifier > ,
502
- /// Determine if broadcasted call has fixed gas by tracking checking that CALL is preceded by
503
- /// GAS opcode. Set to option true when GAS opcode seen and to option false if next opcode is
504
- /// CALL .
505
- pub is_fixed_gas_limit : Option < bool > ,
502
+ /// Whether the broadcasted call has fixed gas limit (if no GAS opcode seen before
503
+ /// CALL opcode) . Set to (true, true) when GAS is followed by a CALL opcode or if CREATE2
504
+ /// opcode .
505
+ pub is_fixed_gas_limit : Option < ( bool , bool ) > ,
506
506
}
507
507
508
508
// This is not derived because calling this in `fn new` with `..Default::default()` creates a second
@@ -857,12 +857,14 @@ impl Cheatcodes {
857
857
} ) ;
858
858
}
859
859
860
- let mut is_fixed_gas_limit = self . is_fixed_gas_limit . take ( ) . unwrap_or_default ( ) ;
860
+ let ( gas_seen, call_seen) = self . is_fixed_gas_limit . take ( ) . unwrap_or_default ( ) ;
861
+ // Transaction has fixed gas limit if no GAS opcode seen before CALL opcode.
862
+ let mut is_fixed_gas_limit = !( gas_seen && call_seen) ;
861
863
// Additional check as transfers in forge scripts seem to be estimated at 2300
862
864
// by revm leading to "Intrinsic gas too low" failure when simulated on chain.
863
- if call. gas_limit < 21000 {
865
+ if call. gas_limit < 21_000 {
864
866
is_fixed_gas_limit = false ;
865
- } ;
867
+ }
866
868
let input = TransactionInput :: new ( call. input . bytes ( ecx) ) ;
867
869
868
870
let account =
@@ -2309,23 +2311,36 @@ impl Cheatcodes {
2309
2311
2310
2312
#[ cold]
2311
2313
fn record_gas_limit_opcode ( & mut self , interpreter : & mut Interpreter ) {
2312
- if interpreter. bytecode . opcode ( ) == op:: GAS {
2313
- self . is_fixed_gas_limit = Some ( true ) ;
2314
+ match interpreter. bytecode . opcode ( ) {
2315
+ // If current opcode is CREATE2 then set non-fixed gas limit.
2316
+ op:: CREATE2 => self . is_fixed_gas_limit = Some ( ( true , true ) ) ,
2317
+ op:: GAS => {
2318
+ if self . is_fixed_gas_limit . is_none ( ) {
2319
+ // If current opcode is GAS then mark as seen.
2320
+ self . is_fixed_gas_limit = Some ( ( true , false ) ) ;
2321
+ }
2322
+ }
2323
+ _ => { }
2314
2324
}
2315
2325
}
2316
2326
2317
2327
#[ cold]
2318
2328
fn set_gas_limit_type ( & mut self , interpreter : & mut Interpreter ) {
2319
- if interpreter. bytecode . opcode ( ) == op:: CALL {
2320
- if self . is_fixed_gas_limit . is_some ( ) {
2321
- // If GAS opcode was seen and current opcode is CALL then it doesn't have fixed gas
2322
- // limit.
2323
- self . is_fixed_gas_limit = Some ( false ) ;
2324
- } else {
2325
- // If GAS opcode wasn't seen then it has fixed call limit.
2326
- self . is_fixed_gas_limit = Some ( true ) ;
2327
- }
2329
+ // Early exit in case we already determined is non-fixed gas limit.
2330
+ if matches ! ( self . is_fixed_gas_limit, Some ( ( true , true ) ) ) {
2331
+ return ;
2328
2332
}
2333
+
2334
+ // Record CALL opcode if GAS opcode was seen.
2335
+ if matches ! ( self . is_fixed_gas_limit, Some ( ( true , false ) ) )
2336
+ && interpreter. bytecode . opcode ( ) == op:: CALL
2337
+ {
2338
+ self . is_fixed_gas_limit = Some ( ( true , true ) ) ;
2339
+ return ;
2340
+ }
2341
+
2342
+ // Reset gas record if GAS opcode was not followed by a CALL opcode.
2343
+ self . is_fixed_gas_limit = None ;
2329
2344
}
2330
2345
}
2331
2346
0 commit comments