From 9bf832039e9b318787a3b2a0b3e9dc5b1b2d13d3 Mon Sep 17 00:00:00 2001 From: chen Date: Thu, 3 Oct 2024 16:20:22 +0800 Subject: [PATCH 1/6] Add options for state changes output and json output in cast run command --- Cargo.lock | 1 + crates/cast/bin/cmd/call.rs | 14 +++++-- crates/cast/bin/cmd/run.rs | 16 ++++++-- crates/cli/src/utils/cmd.rs | 59 +++++++++++++++------------ crates/evm/evm/src/executors/trace.rs | 9 ++-- crates/evm/traces/Cargo.toml | 1 + crates/evm/traces/src/lib.rs | 26 ++++++++++-- 7 files changed, 88 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7308606c9e3c..d909bbd0e34f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4009,6 +4009,7 @@ dependencies = [ "revm-inspectors", "rustc-hash", "serde", + "serde_json", "solang-parser", "tempfile", "tokio", diff --git a/crates/cast/bin/cmd/call.rs b/crates/cast/bin/cmd/call.rs index 9afc7ff5ae35..9914c6d7362c 100644 --- a/crates/cast/bin/cmd/call.rs +++ b/crates/cast/bin/cmd/call.rs @@ -182,8 +182,15 @@ impl CallArgs { env.cfg.disable_block_gas_limit = true; env.block.gas_limit = U256::MAX; - let mut executor = - TracingExecutor::new(env, fork, evm_version, debug, decode_internal, alphanet); + let mut executor = TracingExecutor::new( + env, + fork, + evm_version, + debug, + decode_internal, + false, + alphanet, + ); let value = tx.value.unwrap_or_default(); let input = tx.inner.input.into_input().unwrap_or_default(); @@ -200,7 +207,8 @@ impl CallArgs { ), }; - handle_traces(trace, &config, chain, labels, debug, decode_internal, false).await?; + handle_traces(trace, &config, chain, labels, debug, decode_internal, false, false) + .await?; return Ok(()); } diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 7d7c922b4b6d..1932ba428779 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -52,6 +52,14 @@ pub struct RunArgs { #[arg(long, short)] verbose: bool, + /// Prints the trace in JSON format. + #[arg(long, short)] + json: bool, + + /// Prints the state changes, only works with the `json` flag. + #[arg(long)] + with_state_changes: bool, + /// Label addresses in the trace. /// /// Example: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045:vitalik.eth @@ -163,6 +171,7 @@ impl RunArgs { evm_version, self.debug, self.decode_internal, + self.with_state_changes, alphanet, ); let mut env = @@ -177,15 +186,15 @@ impl RunArgs { pb.set_position(0); let BlockTransactions::Full(ref txs) = block.transactions else { - return Err(eyre::eyre!("Could not get block txs")) + return Err(eyre::eyre!("Could not get block txs")); }; for (index, tx) in txs.iter().enumerate() { // System transactions such as on L2s don't contain any pricing info so // we skip them otherwise this would cause // reverts - if is_known_system_sender(tx.from) || - tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) + if is_known_system_sender(tx.from) + || tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) { pb.set_position((index + 1) as u64); continue; @@ -250,6 +259,7 @@ impl RunArgs { self.debug, self.decode_internal, self.verbose, + self.json, ) .await?; diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 8a4bff729410..1d78cb09a873 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -17,8 +17,7 @@ use foundry_evm::{ debug::DebugTraceIdentifier, decode_trace_arena, identifier::{EtherscanIdentifier, SignaturesIdentifier}, - render_trace_arena_with_bytecodes, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, - Traces, + render_trace_arena_inner, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, Traces, }, }; use std::{ @@ -164,22 +163,22 @@ pub fn has_different_gas_calc(chain_id: u64) -> bool { if let Some(chain) = Chain::from(chain_id).named() { return matches!( chain, - NamedChain::Acala | - NamedChain::AcalaMandalaTestnet | - NamedChain::AcalaTestnet | - NamedChain::Arbitrum | - NamedChain::ArbitrumGoerli | - NamedChain::ArbitrumSepolia | - NamedChain::ArbitrumTestnet | - NamedChain::Karura | - NamedChain::KaruraTestnet | - NamedChain::Mantle | - NamedChain::MantleSepolia | - NamedChain::MantleTestnet | - NamedChain::Moonbase | - NamedChain::Moonbeam | - NamedChain::MoonbeamDev | - NamedChain::Moonriver + NamedChain::Acala + | NamedChain::AcalaMandalaTestnet + | NamedChain::AcalaTestnet + | NamedChain::Arbitrum + | NamedChain::ArbitrumGoerli + | NamedChain::ArbitrumSepolia + | NamedChain::ArbitrumTestnet + | NamedChain::Karura + | NamedChain::KaruraTestnet + | NamedChain::Mantle + | NamedChain::MantleSepolia + | NamedChain::MantleTestnet + | NamedChain::Moonbase + | NamedChain::Moonbeam + | NamedChain::MoonbeamDev + | NamedChain::Moonriver ); } false @@ -190,10 +189,10 @@ pub fn has_batch_support(chain_id: u64) -> bool { if let Some(chain) = Chain::from(chain_id).named() { return !matches!( chain, - NamedChain::Arbitrum | - NamedChain::ArbitrumTestnet | - NamedChain::ArbitrumGoerli | - NamedChain::ArbitrumSepolia + NamedChain::Arbitrum + | NamedChain::ArbitrumTestnet + | NamedChain::ArbitrumGoerli + | NamedChain::ArbitrumSepolia ); } true @@ -363,6 +362,7 @@ pub async fn handle_traces( debug: bool, decode_internal: bool, verbose: bool, + json: bool, ) -> Result<()> { let labels = labels.iter().filter_map(|label_str| { let mut iter = label_str.split(':'); @@ -412,7 +412,7 @@ pub async fn handle_traces( .build(); debugger.try_run()?; } else { - print_traces(&mut result, &decoder, verbose).await?; + print_traces(&mut result, &decoder, verbose, json).await?; } Ok(()) @@ -422,14 +422,23 @@ pub async fn print_traces( result: &mut TraceResult, decoder: &CallTraceDecoder, verbose: bool, + json: bool, ) -> Result<()> { let traces = result.traces.as_mut().expect("No traces found"); - println!("Traces:"); + if !json { + println!("Traces:"); + } + for (_, arena) in traces { decode_trace_arena(arena, decoder).await?; - println!("{}", render_trace_arena_with_bytecodes(arena, verbose)); + println!("{}", render_trace_arena_inner(arena, verbose, json)); } + + if json { + return Ok(()); + } + println!(); if result.success { diff --git a/crates/evm/evm/src/executors/trace.rs b/crates/evm/evm/src/executors/trace.rs index 69c68442b65c..ceea6e67248a 100644 --- a/crates/evm/evm/src/executors/trace.rs +++ b/crates/evm/evm/src/executors/trace.rs @@ -18,15 +18,18 @@ impl TracingExecutor { version: Option, debug: bool, decode_internal: bool, + with_state_changes: bool, alphanet: bool, ) -> Self { let db = Backend::spawn(fork); - let trace_mode = - TraceMode::Call.with_debug(debug).with_decode_internal(if decode_internal { + let trace_mode = TraceMode::Call + .with_debug(debug) + .with_decode_internal(if decode_internal { InternalTraceMode::Full } else { InternalTraceMode::None - }); + }) + .with_state_changes(with_state_changes); Self { // configures a bare version of the evm executor: no cheatcode inspector is enabled, // tracing will be enabled only for the targeted transaction diff --git a/crates/evm/traces/Cargo.toml b/crates/evm/traces/Cargo.toml index 96fb8d1c6dc0..7a6f7fe00067 100644 --- a/crates/evm/traces/Cargo.toml +++ b/crates/evm/traces/Cargo.toml @@ -36,6 +36,7 @@ eyre.workspace = true futures.workspace = true itertools.workspace = true serde.workspace = true +serde_json.workspace = true tokio = { workspace = true, features = ["time", "macros"] } tracing.workspace = true rustc-hash.workspace = true diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index dd4a8966481a..3382e3905ace 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -180,14 +180,18 @@ pub async fn decode_trace_arena( /// Render a collection of call traces to a string. pub fn render_trace_arena(arena: &SparsedTraceArena) -> String { - render_trace_arena_with_bytecodes(arena, false) + render_trace_arena_inner(arena, false, false) } -/// Render a collection of call traces to a string optionally including contract creation bytecodes. -pub fn render_trace_arena_with_bytecodes( +/// Render a collection of call traces to a string optionally including contract creation bytecodes and in JSON format. +pub fn render_trace_arena_inner( arena: &SparsedTraceArena, with_bytecodes: bool, + as_json: bool, ) -> String { + if as_json { + return serde_json::to_string(&arena.resolve_arena()).expect("Failed to write traces"); + } let mut w = TraceWriter::new(Vec::::new()).write_bytecodes(with_bytecodes); w.write_arena(&arena.resolve_arena()).expect("Failed to write traces"); String::from_utf8(w.into_writer()).expect("trace writer wrote invalid UTF-8") @@ -286,6 +290,8 @@ pub enum TraceMode { /// /// Used by debugger. Debug, + /// Debug trace with storage changes. + RecordStateDiff, } impl TraceMode { @@ -305,6 +311,10 @@ impl TraceMode { matches!(self, Self::Jump) } + pub const fn record_state_diff(self) -> bool { + matches!(self, Self::RecordStateDiff) + } + pub const fn is_debug(self) -> bool { matches!(self, Self::Debug) } @@ -321,6 +331,14 @@ impl TraceMode { std::cmp::max(self, mode.into()) } + pub fn with_state_changes(self, yes: bool) -> Self { + if yes { + std::cmp::max(self, Self::RecordStateDiff) + } else { + self + } + } + pub fn with_verbosity(self, verbosiy: u8) -> Self { if verbosiy >= 3 { std::cmp::max(self, Self::Call) @@ -342,7 +360,7 @@ impl TraceMode { StackSnapshotType::None }, record_logs: true, - record_state_diff: false, + record_state_diff: self.record_state_diff(), record_returndata_snapshots: self.is_debug(), record_opcodes_filter: (self.is_jump() || self.is_jump_simple()) .then(|| OpcodeFilter::new().enabled(OpCode::JUMP).enabled(OpCode::JUMPDEST)), From 554657515fff310bc5224b3bbf587cf8e8be8a7b Mon Sep 17 00:00:00 2001 From: chen Date: Thu, 3 Oct 2024 16:55:23 +0800 Subject: [PATCH 2/6] fix test --- Cargo.lock | 1 - crates/verify/src/utils.rs | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 875209c9dbac..70ea8bef4cab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4088,7 +4088,6 @@ dependencies = [ "revm-inspectors", "rustc-hash", "serde", - "serde_json", "solang-parser", "tempfile", "tokio", diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index aaf8a0e016b7..16405a537439 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -120,15 +120,15 @@ pub fn build_using_cache( // Check if Solidity version matches if let Ok(version) = Version::parse(&version) { - if !(artifact.version.major == version.major && - artifact.version.minor == version.minor && - artifact.version.patch == version.patch) + if !(artifact.version.major == version.major + && artifact.version.minor == version.minor + && artifact.version.patch == version.patch) { continue; } } - return Ok(artifact.artifact) + return Ok(artifact.artifact); } } } @@ -189,7 +189,7 @@ fn is_partial_match( // 1. Check length of constructor args if constructor_args.is_empty() || is_runtime { // Assume metadata is at the end of the bytecode - return try_extract_and_compare_bytecode(local_bytecode, bytecode) + return try_extract_and_compare_bytecode(local_bytecode, bytecode); } // If not runtime, extract constructor args from the end of the bytecode @@ -340,6 +340,7 @@ pub async fn get_tracing_executor( Some(fork_config.evm_version), false, false, + false, is_alphanet, ); From 28ef6a9a06d14ebf6c34c879773d0bec3627fec9 Mon Sep 17 00:00:00 2001 From: chen Date: Thu, 3 Oct 2024 17:12:18 +0800 Subject: [PATCH 3/6] add back serde_json in Cargo.lock --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index 70ea8bef4cab..875209c9dbac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4088,6 +4088,7 @@ dependencies = [ "revm-inspectors", "rustc-hash", "serde", + "serde_json", "solang-parser", "tempfile", "tokio", From 99a691482afd849e645a44a4601c1fd5ac250b46 Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 4 Oct 2024 10:30:11 +0800 Subject: [PATCH 4/6] format using nightly --- crates/cast/bin/cmd/run.rs | 6 ++--- crates/cli/src/utils/cmd.rs | 45 +++++++++++++++++------------------- crates/evm/traces/src/lib.rs | 3 ++- crates/verify/src/utils.rs | 10 ++++---- 4 files changed, 31 insertions(+), 33 deletions(-) diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 1932ba428779..7a4c01efc414 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -186,15 +186,15 @@ impl RunArgs { pb.set_position(0); let BlockTransactions::Full(ref txs) = block.transactions else { - return Err(eyre::eyre!("Could not get block txs")); + return Err(eyre::eyre!("Could not get block txs")) }; for (index, tx) in txs.iter().enumerate() { // System transactions such as on L2s don't contain any pricing info so // we skip them otherwise this would cause // reverts - if is_known_system_sender(tx.from) - || tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) + if is_known_system_sender(tx.from) || + tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) { pb.set_position((index + 1) as u64); continue; diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 1d78cb09a873..a5067664d1fe 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -163,22 +163,22 @@ pub fn has_different_gas_calc(chain_id: u64) -> bool { if let Some(chain) = Chain::from(chain_id).named() { return matches!( chain, - NamedChain::Acala - | NamedChain::AcalaMandalaTestnet - | NamedChain::AcalaTestnet - | NamedChain::Arbitrum - | NamedChain::ArbitrumGoerli - | NamedChain::ArbitrumSepolia - | NamedChain::ArbitrumTestnet - | NamedChain::Karura - | NamedChain::KaruraTestnet - | NamedChain::Mantle - | NamedChain::MantleSepolia - | NamedChain::MantleTestnet - | NamedChain::Moonbase - | NamedChain::Moonbeam - | NamedChain::MoonbeamDev - | NamedChain::Moonriver + NamedChain::Acala | + NamedChain::AcalaMandalaTestnet | + NamedChain::AcalaTestnet | + NamedChain::Arbitrum | + NamedChain::ArbitrumGoerli | + NamedChain::ArbitrumSepolia | + NamedChain::ArbitrumTestnet | + NamedChain::Karura | + NamedChain::KaruraTestnet | + NamedChain::Mantle | + NamedChain::MantleSepolia | + NamedChain::MantleTestnet | + NamedChain::Moonbase | + NamedChain::Moonbeam | + NamedChain::MoonbeamDev | + NamedChain::Moonriver ); } false @@ -189,10 +189,10 @@ pub fn has_batch_support(chain_id: u64) -> bool { if let Some(chain) = Chain::from(chain_id).named() { return !matches!( chain, - NamedChain::Arbitrum - | NamedChain::ArbitrumTestnet - | NamedChain::ArbitrumGoerli - | NamedChain::ArbitrumSepolia + NamedChain::Arbitrum | + NamedChain::ArbitrumTestnet | + NamedChain::ArbitrumGoerli | + NamedChain::ArbitrumSepolia ); } true @@ -426,10 +426,7 @@ pub async fn print_traces( ) -> Result<()> { let traces = result.traces.as_mut().expect("No traces found"); - if !json { - println!("Traces:"); - } - + println!("Traces:"); for (_, arena) in traces { decode_trace_arena(arena, decoder).await?; println!("{}", render_trace_arena_inner(arena, verbose, json)); diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 3382e3905ace..281ec780df3d 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -183,7 +183,8 @@ pub fn render_trace_arena(arena: &SparsedTraceArena) -> String { render_trace_arena_inner(arena, false, false) } -/// Render a collection of call traces to a string optionally including contract creation bytecodes and in JSON format. +/// Render a collection of call traces to a string optionally including contract creation bytecodes +/// and in JSON format. pub fn render_trace_arena_inner( arena: &SparsedTraceArena, with_bytecodes: bool, diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index 16405a537439..60bcddf36b76 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -120,15 +120,15 @@ pub fn build_using_cache( // Check if Solidity version matches if let Ok(version) = Version::parse(&version) { - if !(artifact.version.major == version.major - && artifact.version.minor == version.minor - && artifact.version.patch == version.patch) + if !(artifact.version.major == version.major && + artifact.version.minor == version.minor && + artifact.version.patch == version.patch) { continue; } } - return Ok(artifact.artifact); + return Ok(artifact.artifact) } } } @@ -189,7 +189,7 @@ fn is_partial_match( // 1. Check length of constructor args if constructor_args.is_empty() || is_runtime { // Assume metadata is at the end of the bytecode - return try_extract_and_compare_bytecode(local_bytecode, bytecode); + return try_extract_and_compare_bytecode(local_bytecode, bytecode) } // If not runtime, extract constructor args from the end of the bytecode From c6ca2b6f8c622992bd4fc06c11eed53cdc224b83 Mon Sep 17 00:00:00 2001 From: chen Date: Fri, 4 Oct 2024 10:54:22 +0800 Subject: [PATCH 5/6] rename parameter --- crates/evm/traces/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 281ec780df3d..58da18f505cb 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -188,11 +188,12 @@ pub fn render_trace_arena(arena: &SparsedTraceArena) -> String { pub fn render_trace_arena_inner( arena: &SparsedTraceArena, with_bytecodes: bool, - as_json: bool, + to_json: bool, ) -> String { - if as_json { + if to_json { return serde_json::to_string(&arena.resolve_arena()).expect("Failed to write traces"); } + let mut w = TraceWriter::new(Vec::::new()).write_bytecodes(with_bytecodes); w.write_arena(&arena.resolve_arena()).expect("Failed to write traces"); String::from_utf8(w.into_writer()).expect("trace writer wrote invalid UTF-8") From 68f58873b36cb5979d0df6ff779977fff2ae1710 Mon Sep 17 00:00:00 2001 From: chen Date: Mon, 7 Oct 2024 14:26:44 +0800 Subject: [PATCH 6/6] update revm-inspectors --- Cargo.lock | 3 +-- Cargo.toml | 3 ++- crates/cast/bin/cmd/call.rs | 14 ++++++++++++-- crates/cast/bin/cmd/run.rs | 1 + crates/cli/src/utils/cmd.rs | 6 ++++-- crates/evm/traces/src/lib.rs | 7 +++++-- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 875209c9dbac..58233d21087e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7247,8 +7247,7 @@ dependencies = [ [[package]] name = "revm-inspectors" version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c44af0bf801f48d25f7baf25cf72aff4c02d610f83b428175228162fef0246" +source = "git+https://github.com/paradigmxyz/revm-inspectors.git?rev=3c079514cdc39cf95ddb42816a841fd55c16c3b7#3c079514cdc39cf95ddb42816a841fd55c16c3b7" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth 0.4.0", diff --git a/Cargo.toml b/Cargo.toml index e6ccd75bd3ae..7565058c2802 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -174,7 +174,8 @@ solang-parser = "=0.3.3" ## revm revm = { version = "14.0.3", default-features = false } revm-primitives = { version = "10.0.0", default-features = false } -revm-inspectors = { version = "0.8.0", features = ["serde"] } +# Update this after the PR https://github.com/paradigmxyz/revm-inspectors/pull/213 is merged +revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors.git", rev="3c079514cdc39cf95ddb42816a841fd55c16c3b7", features = ["serde"] } ## ethers ethers-contract-abigen = { version = "2.0.14", default-features = false } diff --git a/crates/cast/bin/cmd/call.rs b/crates/cast/bin/cmd/call.rs index 9914c6d7362c..534bae2d6055 100644 --- a/crates/cast/bin/cmd/call.rs +++ b/crates/cast/bin/cmd/call.rs @@ -207,8 +207,18 @@ impl CallArgs { ), }; - handle_traces(trace, &config, chain, labels, debug, decode_internal, false, false) - .await?; + handle_traces( + trace, + &config, + chain, + labels, + debug, + decode_internal, + false, + false, + false, + ) + .await?; return Ok(()); } diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 7a4c01efc414..bef2723af266 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -260,6 +260,7 @@ impl RunArgs { self.decode_internal, self.verbose, self.json, + self.with_state_changes, ) .await?; diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index a5067664d1fe..8c6fe8482ef4 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -363,6 +363,7 @@ pub async fn handle_traces( decode_internal: bool, verbose: bool, json: bool, + with_state_changes: bool, ) -> Result<()> { let labels = labels.iter().filter_map(|label_str| { let mut iter = label_str.split(':'); @@ -412,7 +413,7 @@ pub async fn handle_traces( .build(); debugger.try_run()?; } else { - print_traces(&mut result, &decoder, verbose, json).await?; + print_traces(&mut result, &decoder, verbose, json, with_state_changes).await?; } Ok(()) @@ -423,13 +424,14 @@ pub async fn print_traces( decoder: &CallTraceDecoder, verbose: bool, json: bool, + state_changes: bool, ) -> Result<()> { let traces = result.traces.as_mut().expect("No traces found"); println!("Traces:"); for (_, arena) in traces { decode_trace_arena(arena, decoder).await?; - println!("{}", render_trace_arena_inner(arena, verbose, json)); + println!("{}", render_trace_arena_inner(arena, verbose, json, state_changes)); } if json { diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 58da18f505cb..699989cb607f 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -180,7 +180,7 @@ pub async fn decode_trace_arena( /// Render a collection of call traces to a string. pub fn render_trace_arena(arena: &SparsedTraceArena) -> String { - render_trace_arena_inner(arena, false, false) + render_trace_arena_inner(arena, false, false, false) } /// Render a collection of call traces to a string optionally including contract creation bytecodes @@ -189,12 +189,15 @@ pub fn render_trace_arena_inner( arena: &SparsedTraceArena, with_bytecodes: bool, to_json: bool, + with_storage_changes: bool, ) -> String { if to_json { return serde_json::to_string(&arena.resolve_arena()).expect("Failed to write traces"); } - let mut w = TraceWriter::new(Vec::::new()).write_bytecodes(with_bytecodes); + let mut w = TraceWriter::new(Vec::::new()) + .write_bytecodes(with_bytecodes) + .with_storage_changes(with_storage_changes); w.write_arena(&arena.resolve_arena()).expect("Failed to write traces"); String::from_utf8(w.into_writer()).expect("trace writer wrote invalid UTF-8") }