1use crate::types::{Action, ActionType, Bytes, Res, H160, H256, U256};
4use serde::{Deserialize, Serialize};
5use std::collections::BTreeMap;
6
7#[derive(Debug, Clone, Serialize)]
8pub enum TraceType {
10 #[serde(rename = "trace")]
12 Trace,
13 #[serde(rename = "vmTrace")]
15 VmTrace,
16 #[serde(rename = "stateDiff")]
18 StateDiff,
19}
20
21#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
22pub struct BlockTrace {
24 pub output: Bytes,
26 pub trace: Option<Vec<TransactionTrace>>,
28 #[serde(rename = "vmTrace")]
30 pub vm_trace: Option<VMTrace>,
31 #[serde(rename = "stateDiff")]
33 pub state_diff: Option<StateDiff>,
34 #[serde(rename = "transactionHash")]
36 pub transaction_hash: Option<H256>,
37}
38
39#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
42pub struct ChangedType<T> {
43 pub from: T,
45 pub to: T,
47}
48
49#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
51pub enum Diff<T> {
52 #[serde(rename = "=")]
54 Same,
55 #[serde(rename = "+")]
57 Born(T),
58 #[serde(rename = "-")]
60 Died(T),
61 #[serde(rename = "*")]
63 Changed(ChangedType<T>),
64}
65
66#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
68pub struct AccountDiff {
69 pub balance: Diff<U256>,
71 pub nonce: Diff<U256>,
73 pub code: Diff<Bytes>,
75 pub storage: BTreeMap<H256, Diff<H256>>,
77}
78
79#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
81pub struct StateDiff(pub BTreeMap<H160, AccountDiff>);
82
83#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
86pub struct TransactionTrace {
87 #[serde(rename = "traceAddress")]
89 pub trace_address: Vec<usize>,
90 pub subtraces: usize,
92 pub action: Action,
94 #[serde(rename = "type")]
96 pub action_type: ActionType,
97 pub result: Option<Res>,
99 pub error: Option<String>,
101}
102
103#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
105pub struct VMTrace {
107 pub code: Bytes,
109 pub ops: Vec<VMOperation>,
111}
112
113#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
114pub struct VMOperation {
116 pub pc: usize,
118 pub cost: u64,
120 pub ex: Option<VMExecutedOperation>,
122 pub sub: Option<VMTrace>,
125}
126
127#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
128pub struct VMExecutedOperation {
130 #[serde(rename = "used")]
132 pub used: u64,
133 pub push: Vec<U256>,
135 #[serde(rename = "mem")]
137 pub mem: Option<MemoryDiff>,
138 #[serde(rename = "store")]
140 pub store: Option<StorageDiff>,
141}
142
143#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
144pub struct MemoryDiff {
146 pub off: usize,
148 pub data: Bytes,
150}
151
152#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
153pub struct StorageDiff {
155 pub key: U256,
157 pub val: U256,
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 const EXAMPLE_TRACE: &str = include!("./example-trace-str.rs");
169
170 const EXAMPLE_TRACES: &str = include!("./example-traces-str.rs");
174
175 #[test]
176 fn test_serialize_trace_type() {
177 let trace_type_str = r#"["trace","vmTrace","stateDiff"]"#;
178 let trace_type = vec![TraceType::Trace, TraceType::VmTrace, TraceType::StateDiff];
179
180 let se_trace_str: String = serde_json::to_string(&trace_type).unwrap();
181 assert_eq!(trace_type_str, se_trace_str);
182 }
183
184 #[test]
185 fn test_deserialize_blocktrace() {
186 let _trace: BlockTrace = serde_json::from_str(EXAMPLE_TRACE).unwrap();
187 }
188
189 #[test]
190 fn test_deserialize_blocktraces() {
191 let _traces: Vec<BlockTrace> = serde_json::from_str(EXAMPLE_TRACES).unwrap();
192 }
193}