diff --git a/crates/rpc/rpc-types/src/eth/trace/common.rs b/crates/rpc/rpc-types/src/eth/trace/common.rs index 78ee088ce..617b44850 100644 --- a/crates/rpc/rpc-types/src/eth/trace/common.rs +++ b/crates/rpc/rpc-types/src/eth/trace/common.rs @@ -1,14 +1,36 @@ //! Types used by tracing backends +use alloy_primitives::TxHash; use serde::{Deserialize, Serialize}; /// The result of a single transaction trace. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -#[allow(missing_docs)] +#[serde(untagged, rename_all = "camelCase")] pub enum TraceResult { /// Untagged success variant - Success { result: Ok }, + Success { + /// Trace results produced by the tracer + result: Ok, + /// transaction hash + #[serde(skip_serializing_if = "Option::is_none")] + tx_hash: Option, + }, /// Untagged error variant - Error { error: Err }, + Error { + /// Trace failure produced by the tracer + error: Err, + /// transaction hash + #[serde(skip_serializing_if = "Option::is_none")] + tx_hash: Option, + }, +} + +impl TraceResult { + /// Returns the hash of the transaction that was traced. + pub fn tx_hash(&self) -> Option { + *match self { + TraceResult::Success { tx_hash, .. } => tx_hash, + TraceResult::Error { tx_hash, .. } => tx_hash, + } + } } diff --git a/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs b/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs index a95a3dc2d..d0f92411e 100644 --- a/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs +++ b/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs @@ -559,4 +559,20 @@ mod tests { let input = serde_json::from_str::(s).unwrap(); similar_asserts::assert_eq!(input, val); } + + #[test] + fn test_trace_result_serde() { + let s = r#" { + "result": { + "from": "0xccc5499e15fedaaeaba68aeb79b95b20f725bc56", + "gas": "0x186a0", + "gasUsed": "0xdb91", + "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "input": "0xa9059cbb000000000000000000000000e3f85a274c1edbea2f2498cf5978f41961cf8b5b0000000000000000000000000000000000000000000000000000000068c8f380", + "value": "0x0", + "type": "CALL" + } + }"#; + let _result: TraceResult = serde_json::from_str(s).unwrap(); + } } diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index f520f42e7..b4238e1fd 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -102,12 +102,19 @@ where let mut transactions = transactions.into_iter().peekable(); while let Some(tx) = transactions.next() { + let tx_hash = tx.hash; let tx = tx_env_with_recovered(&tx); let env = Env { cfg: cfg.clone(), block: block_env.clone(), tx }; let (result, state_changes) = - this.trace_transaction(opts.clone(), env, at, &mut db)?; - results.push(TraceResult::Success { result }); + this.trace_transaction(opts.clone(), env, at, &mut db).map_err(|err| { + results.push(TraceResult::Error { + error: err.to_string(), + tx_hash: Some(tx_hash), + }); + err + })?; + results.push(TraceResult::Success { result, tx_hash: Some(tx_hash) }); if transactions.peek().is_some() { // need to apply the state changes of this transaction before executing the // next transaction