1use crate::{Weight, evm::Bytes};
19use alloc::{collections::BTreeMap, string::String, vec::Vec};
20use derive_more::From;
21use pallet_revive_types::runtime_api::*;
22use sp_core::{H160, H256, U256};
23use sp_runtime::ApplyExtrinsicResult;
24
25#[derive(Debug, Clone, PartialEq, From)]
27pub enum TracerType {
28 CallTracer(Option<CallTracerConfig>),
30
31 PrestateTracer(Option<PrestateTracerConfig>),
33
34 ExecutionTracer(Option<ExecutionTracerConfig>),
36}
37
38impl Default for TracerType {
39 fn default() -> Self {
40 TracerType::ExecutionTracer(Some(ExecutionTracerConfig::default()))
41 }
42}
43
44impl From<TracerTypeV1> for TracerType {
45 fn from(value: TracerTypeV1) -> Self {
46 match value {
47 TracerTypeV1::CallTracer(config) => Self::CallTracer(config.map(Into::into)),
48 TracerTypeV1::PrestateTracer(config) => Self::PrestateTracer(config.map(Into::into)),
49 TracerTypeV1::ExecutionTracer(config) => Self::ExecutionTracer(config.map(Into::into)),
50 }
51 }
52}
53
54#[derive(Clone, Debug, PartialEq)]
56pub struct CallTracerConfig {
57 pub with_logs: bool,
59
60 pub only_top_call: bool,
62}
63
64impl Default for CallTracerConfig {
65 fn default() -> Self {
66 Self { with_logs: true, only_top_call: false }
67 }
68}
69
70impl From<CallTracerConfigV1> for CallTracerConfig {
71 fn from(value: CallTracerConfigV1) -> Self {
72 Self { with_logs: value.with_logs, only_top_call: value.only_top_call }
73 }
74}
75
76#[derive(Clone, Debug, PartialEq)]
78pub struct PrestateTracerConfig {
79 pub diff_mode: bool,
81
82 pub disable_storage: bool,
84
85 pub disable_code: bool,
87}
88
89impl Default for PrestateTracerConfig {
90 fn default() -> Self {
91 Self { diff_mode: false, disable_storage: false, disable_code: false }
92 }
93}
94
95impl From<PrestateTracerConfigV1> for PrestateTracerConfig {
96 fn from(value: PrestateTracerConfigV1) -> Self {
97 Self {
98 diff_mode: value.diff_mode,
99 disable_storage: value.disable_storage,
100 disable_code: value.disable_code,
101 }
102 }
103}
104
105#[derive(Clone, Debug, PartialEq)]
107pub struct ExecutionTracerConfig {
108 pub enable_memory: bool,
110
111 pub disable_stack: bool,
113
114 pub disable_storage: bool,
116
117 pub enable_return_data: bool,
119
120 pub disable_syscall_details: bool,
122
123 pub limit: Option<u64>,
125
126 pub memory_word_limit: u32,
128}
129
130impl Default for ExecutionTracerConfig {
131 fn default() -> Self {
132 Self {
133 enable_memory: false,
134 disable_stack: false,
135 disable_storage: false,
136 enable_return_data: false,
137 disable_syscall_details: false,
138 limit: None,
139 memory_word_limit: 16,
140 }
141 }
142}
143
144impl From<ExecutionTracerConfigV1> for ExecutionTracerConfig {
145 fn from(value: ExecutionTracerConfigV1) -> Self {
146 Self {
147 enable_memory: value.enable_memory,
148 disable_stack: value.disable_stack,
149 disable_storage: value.disable_storage,
150 enable_return_data: value.enable_return_data,
151 disable_syscall_details: value.disable_syscall_details,
152 limit: value.limit,
153 memory_word_limit: value.memory_word_limit,
154 }
155 }
156}
157
158#[derive(Default, Eq, PartialEq, Clone, Debug)]
160pub enum CallType {
161 #[default]
163 Call,
164 StaticCall,
166 DelegateCall,
168 Create,
170 Create2,
172 Selfdestruct,
174}
175
176impl From<CallType> for CallTypeV1 {
177 fn from(value: CallType) -> Self {
178 match value {
179 CallType::Call => Self::Call,
180 CallType::StaticCall => Self::StaticCall,
181 CallType::DelegateCall => Self::DelegateCall,
182 CallType::Create => Self::Create,
183 CallType::Create2 => Self::Create2,
184 CallType::Selfdestruct => Self::Selfdestruct,
185 }
186 }
187}
188
189#[derive(From, Clone, Debug, Eq, PartialEq)]
191pub enum Trace {
192 Call(CallTrace),
194 Prestate(PrestateTrace),
196 Execution(ExecutionTrace),
198}
199
200impl From<Trace> for TraceV1 {
201 fn from(value: Trace) -> Self {
202 match value {
203 Trace::Call(value) => Self::Call(value.into()),
204 Trace::Prestate(value) => Self::Prestate(value.into()),
205 Trace::Execution(value) => Self::Execution(value.into()),
206 }
207 }
208}
209
210impl From<Trace> for TraceV2 {
211 fn from(value: Trace) -> Self {
212 match value {
213 Trace::Call(value) => Self::Call(value.into()),
214 Trace::Prestate(value) => Self::Prestate(value.into()),
215 Trace::Execution(value) => Self::Execution(value.into()),
216 }
217 }
218}
219
220pub enum TraceEntry {
222 Traced(Trace),
224 NotTraced,
226}
227
228impl TraceEntry {
229 pub fn for_untraced(result: &ApplyExtrinsicResult) -> Option<Self> {
233 matches!(result, Err(err) if err.exhausted_resources()).then_some(Self::NotTraced)
234 }
235}
236
237impl From<TraceEntry> for TraceEntryV1 {
238 fn from(value: TraceEntry) -> Self {
239 match value {
240 TraceEntry::Traced(trace) => TraceEntryV1::Traced(trace.into()),
241 TraceEntry::NotTraced => TraceEntryV1::NotTraced,
242 }
243 }
244}
245
246#[derive(Clone, Debug, Eq, PartialEq)]
248pub enum PrestateTrace {
249 Prestate(BTreeMap<H160, PrestateTraceInfo>),
251
252 DiffMode {
255 pre: BTreeMap<H160, PrestateTraceInfo>,
260 post: BTreeMap<H160, PrestateTraceInfo>,
263 },
264}
265
266impl PrestateTrace {
267 pub fn state_mut(
269 &mut self,
270 ) -> (&mut BTreeMap<H160, PrestateTraceInfo>, Option<&mut BTreeMap<H160, PrestateTraceInfo>>) {
271 match self {
272 PrestateTrace::Prestate(pre) => (pre, None),
273 PrestateTrace::DiffMode { pre, post } => (pre, Some(post)),
274 }
275 }
276}
277
278impl From<PrestateTrace> for PrestateTraceV1 {
279 fn from(value: PrestateTrace) -> Self {
280 let convert = |v: BTreeMap<H160, PrestateTraceInfo>| {
281 v.into_iter().map(|(k, v)| (k, v.into())).collect()
282 };
283
284 match value {
285 PrestateTrace::Prestate(accounts) => Self::Prestate(convert(accounts)),
286 PrestateTrace::DiffMode { pre, post } => {
287 Self::DiffMode { pre: convert(pre), post: convert(post) }
288 },
289 }
290 }
291}
292
293#[derive(Default, Clone, Debug, Eq, PartialEq)]
295pub struct PrestateTraceInfo {
296 pub balance: Option<U256>,
298 pub nonce: Option<u32>,
300 pub code: Option<Bytes>,
302 pub storage: BTreeMap<Bytes, Option<Bytes>>,
304}
305
306impl From<PrestateTraceInfo> for PrestateTraceInfoV1 {
307 fn from(value: PrestateTraceInfo) -> Self {
308 Self {
309 balance: value.balance,
310 nonce: value.nonce,
311 code: value.code,
312 storage: value.storage,
313 }
314 }
315}
316
317#[derive(Default, Clone, Debug, Eq, PartialEq)]
320pub struct ExecutionTrace {
321 pub gas: u64,
323 pub weight_consumed: Weight,
325 pub base_call_weight: Weight,
327 pub failed: bool,
329 pub return_value: Bytes,
331 pub struct_logs: Vec<ExecutionStep>,
333}
334
335impl From<ExecutionTrace> for ExecutionTraceV1 {
336 fn from(value: ExecutionTrace) -> Self {
337 Self {
338 gas: value.gas,
339 weight_consumed: value.weight_consumed,
340 base_call_weight: value.base_call_weight,
341 failed: value.failed,
342 return_value: value.return_value,
343 struct_logs: value.struct_logs.into_iter().map(Into::into).collect(),
344 }
345 }
346}
347
348#[derive(Clone, Debug, Eq, PartialEq, Default)]
350pub struct ExecutionStep {
351 pub gas: u64,
353 pub gas_cost: u64,
355 pub weight_cost: Weight,
357 pub depth: u16,
359 pub return_data: Bytes,
361 pub error: Option<String>,
363 pub kind: ExecutionStepKind,
365}
366
367impl From<ExecutionStep> for ExecutionStepV1 {
368 fn from(value: ExecutionStep) -> Self {
369 Self {
370 gas: value.gas,
371 gas_cost: value.gas_cost,
372 weight_cost: value.weight_cost,
373 depth: value.depth,
374 return_data: value.return_data,
375 error: value.error,
376 kind: value.kind.into(),
377 }
378 }
379}
380
381#[derive(Clone, Debug, Eq, PartialEq)]
383pub enum ExecutionStepKind {
384 EVMOpcode {
386 pc: u32,
388 op: u8,
390 stack: Vec<Bytes>,
392 memory: Vec<Bytes>,
394 storage: Option<alloc::collections::BTreeMap<Bytes, Bytes>>,
396 },
397 PVMSyscall {
399 op: u8,
401 args: Vec<u64>,
404 returned: Option<u64>,
407 },
408}
409
410impl Default for ExecutionStepKind {
411 fn default() -> Self {
412 Self::EVMOpcode { pc: 0, op: 0, stack: Vec::new(), memory: Vec::new(), storage: None }
413 }
414}
415
416impl From<ExecutionStepKind> for ExecutionStepKindV1 {
417 fn from(value: ExecutionStepKind) -> Self {
418 match value {
419 ExecutionStepKind::EVMOpcode { pc, op, stack, memory, storage } => {
420 Self::EVMOpcode { pc, op: EvmOpcodeV1(op), stack, memory, storage }
421 },
422 ExecutionStepKind::PVMSyscall { op, args, returned } => Self::PVMSyscall {
423 op: op
424 .try_into()
425 .expect("all sys calls produced by revive are valid. Tested in env.rs; qed"),
426 args,
427 returned,
428 },
429 }
430 }
431}
432
433#[derive(Default, Clone, Debug, Eq, PartialEq)]
435pub struct CallTrace {
436 pub from: H160,
438 pub gas: u64,
440 pub gas_used: u64,
442 pub to: H160,
444 pub input: Bytes,
446 pub output: Bytes,
448 pub error: Option<String>,
450 pub revert_reason: Option<String>,
452 pub calls: Vec<CallTrace>,
454 pub logs: Vec<CallLog>,
456 pub value: Option<U256>,
458 pub call_type: CallType,
460 pub child_call_count: u32,
462}
463
464impl From<CallTrace> for CallTraceV1 {
465 fn from(value: CallTrace) -> Self {
466 Self {
467 from: value.from,
468 gas: value.gas,
469 gas_used: value.gas_used,
470 to: value.to,
471 input: value.input,
472 output: value.output,
473 error: value.error,
474 revert_reason: value.revert_reason,
475 calls: value.calls.into_iter().map(Into::into).collect(),
476 logs: value.logs.into_iter().map(Into::into).collect(),
477 value: value.value,
478 call_type: value.call_type.into(),
479 child_call_count: value.child_call_count,
480 }
481 }
482}
483
484impl From<CallTrace> for CallTraceV2 {
485 fn from(value: CallTrace) -> Self {
486 Self {
487 from: value.from,
488 gas: value.gas,
489 gas_used: value.gas_used,
490 to: value.to,
491 input: value.input,
492 output: value.output,
493 error: value.error,
494 revert_reason: value.revert_reason,
495 calls: value.calls.into_iter().map(Into::into).collect(),
496 logs: value.logs.into_iter().map(Into::into).collect(),
497 value: value.value,
498 call_type: value.call_type.into(),
499 }
500 }
501}
502
503#[derive(Debug, Default, Clone, Eq, PartialEq)]
505pub struct CallLog {
506 pub address: H160,
508 pub topics: Vec<H256>,
510 pub data: Bytes,
512 pub position: u32,
515 pub index: u32,
519}
520
521impl From<CallLog> for CallLogV1 {
522 fn from(value: CallLog) -> Self {
523 Self {
524 address: value.address,
525 topics: value.topics,
526 data: value.data,
527 position: value.position,
528 }
529 }
530}
531
532impl From<CallLog> for CallLogV2 {
533 fn from(value: CallLog) -> Self {
534 Self {
535 address: value.address,
536 topics: value.topics,
537 data: value.data,
538 position: value.position,
539 index: value.index,
540 }
541 }
542}