Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8f07b75
Add configuration to set Ethereum gas scale
TorstenStueber Nov 22, 2025
5e98c43
Update from github-actions[bot] running command 'prdoc --audience run…
github-actions[bot] Nov 22, 2025
2b823cc
Add GasScale config to other chains
TorstenStueber Nov 22, 2025
b3c9192
Merge branch 'torsten/scale-eth-gas' of github.com:paritytech/polkado…
TorstenStueber Nov 22, 2025
15b8c76
Address clippy complaints
TorstenStueber Nov 22, 2025
cb29390
Increase endowments on dev-node
TorstenStueber Nov 23, 2025
aec7970
Increase the GasScale on the dev node
TorstenStueber Nov 23, 2025
bd87e40
Increase endowments on dev-node again
TorstenStueber Nov 23, 2025
338f0ee
Clean up code structure
TorstenStueber Nov 24, 2025
7268c14
Merge changes from torsten/gas-fixes
TorstenStueber Nov 24, 2025
21e7687
Merge branch 'torsten/gas-fixes' into torsten/scale-eth-gas
TorstenStueber Nov 24, 2025
f3a9a3e
Update from github-actions[bot] running command 'prdoc --audience run…
github-actions[bot] Nov 24, 2025
8388ab1
Update commit of differential testing CI
TorstenStueber Nov 24, 2025
2a8a6c6
Merge branch 'torsten/scale-eth-gas' of github.com:paritytech/polkado…
TorstenStueber Nov 24, 2025
aacd84f
Merge branch 'torsten/gas-fixes' into torsten/scale-eth-gas
TorstenStueber Nov 25, 2025
cda93cc
Merge branch 'torsten/gas-fixes' into torsten/scale-eth-gas
TorstenStueber Nov 27, 2025
56c8a3c
Merge branch 'torsten/gas-fixes' into torsten/scale-eth-gas
TorstenStueber Nov 27, 2025
7362fa1
Merge branch 'torsten/gas-fixes' into torsten/scale-eth-gas
TorstenStueber Nov 27, 2025
aadd6fe
Merge branch 'torsten/gas-fixes' into torsten/scale-eth-gas
TorstenStueber Nov 27, 2025
6c80641
Add doc comment and integrity check
TorstenStueber Nov 27, 2025
ec0b8fb
Fix typo
TorstenStueber Nov 27, 2025
54a9c43
Fix cargo check error
TorstenStueber Nov 27, 2025
94f1a05
Increase gas scale further on dev node
TorstenStueber Nov 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests-evm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: paritytech/revive-differential-tests
ref: a6e4932a08b1ca231e4a02ca6e54e08a53f0e786
ref: cc753a1a2ca6a409748e70e043d7be064e9ce741
path: revive-differential-tests
submodules: recursive
- name: Installing Retester
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,7 @@ impl pallet_revive::Config for Runtime {
type FeeInfo = pallet_revive::evm::fees::Info<Address, Signature, EthExtraImpl>;
type MaxEthExtrinsicWeight = MaxEthExtrinsicWeight;
type DebugEnabled = ConstBool<false>;
type GasScale = ConstU128<1000>;
}

