diff --git a/client/rpc/src/eth/execute.rs b/client/rpc/src/eth/execute.rs index 67a1279324..5db2625ba6 100644 --- a/client/rpc/src/eth/execute.rs +++ b/client/rpc/src/eth/execute.rs @@ -100,12 +100,7 @@ where let details = fee_details(gas_price, max_fee_per_gas, max_priority_fee_per_gas)?; ( details.gas_price, - // Old runtimes require max_fee_per_gas to be None for non transactional calls. - if details.max_fee_per_gas == Some(U256::zero()) { - None - } else { - details.max_fee_per_gas - }, + details.max_fee_per_gas, details.max_priority_fee_per_gas, ) }; @@ -1051,7 +1046,8 @@ fn fee_details( // Default to EIP-1559 transaction _ => Ok(FeeDetails { gas_price: None, - max_fee_per_gas: Some(U256::zero()), + // Old runtimes require max_fee_per_gas to be None for non transactional calls. + max_fee_per_gas: None, max_priority_fee_per_gas: Some(U256::zero()), fee_cap: U256::zero(), }), diff --git a/template/runtime/src/lib.rs b/template/runtime/src/lib.rs index db5bd840e1..b687c2fa57 100644 --- a/template/runtime/src/lib.rs +++ b/template/runtime/src/lib.rs @@ -46,10 +46,7 @@ use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter}; use fp_account::EthereumSignature; use fp_evm::weight_per_gas; use fp_rpc::TransactionStatus; -use pallet_ethereum::{ - Call::transact, PostLogContent, Transaction as EthereumTransaction, TransactionAction, - TransactionData, -}; +use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction}; use pallet_evm::{ Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner, }; @@ -791,6 +788,8 @@ impl_runtime_apis! { estimate: bool, access_list: Option)>>, ) -> Result { + use pallet_evm::GasWeightMapping as _; + let config = if estimate { let mut config = ::config().clone(); config.estimate = true; @@ -799,20 +798,45 @@ impl_runtime_apis! { None }; - let gas_limit = gas_limit.min(u64::MAX.into()); - let transaction_data = TransactionData::new( - TransactionAction::Call(to), - data.clone(), - nonce.unwrap_or_default(), - gas_limit, - None, - max_fee_per_gas, - max_priority_fee_per_gas, - value, - Some(::ChainId::get()), - access_list.clone().unwrap_or_default(), - ); - let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::::transaction_weight(&transaction_data); + // Estimated encoded transaction size must be based on the heaviest transaction + // type (EIP1559Transaction) to be compatible with all transaction types. + let mut estimated_transaction_len = data.len() + + // pallet ethereum index: 1 + // transact call index: 1 + // Transaction enum variant: 1 + // chain_id 8 bytes + // nonce: 32 + // max_priority_fee_per_gas: 32 + // max_fee_per_gas: 32 + // gas_limit: 32 + // action: 21 (enum varianrt + call address) + // value: 32 + // access_list: 1 (empty vec size) + // 65 bytes signature + 258; + + if access_list.is_some() { + estimated_transaction_len += access_list.encoded_size(); + } + + + let gas_limit = if gas_limit > U256::from(u64::MAX) { + u64::MAX + } else { + gas_limit.low_u64() + }; + let without_base_extrinsic_weight = true; + + let (weight_limit, proof_size_base_cost) = + match ::GasWeightMapping::gas_to_weight( + gas_limit, + without_base_extrinsic_weight + ) { + weight_limit if weight_limit.proof_size() > 0 => { + (Some(weight_limit), Some(estimated_transaction_len as u64)) + } + _ => (None, None), + }; ::Runner::call( from, @@ -843,6 +867,8 @@ impl_runtime_apis! { estimate: bool, access_list: Option)>>, ) -> Result { + use pallet_evm::GasWeightMapping as _; + let config = if estimate { let mut config = ::config().clone(); config.estimate = true; @@ -851,19 +877,45 @@ impl_runtime_apis! { None }; - let transaction_data = TransactionData::new( - TransactionAction::Create, - data.clone(), - nonce.unwrap_or_default(), - gas_limit, - None, - max_fee_per_gas, - max_priority_fee_per_gas, - value, - Some(::ChainId::get()), - access_list.clone().unwrap_or_default(), - ); - let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::::transaction_weight(&transaction_data); + + let mut estimated_transaction_len = data.len() + + // from: 20 + // value: 32 + // gas_limit: 32 + // nonce: 32 + // 1 byte transaction action variant + // chain id 8 bytes + // 65 bytes signature + 190; + + if max_fee_per_gas.is_some() { + estimated_transaction_len += 32; + } + if max_priority_fee_per_gas.is_some() { + estimated_transaction_len += 32; + } + if access_list.is_some() { + estimated_transaction_len += access_list.encoded_size(); + } + + + let gas_limit = if gas_limit > U256::from(u64::MAX) { + u64::MAX + } else { + gas_limit.low_u64() + }; + let without_base_extrinsic_weight = true; + + let (weight_limit, proof_size_base_cost) = + match ::GasWeightMapping::gas_to_weight( + gas_limit, + without_base_extrinsic_weight + ) { + weight_limit if weight_limit.proof_size() > 0 => { + (Some(weight_limit), Some(estimated_transaction_len as u64)) + } + _ => (None, None), + }; ::Runner::create( from,