revive_strategy/tracing/
revert_tracer.rs1use polkadot_sdk::{
2 pallet_revive::{Code, tracing::Tracing},
3 sp_core::{H160, U256},
4};
5
6#[derive(Debug)]
7pub(crate) struct RevertTracer {
8 pub max_depth: usize,
9 pub has_reverted: Option<polkadot_sdk::sp_core::H160>,
10 pub calls: Vec<polkadot_sdk::sp_core::H160>,
11 pub is_create: bool,
12 pub call_types: Vec<Type>,
13}
14
15#[derive(Debug)]
16pub enum Type {
17 Create,
18 Rest,
19}
20
21impl RevertTracer {
22 fn current_addr(&self) -> H160 {
23 self.calls.last().copied().unwrap_or_default()
24 }
25 pub fn new() -> Self {
26 Self {
27 max_depth: 1,
28 has_reverted: None,
29 calls: vec![],
30 is_create: false,
31 call_types: vec![],
32 }
33 }
34}
35
36impl Tracing for RevertTracer {
37 fn instantiate_code(&mut self, _code: &Code, _salt: Option<&[u8; 32]>) {
38 self.is_create = true;
39 }
40
41 fn enter_child_span(
42 &mut self,
43 _from: H160,
44 to: H160,
45 _is_delegate_call: Option<H160>,
46 _is_read_only: bool,
47 _value: U256,
48 _input: &[u8],
49 _gas: U256,
50 ) {
51 self.call_types.push(if self.is_create { Type::Create } else { Type::Rest });
52
53 self.calls.push(if self.call_types.last().is_some_and(|x| matches!(x, Type::Create)) {
54 self.current_addr()
55 } else {
56 to
57 });
58
59 if self.has_reverted.is_none() {
60 self.max_depth += 1;
61 }
62 }
63
64 fn exit_child_span(
65 &mut self,
66 output: &polkadot_sdk::pallet_revive::ExecReturnValue,
67 _gas_left: U256,
68 ) {
69 let addr = self.calls.pop().unwrap_or_default();
70
71 if output.did_revert() && self.has_reverted.is_none() {
72 self.has_reverted = Some(addr);
73 }
74 let typ = self.call_types.pop();
75 if typ.is_some_and(|x| matches!(x, Type::Create)) {
76 self.is_create = false;
77 }
78 if self.has_reverted.is_none() {
79 self.max_depth -= 1;
80 }
81 }
82 fn exit_child_span_with_error(
83 &mut self,
84 _error: polkadot_sdk::sp_runtime::DispatchError,
85 _gas_used: U256,
86 ) {
87 let addr = self.calls.pop().unwrap_or_default();
88 if self.has_reverted.is_none() {
89 self.has_reverted = Some(addr);
90 }
91 let typ = self.call_types.pop();
92 if typ.is_some_and(|x| matches!(x, Type::Create)) {
93 self.is_create = false;
94 }
95 if self.has_reverted.is_none() {
96 self.max_depth -= 1;
97 }
98 }
99}