1#[macro_export]
18macro_rules! impl_evm_runner_precompile_or_eth_xcm {
19 {} => {
20 use ethereum::AuthorizationList;
21 use fp_evm::{CallInfo, CallOrCreateInfo, Context, Transfer};
22 use frame_support::dispatch::CallableCallFor;
23 use pallet_evm::{Runner, RunnerError};
24 use precompile_utils::{prelude::*, evm::handle::with_precompile_handle};
25 use sp_core::U256;
26 use sp_runtime::DispatchError;
27 use sp_std::vec::Vec;
28 use xcm_primitives::{EthereumXcmTransaction, EthereumXcmTransactionV3};
29
30 pub struct EvmRunnerPrecompileOrEthXcm<CallDispatcher, Runtime>(
31 core::marker::PhantomData<(CallDispatcher, Runtime)>,
32 );
33
34 impl<CallDispatcher, Runtime> Runner<Runtime>
35 for EvmRunnerPrecompileOrEthXcm<CallDispatcher, Runtime>
36 where
37 CallDispatcher: xcm_executor::traits::CallDispatcher<RuntimeCall>,
38 Runtime: pallet_evm::Config + pallet_ethereum_xcm::Config,
39 Runtime::RuntimeOrigin: From<pallet_ethereum_xcm::RawOrigin>,
40 {
41 type Error = DispatchError;
42
43 fn call(
44 source: H160,
45 target: H160,
46 input: Vec<u8>,
47 value: U256,
48 gas_limit: u64,
49 _max_fee_per_gas: Option<U256>,
50 _max_priority_fee_per_gas: Option<U256>,
51 _nonce: Option<U256>,
52 access_list: Vec<(H160, Vec<H256>)>,
53 authorization_list: AuthorizationList,
54 _is_transactional: bool,
55 _validate: bool,
56 _weight_limit: Option<Weight>,
57 _transaction_len: Option<u64>,
58 _config: &fp_evm::Config,
59 ) -> Result<CallInfo, RunnerError<Self::Error>> {
60 if let Some((exit_reason, value)) = with_precompile_handle(|precompile_handle| {
64 let transfer = if value.is_zero() {
65 None
66 } else {
67 Some(Transfer {
68 source,
69 target,
70 value,
71 })
72 };
73
74 precompile_handle.call(
75 target,
76 transfer,
77 input.clone(),
78 Some(gas_limit),
79 false,
80 &Context {
81 address: target,
82 caller: source,
83 apparent_value: value,
84 },
85 )
86 }) {
87 Ok(CallInfo {
88 exit_reason,
89 value,
90 used_gas: fp_evm::UsedGas {
91 standard: U256::default(),
92 effective: U256::default(),
93 },
94 logs: Default::default(),
95 weight_info: None,
96 })
97 } else {
98 let xcm_transaction = EthereumXcmTransaction::V3(EthereumXcmTransactionV3 {
99 gas_limit: gas_limit.into(),
100 action: pallet_ethereum_xcm::TransactionAction::Call(target),
101 value,
102 input: input.try_into().map_err(|_| RunnerError {
103 error: DispatchError::Exhausted,
104 weight: Default::default(),
105 })?,
106 access_list: Some(access_list),
107 authorization_list: Some(authorization_list),
108 });
109
110 let mut execution_info: Option<CallOrCreateInfo> = None;
111 pallet_ethereum::catch_exec_info(&mut execution_info, || {
112 CallDispatcher::dispatch(
113 RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact { xcm_transaction }),
114 RawOrigin::Signed(source.into()).into(),
115 )
116 .map_err(|DispatchErrorWithPostInfo { error, .. }| RunnerError {
117 error,
118 weight: Default::default(),
119 })
120 })?;
121
122 if let Some(CallOrCreateInfo::Call(call_info))= execution_info {
123 Ok(call_info)
124 } else {
125 Err(RunnerError {
127 error: DispatchError::Unavailable,
128 weight: Default::default(),
129 })
130 }
131 }
132 }
133
134 fn create(
135 _source: H160,
136 _init: Vec<u8>,
137 _value: U256,
138 _gas_limit: u64,
139 _max_fee_per_gas: Option<U256>,
140 _max_priority_fee_per_gas: Option<U256>,
141 _nonce: Option<U256>,
142 _access_list: Vec<(H160, Vec<H256>)>,
143 _authorization_list: AuthorizationList,
144 _is_transactional: bool,
145 _validate: bool,
146 _weight_limit: Option<Weight>,
147 _transaction_len: Option<u64>,
148 _config: &fp_evm::Config,
149 ) -> Result<fp_evm::CreateInfo, RunnerError<Self::Error>> {
150 unimplemented!()
151 }
152
153 fn create2(
154 _source: H160,
155 _init: Vec<u8>,
156 _salt: H256,
157 _value: U256,
158 _gas_limit: u64,
159 _max_fee_per_gas: Option<U256>,
160 _max_priority_fee_per_gas: Option<U256>,
161 _nonce: Option<U256>,
162 _access_list: Vec<(H160, Vec<H256>)>,
163 _authorization_list: AuthorizationList,
164 _is_transactional: bool,
165 _validate: bool,
166 _weight_limit: Option<Weight>,
167 _transaction_len: Option<u64>,
168 _config: &fp_evm::Config,
169 ) -> Result<fp_evm::CreateInfo, RunnerError<Self::Error>> {
170 unimplemented!()
171 }
172
173 fn create_force_address(
174 source: H160,
175 init: Vec<u8>,
176 value: U256,
177 gas_limit: u64,
178 max_fee_per_gas: Option<U256>,
179 max_priority_fee_per_gas: Option<U256>,
180 nonce: Option<U256>,
181 access_list: Vec<(H160, Vec<H256>)>,
182 authorization_list: AuthorizationList,
183 is_transactional: bool,
184 validate: bool,
185 weight_limit: Option<Weight>,
186 transaction_len: Option<u64>,
187 config: &fp_evm::Config,
188 force_address: H160,
189 ) -> Result<fp_evm::CreateInfo, RunnerError<Self::Error>> {
190 let xcm_transaction = EthereumXcmTransaction::V3(EthereumXcmTransactionV3 {
191 gas_limit: gas_limit.into(),
192 action: pallet_ethereum_xcm::TransactionAction::Create,
193 value,
194 input: init.try_into().map_err(|_| RunnerError {
195 error: DispatchError::Exhausted,
196 weight: Default::default(),
197 })?,
198 access_list: Some(access_list),
199 authorization_list: Some(authorization_list),
200 });
201
202 let mut execution_info: Option<CallOrCreateInfo> = None;
203 pallet_ethereum::catch_exec_info(&mut execution_info, || {
204 CallDispatcher::dispatch(
205 RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::force_transact_as {
206 transact_as: source,
207 xcm_transaction,
208 force_create_address: Some(force_address),
209 }),
210 RawOrigin::Root.into(),
211 )
212 .map_err(|DispatchErrorWithPostInfo { error, .. }| RunnerError {
213 error,
214 weight: Default::default(),
215 })
216 })?;
217
218 if let Some(CallOrCreateInfo::Create(create_info))= execution_info {
219 Ok(create_info)
220 } else {
221 Err(RunnerError {
223 error: DispatchError::Unavailable,
224 weight: Default::default(),
225 })
226 }
227 }
228
229 fn validate(
230 _source: H160,
231 _target: Option<H160>,
232 _input: Vec<u8>,
233 _value: U256,
234 _gas_limit: u64,
235 _max_fee_per_gas: Option<U256>,
236 _max_priority_fee_per_gas: Option<U256>,
237 _nonce: Option<U256>,
238 _access_list: Vec<(H160, Vec<H256>)>,
239 _authorization_list: Vec<(U256, H160, U256, Option<H160>)>,
240 _is_transactional: bool,
241 _weight_limit: Option<Weight>,
242 _transaction_len: Option<u64>,
243 _evm_config: &fp_evm::Config,
244 ) -> Result<(), RunnerError<Self::Error>> {
245 unimplemented!()
246 }
247 }
248
249 }
250}