tycho_simulation/evm/traces/
mod.rs

1mod config;
2mod decoder;
3mod etherscan;
4mod renderer;
5mod signatures;
6
7// Private imports for internal use only
8use config::TraceConfig;
9use decoder::CallTraceDecoder;
10use renderer::render_trace_arena;
11// Re-export only what's needed by simulation.rs
12use revm_inspectors::tracing::CallTraceArena;
13pub use signatures::SignaturesIdentifier;
14
15/// Type alias for the traces collection (internal use only)
16type Traces = Vec<CallTraceArena>;
17
18/// A slimmed down return from the executor used for returning minimal trace + gas metering info
19#[derive(Debug, Clone)]
20pub(crate) struct TraceResult {
21    pub success: bool,
22    pub traces: Option<Traces>,
23    pub gas_used: u64,
24}
25
26/// Handle traces with Etherscan & 4Byte identification and pretty printing
27/// This is the main public function used by SimulationEngine
28pub(crate) async fn handle_traces(
29    mut result: TraceResult,
30    etherscan_api_key: Option<String>,
31    chain: tycho_common::models::Chain,
32) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
33    let offline = etherscan_api_key.is_none();
34    let trace_config = TraceConfig::new(chain)
35        .with_etherscan_api_key(etherscan_api_key.unwrap_or_default())
36        .with_offline(offline);
37
38    let mut decoder = CallTraceDecoder::with_config(&trace_config).await?;
39
40    // Decode traces
41    if let Some(traces) = result.traces.as_mut() {
42        for arena in traces {
43            decoder.decode_arena(arena).await?;
44        }
45    }
46
47    print_traces(&mut result, &decoder).await?;
48
49    Ok(())
50}
51
52/// Print decoded traces to console (internal use only)
53async fn print_traces(
54    result: &mut TraceResult,
55    _decoder: &CallTraceDecoder, // Decoder already applied in handle_traces
56) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
57    let traces = result
58        .traces
59        .as_ref()
60        .ok_or_else(|| std::io::Error::other("No traces found"))?;
61
62    println!("Traces:");
63    for arena in traces {
64        let rendered = render_trace_arena(arena);
65        println!("{}", rendered);
66    }
67    println!();
68
69    if result.success {
70        println!("Transaction successfully executed.");
71    } else {
72        println!("Transaction failed.");
73    }
74
75    println!("Gas used: {gas}", gas = result.gas_used);
76    Ok(())
77}