Skip to content

Commit

Permalink
Fix bug estimate used gas and estimation for WeightV2 (polkadot-evm#1101
Browse files Browse the repository at this point in the history
)

* Fix estimate used gas and estimation for WeightV2

* fmt

* suggestion

* add ts tests

* try to fix ts tests with bigger txns
  • Loading branch information
tgmichel authored and girazoki committed Aug 29, 2023
1 parent ddfcb04 commit d5e4707
Show file tree
Hide file tree
Showing 5 changed files with 496 additions and 30 deletions.
5 changes: 4 additions & 1 deletion frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,10 @@ impl<T: Config> Pallet<T> {
Ok(PostDispatchInfo {
actual_weight: {
let mut gas_to_weight = T::GasWeightMapping::gas_to_weight(
used_gas.standard.unique_saturated_into(),
sp_std::cmp::max(
used_gas.standard.unique_saturated_into(),
used_gas.effective.unique_saturated_into(),
),
true,
);
if let Some(weight_info) = weight_info {
Expand Down
86 changes: 79 additions & 7 deletions template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ use fp_evm::weight_per_gas;
use fp_rpc::TransactionStatus;
use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction};
use pallet_evm::{
Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner,
Account as EVMAccount, EnsureAccountId20, FeeCalculator, GasWeightMapping,
IdentityAddressMapping, Runner,
};

// A few exports that help ease life for downstream crates.
Expand Down Expand Up @@ -689,6 +690,41 @@ impl_runtime_apis! {
let is_transactional = false;
let validate = true;
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());

let mut estimated_transaction_len = data.len() +
20 + // to
20 + // from
32 + // value
32 + // gas_limit
32 + // nonce
1 + // TransactionAction
8 + // chain id
65; // signature

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 = gas_limit.min(u64::MAX.into()).low_u64();
let without_base_extrinsic_weight = true;

let (weight_limit, proof_size_base_cost) =
match <Runtime as pallet_evm::Config>::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),
};

<Runtime as pallet_evm::Config>::Runner::call(
from,
to,
Expand All @@ -701,9 +737,8 @@ impl_runtime_apis! {
access_list.unwrap_or_default(),
is_transactional,
validate,
// TODO we probably want to support external cost recording in non-transactional calls
None,
None,
weight_limit,
proof_size_base_cost,
evm_config,
).map_err(|err| err.error.into())
}
Expand All @@ -730,6 +765,44 @@ impl_runtime_apis! {
let is_transactional = false;
let validate = true;
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());

let mut estimated_transaction_len = data.len() +
20 + // from
32 + // value
32 + // gas_limit
32 + // nonce
1 + // TransactionAction
8 + // chain id
65; // signature

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 <Runtime as pallet_evm::Config>::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),
};

<Runtime as pallet_evm::Config>::Runner::create(
from,
data,
Expand All @@ -741,9 +814,8 @@ impl_runtime_apis! {
access_list.unwrap_or_default(),
is_transactional,
validate,
// TODO we probably want to support external cost recording in non-transactional calls
None,
None,
weight_limit,
proof_size_base_cost,
evm_config,
).map_err(|err| err.error.into())
}
Expand Down
22 changes: 22 additions & 0 deletions ts-tests/contracts/StorageLoop.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;

contract StorageLoop {
mapping(address => uint) public map;

// n=1 30k
// n=10 37k
// n=100 100k
// n=250 205k
// n=500 380k
// n=1000 745k
function storageLoop(
uint16 n,
address _to,
uint _amount
) public {
for (uint16 i = 0; i < n; i++) {
map[_to] += _amount;
}
}
}
Loading

0 comments on commit d5e4707

Please sign in to comment.