Skip to content

Commit 4242e33

Browse files
authored
Fix estimate gas for old runtimes (#1409)
* max_fee_per_gas should be set to None for old runtimes * estimate max transaction length for proof size base cost * import GasWeightMapping trait * fix compilation errors * remove unused imports
1 parent b846a22 commit 4242e33

File tree

2 files changed

+86
-38
lines changed

2 files changed

+86
-38
lines changed

client/rpc/src/eth/execute.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,7 @@ where
100100
let details = fee_details(gas_price, max_fee_per_gas, max_priority_fee_per_gas)?;
101101
(
102102
details.gas_price,
103-
// Old runtimes require max_fee_per_gas to be None for non transactional calls.
104-
if details.max_fee_per_gas == Some(U256::zero()) {
105-
None
106-
} else {
107-
details.max_fee_per_gas
108-
},
103+
details.max_fee_per_gas,
109104
details.max_priority_fee_per_gas,
110105
)
111106
};
@@ -1051,7 +1046,8 @@ fn fee_details(
10511046
// Default to EIP-1559 transaction
10521047
_ => Ok(FeeDetails {
10531048
gas_price: None,
1054-
max_fee_per_gas: Some(U256::zero()),
1049+
// Old runtimes require max_fee_per_gas to be None for non transactional calls.
1050+
max_fee_per_gas: None,
10551051
max_priority_fee_per_gas: Some(U256::zero()),
10561052
fee_cap: U256::zero(),
10571053
}),

template/runtime/src/lib.rs

Lines changed: 83 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,7 @@ use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter};
4949
use fp_account::EthereumSignature;
5050
use fp_evm::weight_per_gas;
5151
use fp_rpc::TransactionStatus;
52-
use pallet_ethereum::{
53-
Call::transact, PostLogContent, Transaction as EthereumTransaction, TransactionAction,
54-
TransactionData,
55-
};
52+
use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction};
5653
use pallet_evm::{
5754
Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner,
5855
};
@@ -794,6 +791,8 @@ impl_runtime_apis! {
794791
estimate: bool,
795792
access_list: Option<Vec<(H160, Vec<H256>)>>,
796793
) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
794+
use pallet_evm::GasWeightMapping as _;
795+
797796
let config = if estimate {
798797
let mut config = <Runtime as pallet_evm::Config>::config().clone();
799798
config.estimate = true;
@@ -802,20 +801,45 @@ impl_runtime_apis! {
802801
None
803802
};
804803

805-
let gas_limit = gas_limit.min(u64::MAX.into());
806-
let transaction_data = TransactionData::new(
807-
TransactionAction::Call(to),
808-
data.clone(),
809-
nonce.unwrap_or_default(),
810-
gas_limit,
811-
None,
812-
max_fee_per_gas,
813-
max_priority_fee_per_gas,
814-
value,
815-
Some(<Runtime as pallet_evm::Config>::ChainId::get()),
816-
access_list.clone().unwrap_or_default(),
817-
);
818-
let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
804+
// Estimated encoded transaction size must be based on the heaviest transaction
805+
// type (EIP1559Transaction) to be compatible with all transaction types.
806+
let mut estimated_transaction_len = data.len() +
807+
// pallet ethereum index: 1
808+
// transact call index: 1
809+
// Transaction enum variant: 1
810+
// chain_id 8 bytes
811+
// nonce: 32
812+
// max_priority_fee_per_gas: 32
813+
// max_fee_per_gas: 32
814+
// gas_limit: 32
815+
// action: 21 (enum varianrt + call address)
816+
// value: 32
817+
// access_list: 1 (empty vec size)
818+
// 65 bytes signature
819+
258;
820+
821+
if access_list.is_some() {
822+
estimated_transaction_len += access_list.encoded_size();
823+
}
824+
825+
826+
let gas_limit = if gas_limit > U256::from(u64::MAX) {
827+
u64::MAX
828+
} else {
829+
gas_limit.low_u64()
830+
};
831+
let without_base_extrinsic_weight = true;
832+
833+
let (weight_limit, proof_size_base_cost) =
834+
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
835+
gas_limit,
836+
without_base_extrinsic_weight
837+
) {
838+
weight_limit if weight_limit.proof_size() > 0 => {
839+
(Some(weight_limit), Some(estimated_transaction_len as u64))
840+
}
841+
_ => (None, None),
842+
};
819843

820844
<Runtime as pallet_evm::Config>::Runner::call(
821845
from,
@@ -846,6 +870,8 @@ impl_runtime_apis! {
846870
estimate: bool,
847871
access_list: Option<Vec<(H160, Vec<H256>)>>,
848872
) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
873+
use pallet_evm::GasWeightMapping as _;
874+
849875
let config = if estimate {
850876
let mut config = <Runtime as pallet_evm::Config>::config().clone();
851877
config.estimate = true;
@@ -854,19 +880,45 @@ impl_runtime_apis! {
854880
None
855881
};
856882

857-
let transaction_data = TransactionData::new(
858-
TransactionAction::Create,
859-
data.clone(),
860-
nonce.unwrap_or_default(),
861-
gas_limit,
862-
None,
863-
max_fee_per_gas,
864-
max_priority_fee_per_gas,
865-
value,
866-
Some(<Runtime as pallet_evm::Config>::ChainId::get()),
867-
access_list.clone().unwrap_or_default(),
868-
);
869-
let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
883+
884+
let mut estimated_transaction_len = data.len() +
885+
// from: 20
886+
// value: 32
887+
// gas_limit: 32
888+
// nonce: 32
889+
// 1 byte transaction action variant
890+
// chain id 8 bytes
891+
// 65 bytes signature
892+
190;
893+
894+
if max_fee_per_gas.is_some() {
895+
estimated_transaction_len += 32;
896+
}
897+
if max_priority_fee_per_gas.is_some() {
898+
estimated_transaction_len += 32;
899+
}
900+
if access_list.is_some() {
901+
estimated_transaction_len += access_list.encoded_size();
902+
}
903+
904+
905+
let gas_limit = if gas_limit > U256::from(u64::MAX) {
906+
u64::MAX
907+
} else {
908+
gas_limit.low_u64()
909+
};
910+
let without_base_extrinsic_weight = true;
911+
912+
let (weight_limit, proof_size_base_cost) =
913+
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
914+
gas_limit,
915+
without_base_extrinsic_weight
916+
) {
917+
weight_limit if weight_limit.proof_size() > 0 => {
918+
(Some(weight_limit), Some(estimated_transaction_len as u64))
919+
}
920+
_ => (None, None),
921+
};
870922

871923
<Runtime as pallet_evm::Config>::Runner::create(
872924
from,

0 commit comments

Comments
 (0)