moonbeam_evm_tracer/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
26
27pub mod tracer {
28 use ethereum_types::H256;
29 use evm_tracing_events::{EvmEvent, GasometerEvent, RuntimeEvent, StepEventFilter};
30 use parity_scale_codec::{Decode, Encode};
31
32 use evm::tracing::{using as evm_using, EventListener as EvmListener};
33 use evm_gasometer::tracing::{using as gasometer_using, EventListener as GasometerListener};
34 use evm_runtime::tracing::{using as runtime_using, EventListener as RuntimeListener};
35 use sp_runtime::DispatchError;
36 use sp_std::{cell::RefCell, rc::Rc};
37
38 #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
40 pub enum EthereumTracingStatus {
41 Block,
43 Transaction(H256),
45 TransactionExited,
47 }
48
49 environmental::environmental!(ETHEREUM_TRACING_STATUS: EthereumTracingStatus);
50
51 struct ListenerProxy<T>(pub Rc<RefCell<T>>);
52 impl<T: GasometerListener> GasometerListener for ListenerProxy<T> {
53 fn event(&mut self, event: evm_gasometer::tracing::Event) {
54 self.0.borrow_mut().event(event);
55 }
56 }
57
58 impl<T: RuntimeListener> RuntimeListener for ListenerProxy<T> {
59 fn event(&mut self, event: evm_runtime::tracing::Event) {
60 self.0.borrow_mut().event(event);
61 }
62 }
63
64 impl<T: EvmListener> EvmListener for ListenerProxy<T> {
65 fn event(&mut self, event: evm::tracing::Event) {
66 self.0.borrow_mut().event(event);
67 }
68 }
69
70 pub struct EthereumTracer;
71
72 impl EthereumTracer {
73 pub fn transaction(
74 tx_hash: H256,
75 func: impl FnOnce() -> Result<(), DispatchError>,
76 ) -> Result<(), DispatchError> {
77 ETHEREUM_TRACING_STATUS::using(&mut EthereumTracingStatus::Transaction(tx_hash), func)
78 }
79
80 pub fn block(
81 func: impl FnOnce() -> Result<(), DispatchError>,
82 ) -> Result<(), DispatchError> {
83 ETHEREUM_TRACING_STATUS::using(&mut EthereumTracingStatus::Block, func)
84 }
85
86 pub fn transaction_exited() {
87 ETHEREUM_TRACING_STATUS::with(|state| {
88 *state = EthereumTracingStatus::TransactionExited
89 });
90 }
91
92 pub fn status() -> Option<EthereumTracingStatus> {
93 ETHEREUM_TRACING_STATUS::with(|state| state.clone())
94 }
95 }
96
97 pub struct EvmTracer {
98 step_event_filter: StepEventFilter,
99 }
100
101 impl EvmTracer {
102 pub fn new() -> Self {
103 Self {
104 step_event_filter: moonbeam_primitives_ext::moonbeam_ext::step_event_filter(),
105 }
106 }
107
108 pub fn trace<R, F: FnOnce() -> R>(self, f: F) {
113 let wrapped = Rc::new(RefCell::new(self));
114
115 let mut gasometer = ListenerProxy(Rc::clone(&wrapped));
116 let mut runtime = ListenerProxy(Rc::clone(&wrapped));
117 let mut evm = ListenerProxy(Rc::clone(&wrapped));
118
119 let f = || runtime_using(&mut runtime, f);
123 let f = || gasometer_using(&mut gasometer, f);
124 let f = || evm_using(&mut evm, f);
125 f();
126 }
127
128 pub fn emit_new() {
129 moonbeam_primitives_ext::moonbeam_ext::call_list_new();
130 }
131 }
132
133 impl EvmListener for EvmTracer {
134 fn event(&mut self, event: evm::tracing::Event) {
136 let event: EvmEvent = event.into();
137 let message = event.encode();
138 moonbeam_primitives_ext::moonbeam_ext::evm_event(message);
139 }
140 }
141
142 impl GasometerListener for EvmTracer {
143 fn event(&mut self, event: evm_gasometer::tracing::Event) {
145 let event: GasometerEvent = event.into();
146 let message = event.encode();
147 moonbeam_primitives_ext::moonbeam_ext::gasometer_event(message);
148 }
149 }
150
151 impl RuntimeListener for EvmTracer {
152 fn event(&mut self, event: evm_runtime::tracing::Event) {
154 let event = RuntimeEvent::from_evm_event(event, self.step_event_filter);
155 let message = event.encode();
156 moonbeam_primitives_ext::moonbeam_ext::runtime_event(message);
157 }
158 }
159}