Skip to content

Commit ba1215c

Browse files
committed
Reset gas if next opcode is not CALL
1 parent a7eb27e commit ba1215c

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

crates/cheatcodes/src/inspector.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -499,10 +499,10 @@ pub struct Cheatcodes {
499499
pub wallets: Option<Wallets>,
500500
/// Signatures identifier for decoding events and functions
501501
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)>,
506506
}
507507

508508
// This is not derived because calling this in `fn new` with `..Default::default()` creates a second
@@ -857,12 +857,14 @@ impl Cheatcodes {
857857
});
858858
}
859859

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);
861863
// Additional check as transfers in forge scripts seem to be estimated at 2300
862864
// 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 {
864866
is_fixed_gas_limit = false;
865-
};
867+
}
866868
let input = TransactionInput::new(call.input.bytes(ecx));
867869

868870
let account =
@@ -2309,23 +2311,36 @@ impl Cheatcodes {
23092311

23102312
#[cold]
23112313
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+
_ => {}
23142324
}
23152325
}
23162326

23172327
#[cold]
23182328
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;
23282332
}
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;
23292344
}
23302345
}
23312346

0 commit comments

Comments
 (0)