moonbeam_runtime_common/
impl_moonbeam_xcm_call_tracing.rs1#[macro_export]
18macro_rules! impl_moonbeam_xcm_call_tracing {
19 {} => {
20 use moonbeam_evm_tracer::tracer::EthereumTracingStatus;
21 type CallResult =
22 Result<
23 PostDispatchInfoOf<RuntimeCall>,
24 DispatchErrorWithPostInfo<PostDispatchInfoOf<RuntimeCall>>
25 >;
26
27 pub struct MoonbeamCall;
28 impl CallDispatcher<RuntimeCall> for MoonbeamCall {
29 fn dispatch(
30 call: RuntimeCall,
31 origin: RuntimeOrigin,
32 ) -> CallResult {
33 if let Ok(raw_origin) = TryInto::<RawOrigin<AccountId>>::try_into(origin.clone().caller) {
34 match call.clone() {
35 RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact { xcm_transaction }) |
36 RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact_through_proxy {
37 xcm_transaction, ..
38 }) |
39 RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::force_transact_as {
40 xcm_transaction, ..
41 }) => {
42 use crate::EthereumXcm;
43 use moonbeam_evm_tracer::tracer::{
44 EthereumTracer,
45 EvmTracer,
46 EthereumTracingStatus
47 };
48 use xcm_primitives::{
49 XcmToEthereum,
50 };
51 use frame_support::storage::unhashed;
52 use frame_support::traits::Get;
53
54 let dispatch_call = || {
55 RuntimeCall::dispatch(
56 call,
57 match raw_origin {
58 RawOrigin::Signed(account_id) => {
59 pallet_ethereum_xcm::Origin::XcmEthereumTransaction(
60 account_id.into()
61 ).into()
62 },
63 origin => origin.into()
64 }
65 )
66 };
67
68 return match EthereumTracer::status() {
69 Some(tracing_status) => {
71 match tracing_status {
72 EthereumTracingStatus::Block => {
74 EvmTracer::emit_new();
76 let mut res: Option<CallResult> = None;
77 EvmTracer::new().trace(|| {
78 res = Some(dispatch_call());
79 });
80 res.expect("Invalid dispatch result")
81 },
82 EthereumTracingStatus::Transaction(traced_transaction_hash) => {
85 let transaction_hash = xcm_transaction.into_transaction(
86 EthereumXcm::nonce(),
87 <Runtime as pallet_evm::Config>::ChainId::get(),
88 false
89 )
90 .expect("Invalid transaction conversion")
91 .hash();
92 if transaction_hash == traced_transaction_hash {
93 let mut res: Option<CallResult> = None;
94 EvmTracer::new().trace(|| {
95 res = Some(dispatch_call());
96 });
97 EthereumTracer::transaction_exited();
99 return res.expect("Invalid dispatch result");
100 }
101 dispatch_call()
102 },
103 EthereumTracingStatus::TransactionExited => Ok(crate::PostDispatchInfo {
107 actual_weight: None,
108 pays_fee: frame_support::pallet_prelude::Pays::No,
109 }),
110 }
111 }
112 None => dispatch_call()
114 };
115 },
116 _ => {}
117 }
118 }
119 RuntimeCall::dispatch(call, origin)
120 }
121 }
122 }
123}