ic_web3_rs/types/
traces.rs

1//! Types for the Parity Ad-Hoc Trace API
2
3use crate::types::{Action, ActionType, Bytes, Res, H160, H256, U256};
4use serde::{Deserialize, Serialize};
5use std::collections::BTreeMap;
6
7#[derive(Debug, Clone, Serialize)]
8/// Description of the type of trace to make
9pub enum TraceType {
10    /// Transaction Trace
11    #[serde(rename = "trace")]
12    Trace,
13    /// Virtual Machine Execution Trace
14    #[serde(rename = "vmTrace")]
15    VmTrace,
16    /// State Difference
17    #[serde(rename = "stateDiff")]
18    StateDiff,
19}
20
21#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
22/// Ad-Hoc trace API type
23pub struct BlockTrace {
24    /// Output Bytes
25    pub output: Bytes,
26    /// Transaction Trace
27    pub trace: Option<Vec<TransactionTrace>>,
28    /// Virtual Machine Execution Trace
29    #[serde(rename = "vmTrace")]
30    pub vm_trace: Option<VMTrace>,
31    /// State Difference
32    #[serde(rename = "stateDiff")]
33    pub state_diff: Option<StateDiff>,
34    /// Transaction Hash
35    #[serde(rename = "transactionHash")]
36    pub transaction_hash: Option<H256>,
37}
38
39//---------------- State Diff ----------------
40/// Aux type for Diff::Changed.
41#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
42pub struct ChangedType<T> {
43    /// Previous value.
44    pub from: T,
45    /// Current value.
46    pub to: T,
47}
48
49/// Serde-friendly `Diff` shadow.
50#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
51pub enum Diff<T> {
52    /// No change.
53    #[serde(rename = "=")]
54    Same,
55    /// A new value has been set.
56    #[serde(rename = "+")]
57    Born(T),
58    /// A value has been removed.
59    #[serde(rename = "-")]
60    Died(T),
61    /// Value changed.
62    #[serde(rename = "*")]
63    Changed(ChangedType<T>),
64}
65
66/// Serde-friendly `AccountDiff` shadow.
67#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
68pub struct AccountDiff {
69    /// Account balance.
70    pub balance: Diff<U256>,
71    /// Account nonce.
72    pub nonce: Diff<U256>,
73    /// Account code.
74    pub code: Diff<Bytes>,
75    /// Account storage.
76    pub storage: BTreeMap<H256, Diff<H256>>,
77}
78
79/// Serde-friendly `StateDiff` shadow.
80#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
81pub struct StateDiff(pub BTreeMap<H160, AccountDiff>);
82
83// ------------------ Trace -------------
84/// Trace
85#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
86pub struct TransactionTrace {
87    /// Trace address
88    #[serde(rename = "traceAddress")]
89    pub trace_address: Vec<usize>,
90    /// Subtraces
91    pub subtraces: usize,
92    /// Action
93    pub action: Action,
94    /// Action Type
95    #[serde(rename = "type")]
96    pub action_type: ActionType,
97    /// Result
98    pub result: Option<Res>,
99    /// Error
100    pub error: Option<String>,
101}
102
103// ---------------- VmTrace ------------------------------
104#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
105/// A record of a full VM trace for a CALL/CREATE.
106pub struct VMTrace {
107    /// The code to be executed.
108    pub code: Bytes,
109    /// The operations executed.
110    pub ops: Vec<VMOperation>,
111}
112
113#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
114/// A record of the execution of a single VM operation.
115pub struct VMOperation {
116    /// The program counter.
117    pub pc: usize,
118    /// The gas cost for this instruction.
119    pub cost: u64,
120    /// Information concerning the execution of the operation.
121    pub ex: Option<VMExecutedOperation>,
122    /// Subordinate trace of the CALL/CREATE if applicable.
123    // #[serde(bound="VMTrace: Deserialize")]
124    pub sub: Option<VMTrace>,
125}
126
127#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
128/// A record of an executed VM operation.
129pub struct VMExecutedOperation {
130    /// The total gas used.
131    #[serde(rename = "used")]
132    pub used: u64,
133    /// The stack item placed, if any.
134    pub push: Vec<U256>,
135    /// If altered, the memory delta.
136    #[serde(rename = "mem")]
137    pub mem: Option<MemoryDiff>,
138    /// The altered storage value, if any.
139    #[serde(rename = "store")]
140    pub store: Option<StorageDiff>,
141}
142
143#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
144/// A diff of some chunk of memory.
145pub struct MemoryDiff {
146    /// Offset into memory the change begins.
147    pub off: usize,
148    /// The changed data.
149    pub data: Bytes,
150}
151
152#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
153/// A diff of some storage value.
154pub struct StorageDiff {
155    /// Which key in storage is changed.
156    pub key: U256,
157    /// What the value has been changed to.
158    pub val: U256,
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    // tx: https://etherscan.io/tx/0x4a91b11dbd2b11c308cfe7775eac2036f20c501691e3f8005d83b2dcce62d6b5
166    // using the 'trace_replayTransaction' API function
167    // with 'trace', 'vmTrace', 'stateDiff'
168    const EXAMPLE_TRACE: &str = include!("./example-trace-str.rs");
169
170    // block: https://etherscan.io/block/46147
171    // using the 'trace_replayBlockTransactions' API function
172    // with 'trace', 'vmTrace', 'stateDiff'
173    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}