|
20 | 20 |
|
21 | 21 | extern crate alloc;
|
22 | 22 |
|
23 |
| -use alloc::format; |
24 | 23 | use core::marker::PhantomData;
|
25 |
| -use fp_evm::{ExitError, PrecompileFailure, PrecompileHandle}; |
| 24 | +use fp_evm::PrecompileHandle; |
26 | 25 | use frame_support::pallet_prelude::IsType;
|
27 |
| -use frame_support::{codec::DecodeLimit as _, dispatch::Pays, traits::Get}; |
| 26 | +use frame_support::weights::Weight; |
| 27 | +use frame_support::{codec::DecodeLimit as _, traits::Get}; |
28 | 28 | use frame_support::{
|
29 | 29 | dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo},
|
30 | 30 | traits::ConstU32,
|
31 | 31 | };
|
32 | 32 | use frame_system::Config;
|
33 | 33 | use pallet_evm::GasWeightMapping;
|
34 | 34 | use pallet_evm_precompile_dispatch::DispatchValidateT;
|
35 |
| -use precompile_utils::prelude::{revert, BoundedBytes, UnboundedBytes}; |
| 35 | +use precompile_utils::prelude::{revert, BoundedBytes, RuntimeHelper, UnboundedBytes}; |
36 | 36 | use precompile_utils::EvmResult;
|
37 | 37 | use sp_core::{crypto::AccountId32, H160, H256};
|
38 | 38 | use sp_io::hashing::keccak_256;
|
@@ -81,72 +81,37 @@ where
|
81 | 81 | pubkey
|
82 | 82 | );
|
83 | 83 |
|
84 |
| - let target_gas = handle.gas_limit(); |
85 | 84 | let caller: H160 = handle.context().caller.into();
|
86 | 85 | let input: Vec<u8> = call.into();
|
87 | 86 |
|
88 |
| - // 1. Decode the call |
89 |
| - let call = Runtime::RuntimeCall::decode_with_depth_limit(DecodeLimit::get(), &mut &*input) |
90 |
| - .map_err(|_| revert("could not decode call"))?; |
| 87 | + // Record the cost of the call to ensure there is no free execution |
| 88 | + handle.record_cost(Runtime::GasWeightMapping::weight_to_gas( |
| 89 | + Weight::from_parts(1_000_000u64, 0), |
| 90 | + ))?; |
91 | 91 |
|
92 |
| - // 2. Charge the max amount of weight ref_time and |
93 |
| - // later when call is successfully dispatched, |
94 |
| - // charge proof_size and refund the ref_time difference. |
95 |
| - // Note: adding hard coded ref_time corresponding to the blake2b Hash |
96 |
| - // and the keccak256 Hash based on the weight of UA::claim_default_evm_address() |
97 |
| - let info = call.get_dispatch_info(); |
98 |
| - let weight = info.weight.ref_time().saturating_add(40_000_000u64); |
99 |
| - if let Some(gas) = target_gas { |
100 |
| - if !(weight <= Runtime::GasWeightMapping::gas_to_weight(gas, false).ref_time()) { |
101 |
| - return Err(PrecompileFailure::Error { |
102 |
| - exit_status: ExitError::OutOfGas, |
103 |
| - }); |
104 |
| - } |
105 |
| - } |
106 |
| - handle.record_external_cost(Some(weight), None)?; |
107 |
| - |
108 |
| - // 3. Ensure that the caller matches the public key |
| 92 | + // Ensure that the caller matches the public key |
109 | 93 | if caller != Self::get_evm_address_from_pubkey(pubkey.as_bytes()) {
|
110 | 94 | let message: &str = "caller does not match the public key";
|
111 | 95 | log::trace!(target: LOG_TARGET, "{}", message);
|
112 | 96 | return Err(revert(message));
|
113 | 97 | }
|
114 | 98 |
|
115 |
| - // 4. Derive the AccountId from the ECDSA compressed Public key |
| 99 | + // Derive the account id from the public key |
116 | 100 | let origin = Self::get_account_id_from_pubkey(pubkey.as_bytes())
|
117 | 101 | .ok_or(revert("could not derive AccountId from pubkey"))?;
|
118 | 102 |
|
119 |
| - // 5. validate the call |
| 103 | + // Decode the call |
| 104 | + let call = Runtime::RuntimeCall::decode_with_depth_limit(DecodeLimit::get(), &mut &*input) |
| 105 | + .map_err(|_| revert("could not decode call"))?; |
| 106 | + |
| 107 | + // Validate the call - ensure that the call is allowed in filter |
120 | 108 | DispatchValidator::validate_before_dispatch(&origin, &call)
|
121 | 109 | .map_or_else(|| Ok(()), |_| Err(revert("could not validate call")))?;
|
122 | 110 |
|
123 |
| - // 6. Dispatch the call |
124 |
| - match call.dispatch(Some(origin).into()) { |
125 |
| - Ok(post_info) => { |
126 |
| - if post_info.pays_fee(&info) == Pays::Yes { |
127 |
| - let actual_weight = post_info.actual_weight.unwrap_or(info.weight); |
128 |
| - handle.record_external_cost(None, Some(info.weight.proof_size()))?; |
129 |
| - |
130 |
| - handle.refund_external_cost( |
131 |
| - Some( |
132 |
| - info.weight |
133 |
| - .ref_time() |
134 |
| - .saturating_sub(actual_weight.ref_time()), |
135 |
| - ), |
136 |
| - None, |
137 |
| - ); |
138 |
| - } |
139 |
| - |
140 |
| - Ok(true) |
141 |
| - } |
142 |
| - Err(e) => { |
143 |
| - log::trace!(target: LOG_TARGET, "{:?}", e); |
144 |
| - Err(revert(format!( |
145 |
| - "dispatch execution failed: {}", |
146 |
| - <&'static str>::from(e) |
147 |
| - ))) |
148 |
| - } |
149 |
| - } |
| 111 | + // Dispatch the call and handle the cost |
| 112 | + RuntimeHelper::<Runtime>::try_dispatch_runtime_call(handle, Some(origin).into(), call)?; |
| 113 | + |
| 114 | + Ok(true) |
150 | 115 | }
|
151 | 116 |
|
152 | 117 | fn get_account_id_from_pubkey(pubkey: &[u8]) -> Option<<Runtime as Config>::AccountId> {
|
|
0 commit comments