Skip to content

Commit 6168284

Browse files
tgmichelbernardoaraujor
authored andcommitted
Fix bug estimate used gas and estimation for WeightV2 (#1101)
* Fix estimate used gas and estimation for WeightV2 * fmt * suggestion * add ts tests * try to fix ts tests with bigger txns
1 parent adf7117 commit 6168284

5 files changed

Lines changed: 496 additions & 30 deletions

File tree

frame/ethereum/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,10 @@ impl<T: Config> Pallet<T> {
683683
Ok(PostDispatchInfo {
684684
actual_weight: {
685685
let mut gas_to_weight = T::GasWeightMapping::gas_to_weight(
686-
used_gas.standard.unique_saturated_into(),
686+
sp_std::cmp::max(
687+
used_gas.standard.unique_saturated_into(),
688+
used_gas.effective.unique_saturated_into(),
689+
),
687690
true,
688691
);
689692
if let Some(weight_info) = weight_info {

template/runtime/src/lib.rs

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ use fp_evm::weight_per_gas;
4848
use fp_rpc::TransactionStatus;
4949
use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction};
5050
use pallet_evm::{
51-
Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner,
51+
Account as EVMAccount, EnsureAccountId20, FeeCalculator, GasWeightMapping,
52+
IdentityAddressMapping, Runner,
5253
};
5354

5455
// A few exports that help ease life for downstream crates.
@@ -689,6 +690,41 @@ impl_runtime_apis! {
689690
let is_transactional = false;
690691
let validate = true;
691692
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());
693+
694+
let mut estimated_transaction_len = data.len() +
695+
20 + // to
696+
20 + // from
697+
32 + // value
698+
32 + // gas_limit
699+
32 + // nonce
700+
1 + // TransactionAction
701+
8 + // chain id
702+
65; // signature
703+
704+
if max_fee_per_gas.is_some() {
705+
estimated_transaction_len += 32;
706+
}
707+
if max_priority_fee_per_gas.is_some() {
708+
estimated_transaction_len += 32;
709+
}
710+
if access_list.is_some() {
711+
estimated_transaction_len += access_list.encoded_size();
712+
}
713+
714+
let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
715+
let without_base_extrinsic_weight = true;
716+
717+
let (weight_limit, proof_size_base_cost) =
718+
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
719+
gas_limit,
720+
without_base_extrinsic_weight
721+
) {
722+
weight_limit if weight_limit.proof_size() > 0 => {
723+
(Some(weight_limit), Some(estimated_transaction_len as u64))
724+
}
725+
_ => (None, None),
726+
};
727+
692728
<Runtime as pallet_evm::Config>::Runner::call(
693729
from,
694730
to,
@@ -701,9 +737,8 @@ impl_runtime_apis! {
701737
access_list.unwrap_or_default(),
702738
is_transactional,
703739
validate,
704-
// TODO we probably want to support external cost recording in non-transactional calls
705-
None,
706-
None,
740+
weight_limit,
741+
proof_size_base_cost,
707742
evm_config,
708743
).map_err(|err| err.error.into())
709744
}
@@ -730,6 +765,44 @@ impl_runtime_apis! {
730765
let is_transactional = false;
731766
let validate = true;
732767
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());
768+
769+
let mut estimated_transaction_len = data.len() +
770+
20 + // from
771+
32 + // value
772+
32 + // gas_limit
773+
32 + // nonce
774+
1 + // TransactionAction
775+
8 + // chain id
776+
65; // signature
777+
778+
if max_fee_per_gas.is_some() {
779+
estimated_transaction_len += 32;
780+
}
781+
if max_priority_fee_per_gas.is_some() {
782+
estimated_transaction_len += 32;
783+
}
784+
if access_list.is_some() {
785+
estimated_transaction_len += access_list.encoded_size();
786+
}
787+
788+
let gas_limit = if gas_limit > U256::from(u64::MAX) {
789+
u64::MAX
790+
} else {
791+
gas_limit.low_u64()
792+
};
793+
let without_base_extrinsic_weight = true;
794+
795+
let (weight_limit, proof_size_base_cost) =
796+
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
797+
gas_limit,
798+
without_base_extrinsic_weight
799+
) {
800+
weight_limit if weight_limit.proof_size() > 0 => {
801+
(Some(weight_limit), Some(estimated_transaction_len as u64))
802+
}
803+
_ => (None, None),
804+
};
805+
733806
<Runtime as pallet_evm::Config>::Runner::create(
734807
from,
735808
data,
@@ -741,9 +814,8 @@ impl_runtime_apis! {
741814
access_list.unwrap_or_default(),
742815
is_transactional,
743816
validate,
744-
// TODO we probably want to support external cost recording in non-transactional calls
745-
None,
746-
None,
817+
weight_limit,
818+
proof_size_base_cost,
747819
evm_config,
748820
).map_err(|err| err.error.into())
749821
}

ts-tests/contracts/StorageLoop.sol

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: GPL-3.0
2+
pragma solidity >=0.8.2 <0.9.0;
3+
4+
contract StorageLoop {
5+
mapping(address => uint) public map;
6+
7+
// n=1 30k
8+
// n=10 37k
9+
// n=100 100k
10+
// n=250 205k
11+
// n=500 380k
12+
// n=1000 745k
13+
function storageLoop(
14+
uint16 n,
15+
address _to,
16+
uint _amount
17+
) public {
18+
for (uint16 i = 0; i < n; i++) {
19+
map[_to] += _amount;
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)