parameter_types! {
Expand Down
1 change: 1 addition & 0 deletions cumulus/parachains/runtimes/testing/penpal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,7 @@ impl pallet_revive::Config for Runtime {
type FeeInfo = pallet_revive::evm::fees::Info<Address, Signature, EthExtraImpl>;
type MaxEthExtrinsicWeight = MaxEthExtrinsicWeight;
type DebugEnabled = ConstBool<false>;
type GasScale = ConstU128<1000>;
}

impl pallet_sudo::Config for Runtime {
Expand Down
39 changes: 39 additions & 0 deletions prdoc/pr_10393.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
title: Add configuration to set Ethereum gas scale
doc:
- audience: Runtime Dev
description: |-
This PR adds a new configuration parameter (`GasScale`) to pallet-revive that allows to change the scale of the Ethereum gas and of the Ethereum gas price.

Before this PR, the Ethereum gas price is simply the next fee multiplier of pallet-transaction-payment multiplied by `NativeToEthRatio`. Thus, on Polkadot this is 100_000_000 when the multiplier has its default value of 1.

The required gas of a transaction is its total cost divided by the gas price, where the total cost is the sum of the transaction fee and the storage deposit.

This leads to a situation where the required gas for a transaction on revive is usually orders of magnitude larger than the required amount of gas on Ethereum. This can lead to issues with tools or systems that interact with revive and hard code expected gas amounts or upper limits of gas amounts.

Setting `GasScale` has two effects:
- revive's Ethereum gas price is scaled up by the factor `GasScale`
- resulting used/estimated gas amounts get scaled down by the factor `GasScale`.

## Technical Details
Internally, revive uses exactly the same gas price and gas units as before. Only at the interface these amounts and prices get scaled by `GasScale`.

## Recommended
This PR sets `GasScale` for the dev-node to 50_000.

This is motivated by the fact that storing a value in a contract storage slot costs `DepositPerChildTrieItem + DepositPerByte * 32`, which is `2_000_000_000 + 10_000_000 * 32` (= `2_320_000_000`) plancks. Before this change the gas price was 1_000_000 wei, so that this
equated to 2_320_000_000 gas units. In EVM this operation requires 22_100 gas only.

Thus, `GasScale` would need to be about 100_000 in order for `SSTORE` to have similar worst case gas requirements.

## Resolved Issues

This PR addresses https://github.com/paritytech/contract-issues/issues/18 but we also need to find an appropriate `GasScale` for a mainnet installment of pallet-revive.
crates:
- name: revive-dev-runtime
bump: patch
- name: pallet-revive
bump: patch
- name: asset-hub-westend-runtime
bump: patch
- name: penpal-runtime
bump: patch
1 change: 1 addition & 0 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,7 @@ impl pallet_revive::Config for Runtime {
type FeeInfo = pallet_revive::evm::fees::Info<Address, Signature, EthExtraImpl>;
type MaxEthExtrinsicWeight = MaxEthExtrinsicWeight;
type DebugEnabled = ConstBool<false>;
type GasScale = ConstU128<1000>;
}

impl pallet_sudo::Config for Runtime {
Expand Down
3 changes: 2 additions & 1 deletion substrate/frame/revive/dev-node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub mod genesis_config_presets {
use alloc::{vec, vec::Vec};
use serde_json::Value;

pub const ENDOWMENT: Balance = 1_000_000_001 * DOLLARS;
pub const ENDOWMENT: Balance = 1_000_000_000_001 * DOLLARS;

fn well_known_accounts() -> Vec<AccountId> {
Sr25519Keyring::well_known()
Expand Down Expand Up @@ -356,6 +356,7 @@ impl pallet_revive::Config for Runtime {
type Time = Timestamp;
type FeeInfo = FeeInfo<Address, Signature, EthExtraImpl>;
type DebugEnabled = ConstBool<false>;
type GasScale = ConstU128<500000>;
}

pallet_revive::impl_runtime_apis_plus_revive_traits!(
Expand Down
31 changes: 30 additions & 1 deletion substrate/frame/revive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,27 @@ pub mod pallet {
/// Allows debug-mode configuration, such as enabling unlimited contract size.
#[pallet::constant]
type DebugEnabled: Get<bool>;

/// This determines the relative scale of our gas price and gas estimates.
///
/// By default, the gas price (in wei) is `FeeInfo::next_fee_multiplier()` multiplied by
/// `NativeToEthRatio`. `GasScale` allows to scale this value: the actual gas price is the
/// default gas price multiplied by `GasScale`.
///
/// As a consequence, gas cost (gas estimates and actual gas usage during transaction) is
/// scaled down by the same factor. Thus, the total transaction cost is not affected by
/// `GasScale` – apart from rounding differences: the transaction cost is always a multiple
/// of the gas price and is derived by rounded up, so that with higher `GasScales` this can
/// lead to higher gas cost as the rounding difference would be larger.
///
/// The main purpose of changing the `GasScale` is to tune the gas cost so that it is closer
/// to standard EVM gas cost and contracts will not run out of gas when tools or code
/// assume hard coded gas limits.
///
/// Requirement: `GasScale` must not be 0
#[pallet::constant]
#[pallet::no_default_bounds]
type GasScale: Get<BalanceOf<Self>>;
}

/// Container for different types that implement [`DefaultConfig`]` of this pallet.
Expand Down Expand Up @@ -377,6 +398,7 @@ pub mod pallet {
pub const DepositPerByte: Balance = deposit(0, 1);
pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
pub const MaxEthExtrinsicWeight: FixedU128 = FixedU128::from_rational(9, 10);
pub const GasScale: Balance = 10 as Balance;
}

/// A type providing default configurations for this pallet in testing environment.
Expand Down Expand Up @@ -431,6 +453,7 @@ pub mod pallet {
type FeeInfo = ();
type MaxEthExtrinsicWeight = MaxEthExtrinsicWeight;
type DebugEnabled = ConstBool<false>;
type GasScale = GasScale;
}
}

Expand Down Expand Up @@ -894,6 +917,8 @@ pub mod pallet {
fn integrity_test() {
assert!(T::ChainId::get() > 0, "ChainId must be greater than 0");

assert!(T::GasScale::get() > 0u32.into(), "GasScale must no be 0");

T::FeeInfo::integrity_test();

// The memory available in the block building runtime
Expand Down Expand Up @@ -2116,8 +2141,12 @@ impl<T: Config> Pallet<T> {

/// Get the base gas price.
pub fn evm_base_fee() -> U256 {
let gas_scale = <T as Config>::GasScale::get();
let multiplier = T::FeeInfo::next_fee_multiplier();
multiplier.saturating_mul_int::<u128>(T::NativeToEthRatio::get().into()).into()
multiplier
.saturating_mul_int::<u128>(T::NativeToEthRatio::get().into())
.saturating_mul(gas_scale.saturated_into())
.into()
}

/// Build an EVM tracer from the given tracer type.
Expand Down
8 changes: 6 additions & 2 deletions substrate/frame/revive/src/metering/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

use crate::{evm::fees::InfoT, BalanceOf, Config, StorageDeposit};
use frame_support::DebugNoBound;
use sp_core::Get;
use sp_runtime::{FixedPointNumber, Saturating};

/// The type for negative and positive gas amounts.
Expand Down Expand Up @@ -52,7 +53,8 @@ impl<T: Config> SignedGas<T> {
/// Transform an Ethereum gas amount coming from outside the metering system and transform into
/// the internally used SignedGas.
pub fn from_ethereum_gas(gas: BalanceOf<T>) -> Self {
Self::Positive(gas)
let gas_scale = <T as Config>::GasScale::get();
Self::Positive(gas.saturating_mul(gas_scale))
}

/// Transform a storage deposit into a gas value. The value will be adjusted by dividing it
Expand Down Expand Up @@ -80,8 +82,10 @@ impl<T: Config> SignedGas<T> {
/// Transform the gas amount to an Ethereum gas amount usable for external purposes
/// Returns None if the gas amount is negative.
pub fn to_ethereum_gas(&self) -> Option<BalanceOf<T>> {
let gas_scale = <T as Config>::GasScale::get();

match self {
Positive(amount) => Some(*amount),
Positive(amount) => Some((*amount) / gas_scale),
Negative(..) => None,
}
}
Expand Down
Loading
Loading