1use alloc::{
19 collections::BTreeMap,
20 string::String,
21 vec::Vec,
22};
23use derive_more::From;
24use ink_primitives::{
25 H160,
26 H256,
27 U256,
28};
29use scale::{
30 Decode,
31 Encode,
32};
33use scale_info::TypeInfo;
34use serde::{
35 Deserialize,
36 Serialize,
37 ser::{
38 SerializeMap,
39 Serializer,
40 },
41};
42
43#[derive(
45 TypeInfo, Default, Encode, Decode, Serialize, Deserialize, Clone, Debug, Eq, PartialEq,
46)]
47#[serde(rename_all = "camelCase")]
48pub struct CallTrace<Gas = U256> {
49 pub from: H160,
51 pub gas: Gas,
53 pub gas_used: Gas,
55 pub to: H160,
57 pub input: Vec<u8>,
59 #[serde(skip_serializing_if = "Vec::is_empty")]
61 pub output: Vec<u8>,
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub error: Option<String>,
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub revert_reason: Option<String>,
68 #[serde(skip_serializing_if = "Vec::is_empty")]
70 pub calls: Vec<CallTrace<Gas>>,
71 #[serde(skip_serializing_if = "Vec::is_empty")]
73 pub logs: Vec<CallLog>,
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub value: Option<U256>,
77 #[serde(rename = "type")]
79 pub call_type: CallType,
80}
81
82#[derive(
84 Debug, Default, Clone, Encode, Decode, TypeInfo, Serialize, Deserialize, Eq, PartialEq,
85)]
86pub struct CallLog {
87 pub address: H160,
89 #[serde(default, skip_serializing_if = "Vec::is_empty")]
91 pub topics: Vec<H256>,
92 pub data: Vec<u8>,
94 #[serde(with = "super::hex_serde")]
97 pub position: u32,
98}
99
100#[derive(
102 Default, TypeInfo, Encode, Decode, Serialize, Deserialize, Eq, PartialEq, Clone, Debug,
103)]
104#[serde(rename_all = "UPPERCASE")]
105pub enum CallType {
106 #[default]
108 Call,
109 StaticCall,
111 DelegateCall,
113 Create,
115 Create2,
117}
118
119#[derive(Clone, Debug, Decode, Serialize, Deserialize, Encode, PartialEq, TypeInfo)]
121#[serde(default, rename_all = "camelCase")]
122pub struct CallTracerConfig {
123 pub with_logs: bool,
125
126 pub only_top_call: bool,
128}
129
130impl Default for CallTracerConfig {
131 fn default() -> Self {
132 Self {
133 with_logs: true,
134 only_top_call: false,
135 }
136 }
137}
138
139#[derive(
141 TypeInfo, From, Encode, Decode, Serialize, Deserialize, Clone, Debug, Eq, PartialEq,
142)]
143#[serde(untagged)]
144pub enum Trace {
145 Call(CallTrace),
147 Prestate(PrestateTrace),
149}
150
151#[derive(
153 TypeInfo, Encode, Decode, Serialize, Deserialize, Clone, Debug, Eq, PartialEq,
154)]
155#[serde(untagged)]
156pub enum PrestateTrace {
157 Prestate(BTreeMap<H160, PrestateTraceInfo>),
159
160 DiffMode {
163 pre: BTreeMap<H160, PrestateTraceInfo>,
168 post: BTreeMap<H160, PrestateTraceInfo>,
172 },
173}
174
175impl PrestateTrace {
176 pub fn state_mut(
178 &mut self,
179 ) -> (
180 &mut BTreeMap<H160, PrestateTraceInfo>,
181 Option<&mut BTreeMap<H160, PrestateTraceInfo>>,
182 ) {
183 match self {
184 PrestateTrace::Prestate(pre) => (pre, None),
185 PrestateTrace::DiffMode { pre, post } => (pre, Some(post)),
186 }
187 }
188}
189
190#[derive(
192 TypeInfo, Default, Encode, Decode, Serialize, Deserialize, Clone, Debug, Eq, PartialEq,
193)]
194pub struct PrestateTraceInfo {
195 #[serde(skip_serializing_if = "Option::is_none")]
197 pub balance: Option<U256>,
198 #[serde(skip_serializing_if = "Option::is_none")]
200 pub nonce: Option<u32>,
201 #[serde(skip_serializing_if = "Option::is_none")]
203 pub code: Option<Vec<u8>>,
204 #[serde(
206 skip_serializing_if = "is_empty",
207 serialize_with = "serialize_map_skip_none"
208 )]
209 pub storage: BTreeMap<Vec<u8>, Option<Vec<u8>>>,
210}
211
212pub fn is_empty<K, V>(map: &BTreeMap<K, Option<V>>) -> bool {
214 !map.values().any(|v| v.is_some())
215}
216
217pub fn serialize_map_skip_none<S, K, V>(
219 map: &BTreeMap<K, Option<V>>,
220 serializer: S,
221) -> Result<S::Ok, S::Error>
222where
223 S: Serializer,
224 K: serde::Serialize,
225 V: serde::Serialize,
226{
227 let len = map.values().filter(|v| v.is_some()).count();
228 let mut ser_map = serializer.serialize_map(Some(len))?;
229
230 for (key, opt_val) in map {
231 if let Some(val) = opt_val {
232 ser_map.serialize_entry(key, val)?;
233 }
234 }
235
236 ser_map.end()
237}
238
239#[derive(TypeInfo, Debug, Clone, Encode, Decode, Serialize, Deserialize, PartialEq)]
242#[serde(tag = "tracer", content = "tracerConfig", rename_all = "camelCase")]
243pub enum TracerType {
244 CallTracer(Option<CallTracerConfig>),
246
247 PrestateTracer(Option<PrestateTracerConfig>),
249}
250
251impl From<CallTracerConfig> for TracerType {
252 fn from(config: CallTracerConfig) -> Self {
253 TracerType::CallTracer(Some(config))
254 }
255}
256
257impl Default for TracerType {
258 fn default() -> Self {
259 TracerType::CallTracer(Some(CallTracerConfig::default()))
260 }
261}
262
263#[derive(Clone, Debug, Decode, Serialize, Deserialize, Encode, PartialEq, TypeInfo)]
265#[serde(default, rename_all = "camelCase")]
266pub struct PrestateTracerConfig {
267 pub diff_mode: bool,
269
270 pub disable_storage: bool,
272
273 pub disable_code: bool,
275}
276
277impl Default for PrestateTracerConfig {
278 fn default() -> Self {
279 Self {
280 diff_mode: false,
281 disable_storage: false,
282 disable_code: false,
283 }
284 }
285}