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 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9bf8320
Add options for state changes output and json output in cast run command
cassc Oct 3, 2024
dceddb0
Merge remote-tracking branch 'foundry-rs/master' into add-options-to-…
cassc Oct 3, 2024
5546575
fix test
cassc Oct 3, 2024
28ef6a9
add back serde_json in Cargo.lock
cassc Oct 3, 2024
99a6914
format using nightly
cassc Oct 4, 2024
c6ca2b6
rename parameter
cassc Oct 4, 2024
68f5887
update revm-inspectors
cassc Oct 7, 2024
7bad232
Merge remote-tracking branch 'foundry-rs/master' into add-options-to-…
cassc Oct 7, 2024
4b6af4f
Merge remote-tracking branch 'foundry-rs/master' into add-options-to-…
cassc Oct 18, 2024
16da772
Merge remote-tracking branch 'foundry-rs/master' into add-options-to-…
cassc Oct 23, 2024
8b7807c
supress clippy warning and merge master
cassc Oct 23, 2024
5d66616
Merge remote-tracking branch 'foundry-rs/master' into add-options-to-…
cassc Oct 29, 2024
a0143fe
add serde_json
cassc Oct 29, 2024
e041926
disable some stdout print when --json option is used
cassc Nov 4, 2024
b52f8c8
remove unnecessary check
cassc Nov 5, 2024
73b0323
replace with sh_println
cassc Nov 5, 2024
4511b2a
Merge branch 'master' into add-options-to-output-storage-change-and-j…
cassc Nov 7, 2024
e9b1e3e
Merge remote-tracking branch 'foundry-rs/master' into add-options-to-…
cassc Nov 11, 2024
5420f26
Merge remote-tracking branch 'refs/remotes/origin/add-options-to-outp…
cassc Nov 11, 2024
d45b1b8
Merge branch 'master' into add-options-to-output-storage-change-and-j…
cassc Nov 13, 2024
0f983d9
Merge remote-tracking branch 'foundry-rs/master' into add-options-to-…
cassc Nov 15, 2024
9aa2894
Merge remote-tracking branch 'origin/add-options-to-output-storage-ch…
cassc Nov 15, 2024
cb48139
Merge branch 'master' into add-options-to-output-storage-change-and-j…
cassc Nov 18, 2024
f45e4cc
replace with shell::is_json
cassc Nov 19, 2024
af9ee80
Merge branch 'master' into add-options-to-output-storage-change-and-j…
cassc Nov 19, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock

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

24 changes: 21 additions & 3 deletions crates/cast/bin/cmd/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,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 @@ -195,7 +202,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
15 changes: 14 additions & 1 deletion crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ pub struct RunArgs {
#[arg(long)]
quick: bool,

/// Prints the trace in JSON format.
#[arg(long, short)]
json: bool,
cassc marked this conversation as resolved.
Show resolved Hide resolved

/// Prints the state changes
#[arg(long)]
with_state_changes: bool,

/// Label addresses in the trace.
///
/// Example: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045:vitalik.eth
Expand Down Expand Up @@ -162,14 +170,17 @@ impl RunArgs {
evm_version,
self.debug,
self.decode_internal,
self.with_state_changes,
alphanet,
);
let mut env =
EnvWithHandlerCfg::new_with_spec_id(Box::new(env.clone()), executor.spec_id());

// Set the state to the moment right before the transaction
if !self.quick {
sh_println!("Executing previous transactions from the block.")?;
if !self.json {
sh_println!("Executing previous transactions from the block.")?;
}

if let Some(block) = block {
let pb = init_progress(block.transactions.len() as u64, "tx");
Expand Down Expand Up @@ -249,6 +260,8 @@ impl RunArgs {
self.debug,
self.decode_internal,
shell::verbosity() > 0,
self.json,
self.with_state_changes,
)
.await?;

Expand Down
25 changes: 18 additions & 7 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 @@ -379,6 +378,7 @@ impl TryFrom<Result<RawCallResult>> for TraceResult {
}

/// labels the traces, conditionally prints them or opens the debugger
#[allow(clippy::too_many_arguments)]
pub async fn handle_traces(
mut result: TraceResult,
config: &Config,
Expand All @@ -387,6 +387,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 @@ -436,7 +438,7 @@ pub async fn handle_traces(
.build();
debugger.try_run_tui()?;
} else {
print_traces(&mut result, &decoder, verbose).await?;
print_traces(&mut result, &decoder, verbose, json, with_state_changes).await?;
}

Ok(())
Expand All @@ -446,22 +448,31 @@ 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");

sh_println!("Traces:")?;
if !json {
sh_println!("Traces:")?;
}

for (_, arena) in traces {
decode_trace_arena(arena, decoder).await?;
sh_println!("{}", render_trace_arena_with_bytecodes(arena, verbose))?;
sh_println!("{}", render_trace_arena_inner(arena, verbose, json, state_changes))?;
cassc marked this conversation as resolved.
Show resolved Hide resolved
}

if json {
return Ok(());
}
sh_println!()?;

sh_println!()?;
if result.success {
sh_println!("{}", "Transaction successfully executed.".green())?;
} else {
sh_err!("Transaction failed.")?;
}

sh_println!("Gas used: {}", result.gas_used)?;

Ok(())
}
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
tempfile.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 @@ -183,15 +183,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 {
cassc marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -289,6 +298,8 @@ pub enum TraceMode {
///
/// Used by debugger.
Debug,
/// Debug trace with storage changes.
RecordStateDiff,
}

impl TraceMode {
Expand All @@ -308,6 +319,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 @@ -324,6 +339,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 @@ -345,7 +368,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 @@ -334,6 +334,7 @@ pub async fn get_tracing_executor(
Some(fork_config.evm_version),
false,
false,
false,
is_alphanet,
);

Expand Down
Loading