Skip to content

Commit b5ae7a6

Browse files
committed
fix: Respect --override-* flags on cast call with --trace flag
1 parent d22e730 commit b5ae7a6

File tree

7 files changed

+78
-12
lines changed

7 files changed

+78
-12
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cast/src/cmd/call.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ impl CallArgs {
262262
trace_mode,
263263
odyssey,
264264
create2_deployer,
265+
state_overrides,
265266
)?;
266267

267268
let value = tx.value.unwrap_or_default();

crates/cast/src/cmd/run.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ impl RunArgs {
186186
trace_mode,
187187
odyssey,
188188
create2_deployer,
189+
None,
189190
)?;
190191
let mut env = Env::new_with_spec_id(
191192
env.evm_env.cfg_env.clone(),

crates/evm/evm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ alloy-primitives = { workspace = true, features = [
3232
"arbitrary",
3333
"rlp",
3434
] }
35+
alloy-rpc-types.workspace = true
3536
alloy-sol-types.workspace = true
3637
revm = { workspace = true, default-features = false, features = [
3738
"std",

crates/evm/evm/src/executors/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,35 @@ impl Executor {
258258
Ok(self.backend().basic_ref(address)?.map(|acc| acc.nonce).unwrap_or_default())
259259
}
260260

261+
/// Set the code of an account.
262+
pub fn set_code(&mut self, address: Address, code: Bytecode) -> BackendResult<()> {
263+
let mut account = self.backend().basic_ref(address)?.unwrap_or_default();
264+
account.code = Some(code);
265+
self.backend_mut().insert_account_info(address, account);
266+
Ok(())
267+
}
268+
269+
/// Set the storage of an account.
270+
pub fn set_storage(
271+
&mut self,
272+
address: Address,
273+
storage: HashMap<U256, U256>,
274+
) -> BackendResult<()> {
275+
self.backend_mut().replace_account_storage(address, storage)?;
276+
Ok(())
277+
}
278+
279+
/// Set a storage slot of an account.
280+
pub fn set_storage_slot(
281+
&mut self,
282+
address: Address,
283+
slot: U256,
284+
value: U256,
285+
) -> BackendResult<()> {
286+
self.backend_mut().insert_account_storage(address, slot, value)?;
287+
Ok(())
288+
}
289+
261290
/// Returns `true` if the account has no code.
262291
pub fn is_empty_code(&self, address: Address) -> BackendResult<bool> {
263292
Ok(self.backend().basic_ref(address)?.map(|acc| acc.is_empty_code_hash()).unwrap_or(true))

crates/evm/evm/src/executors/trace.rs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ use crate::{
22
executors::{Executor, ExecutorBuilder},
33
Env,
44
};
5-
use alloy_primitives::Address;
5+
use alloy_primitives::{map::HashMap, Address, U256};
6+
use alloy_rpc_types::state::StateOverride;
7+
use eyre::Context;
68
use foundry_compilers::artifacts::EvmVersion;
79
use foundry_config::{utils::evm_spec_id, Chain, Config};
810
use foundry_evm_core::{backend::Backend, fork::CreateFork, opts::EvmOpts};
911
use foundry_evm_traces::TraceMode;
10-
use revm::primitives::hardfork::SpecId;
12+
use revm::{primitives::hardfork::SpecId, state::Bytecode};
1113
use std::ops::{Deref, DerefMut};
1214

1315
/// A default executor with tracing enabled
@@ -23,18 +25,48 @@ impl TracingExecutor {
2325
trace_mode: TraceMode,
2426
odyssey: bool,
2527
create2_deployer: Address,
28+
state_overrides: Option<StateOverride>,
2629
) -> eyre::Result<Self> {
2730
let db = Backend::spawn(fork)?;
28-
Ok(Self {
29-
// configures a bare version of the evm executor: no cheatcode inspector is enabled,
30-
// tracing will be enabled only for the targeted transaction
31-
executor: ExecutorBuilder::new()
32-
.inspectors(|stack| {
33-
stack.trace_mode(trace_mode).odyssey(odyssey).create2_deployer(create2_deployer)
34-
})
35-
.spec_id(evm_spec_id(version.unwrap_or_default(), odyssey))
36-
.build(env, db),
37-
})
31+
// configures a bare version of the evm executor: no cheatcode inspector is enabled,
32+
// tracing will be enabled only for the targeted transaction
33+
let mut executor = ExecutorBuilder::new()
34+
.inspectors(|stack| {
35+
stack.trace_mode(trace_mode).odyssey(odyssey).create2_deployer(create2_deployer)
36+
})
37+
.spec_id(evm_spec_id(version.unwrap_or_default(), odyssey))
38+
.build(env, db);
39+
40+
// Apply the state overrides.
41+
if let Some(state_overrides) = state_overrides {
42+
for (address, overrides) in state_overrides {
43+
if let Some(balance) = overrides.balance {
44+
executor.set_balance(address, balance)?;
45+
}
46+
if let Some(nonce) = overrides.nonce {
47+
executor.set_nonce(address, nonce)?;
48+
}
49+
if let Some(code) = overrides.code {
50+
let bytecode = Bytecode::new_raw_checked(code)
51+
.wrap_err("invalid bytecode in state override")?;
52+
executor.set_code(address, bytecode)?;
53+
}
54+
if let Some(state) = overrides.state {
55+
let state: HashMap<U256, U256> = state
56+
.into_iter()
57+
.map(|(slot, value)| (slot.into(), value.into()))
58+
.collect();
59+
executor.set_storage(address, state)?;
60+
}
61+
if let Some(state_diff) = overrides.state_diff {
62+
for (slot, value) in state_diff {
63+
executor.set_storage_slot(address, slot.into(), value.into())?;
64+
}
65+
}
66+
}
67+
}
68+
69+
Ok(Self { executor })
3870
}
3971

4072
/// Returns the spec id of the executor

crates/verify/src/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ pub async fn get_tracing_executor(
321321
TraceMode::Call,
322322
is_odyssey,
323323
create2_deployer,
324+
None,
324325
)?;
325326

326327
Ok((env, executor))

0 commit comments

Comments
 (0)