Skip to content
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
1 change: 1 addition & 0 deletions crates/cast/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,7 @@ pub async fn run_command(args: CastArgs) -> Result<()> {
CastSubcommand::DAEstimate(cmd) => {
cmd.run().await?;
}
CastSubcommand::Trace(cmd) => cmd.run().await?,
};

/// Prints slice of tokens using [`format_tokens`] or [`serialize_value_as_json`] depending
Expand Down
1 change: 1 addition & 0 deletions crates/cast/src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ pub mod rpc;
pub mod run;
pub mod send;
pub mod storage;
pub mod trace;
pub mod txpool;
pub mod wallet;
91 changes: 91 additions & 0 deletions crates/cast/src/cmd/trace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use alloy_eips::Encodable2718;
use alloy_network::AnyRpcTransaction;
use alloy_primitives::hex;
use alloy_provider::ext::TraceApi;
use clap::Parser;
use eyre::Result;
use foundry_cli::{
opts::RpcOpts,
utils::{self, LoadConfig},
};
use foundry_common::stdin;
use op_alloy_consensus::OpTxEnvelope;

/// CLI arguments for `cast trace`.
#[derive(Debug, Parser)]
pub struct TraceArgs {
/// Transaction hash (for trace_transaction) or raw tx hex/JSON (for trace_rawTransaction
/// with --raw)
tx: Option<String>,

/// Use trace_rawTransaction instead of trace_transaction.
/// Required when passing raw transaction hex or JSON instead of a tx hash.
#[arg(long)]
raw: bool,

/// Include the basic trace of the transaction.
#[arg(long, requires = "raw")]
trace: bool,

/// Include the full trace of the virtual machine's state during transaction execution
#[arg(long, requires = "raw")]
vm_trace: bool,

/// Include state changes caused by the transaction (requires --raw).
#[arg(long, requires = "raw")]
state_diff: bool,

#[command(flatten)]
rpc: RpcOpts,
}

impl TraceArgs {
pub async fn run(self) -> Result<()> {
let config = self.rpc.load_config()?;
let provider = utils::get_provider(&config)?;
let input = stdin::unwrap_line(self.tx)?;

let trimmed = input.trim();
let is_json = trimmed.starts_with('{');
let is_raw_hex = trimmed.starts_with("0x") && trimmed.len() > 66;

let result = if self.raw {
// trace_rawTransaction: accepts raw hex OR JSON tx
let raw_bytes = if is_raw_hex {
hex::decode(trimmed.strip_prefix("0x").unwrap_or(trimmed))?
} else if is_json {
let tx: AnyRpcTransaction = serde_json::from_str(trimmed)?;
let envelope = tx.try_into_either::<OpTxEnvelope>()?;
envelope.encoded_2718().to_vec()
} else {
hex::decode(trimmed)?
};

let mut trace_builder = provider.trace_raw_transaction(&raw_bytes);

if self.trace {
trace_builder = trace_builder.trace();
}
if self.vm_trace {
trace_builder = trace_builder.vm_trace();
}
if self.state_diff {
trace_builder = trace_builder.state_diff();
}

if trace_builder.get_trace_types().map(|t| t.is_empty()).unwrap_or(true) {
eyre::bail!("No trace type specified. Use --trace, --vm-trace, or --state-diff");
}

serde_json::to_string_pretty(&trace_builder.await?)?
} else {
// trace_transaction: use tx hash directly
let hash = input.parse()?;
let traces = provider.trace_transaction(hash).await?;
serde_json::to_string_pretty(&traces)?
};

sh_println!("{}", result)?;
Ok(())
}
}
4 changes: 3 additions & 1 deletion crates/cast/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::cmd::{
creation_code::CreationCodeArgs, da_estimate::DAEstimateArgs, erc20::Erc20Subcommand,
estimate::EstimateArgs, find_block::FindBlockArgs, interface::InterfaceArgs, logs::LogsArgs,
mktx::MakeTxArgs, rpc::RpcArgs, run::RunArgs, send::SendTxArgs, storage::StorageArgs,
txpool::TxPoolSubcommands, wallet::WalletSubcommands,
trace::TraceArgs, txpool::TxPoolSubcommands, wallet::WalletSubcommands,
};
use alloy_ens::NameOrAddress;
use alloy_primitives::{Address, B256, Selector, U256};
Expand Down Expand Up @@ -1146,6 +1146,8 @@ pub enum CastSubcommand {
#[command(subcommand)]
command: Erc20Subcommand,
},
#[command(name = "trace")]
Trace(TraceArgs),
}

/// CLI arguments for `cast --to-base`.
Expand Down