Skip to content

Commit 093bb33

Browse files
committed
fix(forge): account gas limit per fork when script simulate
1 parent cff3dec commit 093bb33

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

crates/cheatcodes/src/inspector.rs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use foundry_common::{
4040
use foundry_evm_core::{
4141
InspectorExt,
4242
abi::Vm::stopExpectSafeMemoryCall,
43-
backend::{DatabaseError, DatabaseExt, RevertDiagnostic},
43+
backend::{DatabaseError, DatabaseExt, LocalForkId, RevertDiagnostic},
4444
constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, MAGIC_ASSUME},
4545
evm::{FoundryEvm, new_evm_with_existing_context},
4646
};
@@ -499,6 +499,8 @@ pub struct Cheatcodes {
499499
pub wallets: Option<Wallets>,
500500
/// Signatures identifier for decoding events and functions
501501
pub signatures_identifier: Option<SignaturesIdentifier>,
502+
/// Broadcast gas limits, per fork.
503+
pub broadcast_gas_limits: HashMap<LocalForkId, u64>,
502504
}
503505

504506
// This is not derived because calling this in `fn new` with `..Default::default()` creates a second
@@ -554,6 +556,7 @@ impl Cheatcodes {
554556
deprecated: Default::default(),
555557
wallets: Default::default(),
556558
signatures_identifier: SignaturesIdentifier::new(true).ok(),
559+
broadcast_gas_limits: Default::default(),
557560
}
558561
}
559562

@@ -852,7 +855,11 @@ impl Cheatcodes {
852855
});
853856
}
854857

855-
let is_fixed_gas_limit = check_if_fixed_gas_limit(&ecx, call.gas_limit);
858+
let is_fixed_gas_limit = check_if_fixed_gas_limit(
859+
&mut self.broadcast_gas_limits,
860+
&ecx,
861+
call.gas_limit,
862+
);
856863

857864
let input = TransactionInput::new(call.input.bytes(ecx));
858865

@@ -1612,7 +1619,11 @@ impl Inspector<EthEvmContext<&mut dyn DatabaseExt>> for Cheatcodes {
16121619

16131620
if curr_depth == broadcast.depth {
16141621
input.set_caller(broadcast.new_origin);
1615-
let is_fixed_gas_limit = check_if_fixed_gas_limit(&ecx, input.gas_limit());
1622+
let is_fixed_gas_limit = check_if_fixed_gas_limit(
1623+
&mut self.broadcast_gas_limits,
1624+
&ecx,
1625+
input.gas_limit(),
1626+
);
16161627

16171628
let account = &ecx.journaled_state.inner.state()[&broadcast.new_origin];
16181629
self.broadcastable_transactions.push_back(BroadcastableTransaction {
@@ -2320,17 +2331,33 @@ fn disallowed_mem_write(
23202331
}
23212332

23222333
// Determines if the gas limit on a given call was manually set in the script and should therefore
2323-
// not be overwritten by later estimations
2324-
fn check_if_fixed_gas_limit(ecx: &Ecx, call_gas_limit: u64) -> bool {
2334+
// not be overwritten by later estimations. Applies the gas limit per each fork.
2335+
fn check_if_fixed_gas_limit(
2336+
broadcast_gas_limits: &mut HashMap<LocalForkId, u64>,
2337+
ecx: &Ecx,
2338+
call_gas_limit: u64,
2339+
) -> bool {
2340+
let call_limit_on_active_fork =
2341+
ecx.journaled_state.database.active_fork_id().map_or(0, |fork_id| {
2342+
let total_limits: u64 = broadcast_gas_limits.values().sum();
2343+
let other_forks_limit =
2344+
total_limits - broadcast_gas_limits.get(&fork_id).copied().unwrap_or(0);
2345+
// Calculate and update call limit for the current fork.
2346+
let call_limit_on_active_fork =
2347+
ecx.tx.gas_limit.saturating_sub(call_gas_limit + other_forks_limit);
2348+
broadcast_gas_limits.insert(fork_id, call_limit_on_active_fork);
2349+
call_limit_on_active_fork
2350+
});
2351+
23252352
// If the gas limit was not set in the source code it is set to the estimated gas left at the
2326-
// time of the call, which should be rather close to configured gas limit.
2353+
// time of the call, per fork, which should be rather close to configured gas limit.
23272354
// TODO: Find a way to reliably make this determination.
23282355
// For example by generating it in the compilation or EVM simulation process
23292356
ecx.tx.gas_limit > ecx.block.gas_limit &&
2330-
call_gas_limit <= ecx.block.gas_limit
2357+
call_limit_on_active_fork <= ecx.block.gas_limit
23312358
// Transfers in forge scripts seem to be estimated at 2300 by revm leading to "Intrinsic
23322359
// gas too low" failure when simulated on chain
2333-
&& call_gas_limit > 2300
2360+
&& call_limit_on_active_fork > 2300
23342361
}
23352362

23362363
/// Returns true if the kind of account access is a call.

0 commit comments

Comments
 (0)