Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options for state changes output and json output in cast run command #9013

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one was merged

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it hasn't been included in the lastest release of revm-inspectors, should we wait for the next release first?

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 }
Expand Down
24 changes: 21 additions & 3 deletions crates/cast/bin/cmd/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -200,7 +207,18 @@ impl CallArgs {
),
};

handle_traces(trace, &config, chain, labels, debug, decode_internal, false).await?;
handle_traces(
trace,
&config,
chain,
labels,
debug,
decode_internal,
false,
false,
false,
)
.await?;

return Ok(());
}
Expand Down
11 changes: 11 additions & 0 deletions crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
cassc marked this conversation as resolved.
Show resolved Hide resolved

/// Label addresses in the trace.
///
/// Example: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045:vitalik.eth
Expand Down Expand Up @@ -163,6 +171,7 @@ impl RunArgs {
evm_version,
self.debug,
self.decode_internal,
self.with_state_changes,
alphanet,
);
let mut env =
Expand Down Expand Up @@ -250,6 +259,8 @@ impl RunArgs {
self.debug,
self.decode_internal,
self.verbose,
self.json,
self.with_state_changes,
)
.await?;

Expand Down
16 changes: 12 additions & 4 deletions crates/cli/src/utils/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -363,6 +362,8 @@ pub async fn handle_traces(
debug: bool,
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(':');
Expand Down Expand Up @@ -412,7 +413,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, with_state_changes).await?;
}

Ok(())
Expand All @@ -422,14 +423,21 @@ pub async fn print_traces(
result: &mut TraceResult,
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_with_bytecodes(arena, verbose));
println!("{}", render_trace_arena_inner(arena, verbose, json, state_changes));
}

if json {
return Ok(());
}

println!();

if result.success {
Expand Down
9 changes: 6 additions & 3 deletions crates/evm/evm/src/executors/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ impl TracingExecutor {
version: Option<EvmVersion>,
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
Expand Down
1 change: 1 addition & 0 deletions crates/evm/traces/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 28 additions & 5 deletions crates/evm/traces/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,15 +180,24 @@ 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, 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,
to_json: bool,
with_storage_changes: bool,
) -> String {
let mut w = TraceWriter::new(Vec::<u8>::new()).write_bytecodes(with_bytecodes);
if to_json {
return serde_json::to_string(&arena.resolve_arena()).expect("Failed to write traces");
}

let mut w = TraceWriter::new(Vec::<u8>::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")
}
Expand Down Expand Up @@ -286,6 +295,8 @@ pub enum TraceMode {
///
/// Used by debugger.
Debug,
/// Debug trace with storage changes.
RecordStateDiff,
}

impl TraceMode {
Expand All @@ -305,6 +316,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)
}
Expand All @@ -321,6 +336,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)
Expand All @@ -342,7 +365,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)),
Expand Down
1 change: 1 addition & 0 deletions crates/verify/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ pub async fn get_tracing_executor(
Some(fork_config.evm_version),
false,
false,
false,
is_alphanet,
);

Expand Down
Loading