diff --git a/substrate/frame/revive/rpc/src/fee_history_provider.rs b/substrate/frame/revive/rpc/src/fee_history_provider.rs index 677431eb75fb1..5f4483a0453f1 100644 --- a/substrate/frame/revive/rpc/src/fee_history_provider.rs +++ b/substrate/frame/revive/rpc/src/fee_history_provider.rs @@ -25,9 +25,9 @@ const CACHE_SIZE: u32 = 1024; #[derive(Default, Clone)] struct FeeHistoryCacheItem { - base_fee: u64, + base_fee: u128, gas_used_ratio: f64, - rewards: Vec, + rewards: Vec, } /// Manages the fee history cache. @@ -47,17 +47,17 @@ impl FeeHistoryProvider { let block_number: SubstrateBlockNumber = block.number.try_into().expect("Block number is always valid"); - let base_fee = block.base_fee_per_gas.unwrap_or_default().as_u64(); - let gas_used = block.gas_used.as_u64(); - let gas_used_ratio = (gas_used as f64) / (block.gas_limit.as_u64() as f64); + let base_fee = block.base_fee_per_gas.unwrap_or_default().as_u128(); + let gas_used = block.gas_used.as_u128(); + let gas_used_ratio = (gas_used as f64) / (block.gas_limit.as_u128() as f64); let mut result = FeeHistoryCacheItem { base_fee, gas_used_ratio, rewards: vec![] }; let mut receipts = receipts .iter() .map(|receipt| { - let gas_used = receipt.gas_used.as_u64(); + let gas_used = receipt.gas_used.as_u128(); let effective_reward = - receipt.effective_gas_price.as_u64().saturating_sub(base_fee); + receipt.effective_gas_price.as_u128().saturating_sub(base_fee); (gas_used, effective_reward) }) .collect::>(); @@ -67,8 +67,8 @@ impl FeeHistoryProvider { result.rewards = reward_percentiles .into_iter() .filter_map(|p| { - let target_gas = (p * gas_used as f64 / 100f64) as u64; - let mut sum_gas = 0u64; + let target_gas = (p * gas_used as f64 / 100f64) as u128; + let mut sum_gas = 0u128; for (gas_used, reward) in &receipts { sum_gas += gas_used; if target_gas <= sum_gas { diff --git a/substrate/frame/revive/src/evm/runtime.rs b/substrate/frame/revive/src/evm/runtime.rs index c6603173753b2..86c07f8481a71 100644 --- a/substrate/frame/revive/src/evm/runtime.rs +++ b/substrate/frame/revive/src/evm/runtime.rs @@ -20,16 +20,16 @@ use crate::{ api::{GenericTransaction, TransactionSigned}, GasEncoder, }, - AccountIdOf, AddressMapper, BalanceOf, Config, ConversionPrecision, MomentOf, Pallet, - LOG_TARGET, RUNTIME_PALLETS_ADDR, + AccountIdOf, AddressMapper, BalanceOf, Config, ConversionPrecision, MomentOf, + OnChargeTransactionBalanceOf, Pallet, LOG_TARGET, RUNTIME_PALLETS_ADDR, }; use alloc::vec::Vec; -use codec::{Decode, DecodeWithMemTracking, Encode}; +use codec::{Decode, DecodeLimit, DecodeWithMemTracking, Encode}; use frame_support::{ dispatch::{DispatchInfo, GetDispatchInfo}, traits::{InherentBuilder, IsSubType, SignedTransactionBuilder}, + MAX_EXTRINSIC_DEPTH, }; -use pallet_transaction_payment::OnChargeTransaction; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_core::{Get, H256, U256}; use sp_runtime::{ @@ -118,8 +118,6 @@ impl ExtrinsicCall } } -type OnChargeTransactionBalanceOf = <::OnChargeTransaction as OnChargeTransaction>::Balance; - impl Checkable for UncheckedExtrinsic where @@ -334,7 +332,11 @@ pub trait EthExtra { let call = if let Some(dest) = to { if dest == RUNTIME_PALLETS_ADDR { - let call = CallOf::::decode(&mut &data[..]).map_err(|_| { + let call = CallOf::::decode_all_with_depth_limit( + MAX_EXTRINSIC_DEPTH, + &mut &data[..], + ) + .map_err(|_| { log::debug!(target: LOG_TARGET, "Failed to decode data as Call"); InvalidTransaction::Call })?; diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 57b0c41cb613c..c85537b6fd6b7 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -76,6 +76,7 @@ use frame_system::{ pallet_prelude::{BlockNumberFor, OriginFor}, Pallet as System, }; +use pallet_transaction_payment::OnChargeTransaction; use scale_info::TypeInfo; use sp_runtime::{ traits::{BadOrigin, Bounded, Convert, Dispatchable, Saturating, Zero}, @@ -106,6 +107,7 @@ pub type BalanceOf = type TrieId = BoundedVec>; type CodeVec = BoundedVec>; type ImmutableData = BoundedVec>; +pub(crate) type OnChargeTransactionBalanceOf = <::OnChargeTransaction as OnChargeTransaction>::Balance; /// Used as a sentinel value when reading and writing contract memory. /// @@ -1171,15 +1173,18 @@ where /// /// - `tx`: The Ethereum transaction to simulate. /// - `gas_limit`: The gas limit enforced during contract execution. - /// - `tx_fee`: A function that returns the fee for the given call and dispatch info. + /// - `tx_fee`: A function that returns the fee for the computed eth_transact and actual + /// dispatched call pub fn dry_run_eth_transact( mut tx: GenericTransaction, gas_limit: Weight, - tx_fee: impl Fn(Call, DispatchInfo) -> BalanceOf, + tx_fee: impl Fn(::RuntimeCall, ::RuntimeCall) -> BalanceOf, ) -> Result>, EthTransactError> where ::RuntimeCall: Dispatchable, + T: pallet_transaction_payment::Config, + OnChargeTransactionBalanceOf: Into>, ::RuntimeCall: From>, ::RuntimeCall: Encode, T::Nonce: Into, @@ -1247,7 +1252,7 @@ where }; // Dry run the call - let (mut result, dispatch_info) = match tx.to { + let (mut result, dispatch_call) = match tx.to { // A contract call. Some(dest) => { if dest == RUNTIME_PALLETS_ADDR { @@ -1258,19 +1263,20 @@ where ))); }; - let dispatch_info = dispatch_call.get_dispatch_info(); - if let Err(err) = dispatch_call.dispatch(RawOrigin::Signed(origin).into()) { + if let Err(err) = + dispatch_call.clone().dispatch(RawOrigin::Signed(origin).into()) + { return Err(EthTransactError::Message(format!( "Failed to dispatch call: {err:?}" ))); }; let result = EthTransactInfo { - gas_required: dispatch_info.total_weight(), + gas_required: dispatch_call.get_dispatch_info().total_weight(), ..Default::default() }; - (result, dispatch_info) + (result, dispatch_call) } else { // Dry run the call. let result = crate::Pallet::::bare_call( @@ -1291,7 +1297,7 @@ where }, Err(err) => { log::debug!(target: LOG_TARGET, "Failed to execute call: {err:?}"); - return extract_error(err) + return extract_error(err); }, }; @@ -1314,7 +1320,7 @@ where data: input.clone(), } .into(); - (result, dispatch_call.get_dispatch_info()) + (result, dispatch_call) } }, // A contract deployment @@ -1353,7 +1359,7 @@ where }, Err(err) => { log::debug!(target: LOG_TARGET, "Failed to instantiate: {err:?}"); - return extract_error(err) + return extract_error(err); }, }; @@ -1378,7 +1384,7 @@ where data: data.to_vec(), } .into(); - (result, dispatch_call.get_dispatch_info()) + (result, dispatch_call) }, }; @@ -1386,9 +1392,9 @@ where return Err(EthTransactError::Message("Invalid transaction".into())); }; - let eth_dispatch_call = + let eth_transact_call = crate::Call::::eth_transact { payload: unsigned_tx.dummy_signed_payload() }; - let fee = tx_fee(eth_dispatch_call, dispatch_info); + let fee = tx_fee(eth_transact_call.into(), dispatch_call); let raw_gas = Self::evm_fee_to_gas(fee); let eth_gas = T::EthGasEncoder::encode(raw_gas, result.gas_required, result.storage_deposit); @@ -1439,13 +1445,24 @@ where } /// Get the block gas limit. - pub fn evm_block_gas_limit() -> U256 { + pub fn evm_block_gas_limit() -> U256 + where + ::RuntimeCall: + Dispatchable, + T: pallet_transaction_payment::Config, + OnChargeTransactionBalanceOf: Into>, + { let max_block_weight = T::BlockWeights::get() .get(DispatchClass::Normal) .max_total .unwrap_or_else(|| T::BlockWeights::get().max_block); + let length_fee = pallet_transaction_payment::Pallet::::length_to_fee( + 5 * 1024 * 1024, // 5 MB + ); + Self::evm_gas_from_weight(max_block_weight) + .saturating_add(Self::evm_fee_to_gas(length_fee.into())) } /// Get the gas price. @@ -1547,7 +1564,7 @@ where precision: ConversionPrecision, ) -> Result, Error> { if value.is_zero() { - return Ok(Zero::zero()) + return Ok(Zero::zero()); } let (quotient, remainder) = value.div_mod(T::NativeToEthRatio::get().into()); @@ -1758,15 +1775,19 @@ macro_rules! impl_runtime_apis_plus_revive { sp_runtime::traits::Block as BlockT }; - let tx_fee = |pallet_call, mut dispatch_info: $crate::DispatchInfo| { - let call = - ::RuntimeCall::from(pallet_call); + let tx_fee = |call: ::RuntimeCall, dispatch_call: ::RuntimeCall| { + use $crate::frame_support::dispatch::GetDispatchInfo; + + // Get the dispatch info of the actual call dispatched + let mut dispatch_info = dispatch_call.get_dispatch_info(); dispatch_info.extension_weight = - <$EthExtra>::get_eth_extension(0, 0u32.into()).weight(&call); + <$EthExtra>::get_eth_extension(0, 0u32.into()).weight(&dispatch_call); + // Build the extrinsic let uxt: ::Extrinsic = $crate::sp_runtime::generic::UncheckedExtrinsic::new_bare(call).into(); + // Compute the fee of the extrinsic $crate::pallet_transaction_payment::Pallet::::compute_fee( uxt.encoded_size() as u32, &dispatch_info,