Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 8 additions & 4 deletions frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,13 @@ pub mod pallet {
OriginFor<T>: Into<Result<RawOrigin, OriginFor<T>>>,
{
/// Transact an Ethereum transaction.
#[pallet::weight(<T as pallet_evm::Config>::GasWeightMapping::gas_to_weight({
let transaction_data: TransactionData = transaction.into();
transaction_data.gas_limit.unique_saturated_into()
}))]
#[pallet::weight({
let without_base_extrinsic_weight = true;
<T as pallet_evm::Config>::GasWeightMapping::gas_to_weight({
let transaction_data: TransactionData = transaction.into();
transaction_data.gas_limit.unique_saturated_into()
}, without_base_extrinsic_weight)
})]
pub fn transact(
origin: OriginFor<T>,
transaction: Transaction,
Expand Down Expand Up @@ -604,6 +607,7 @@ impl<T: Config> Pallet<T> {
Ok(PostDispatchInfo {
actual_weight: Some(T::GasWeightMapping::gas_to_weight(
used_gas.unique_saturated_into(),
true,
)),
pays_fee: Pays::No,
})
Expand Down
4 changes: 3 additions & 1 deletion frame/ethereum/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ parameter_types! {
pub const ChainId: u64 = 42;
pub const EVMModuleId: PalletId = PalletId(*b"py/evmpa");
pub const BlockGasLimit: U256 = U256::MAX;
pub const WeightPerGas: u64 = 20_000;
}

pub struct HashedAddressMapping;
Expand All @@ -152,7 +153,8 @@ impl AddressMapping<AccountId32> for HashedAddressMapping {

impl pallet_evm::Config for Test {
type FeeCalculator = FixedGasPrice;
type GasWeightMapping = ();
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
type CallOrigin = EnsureAddressTruncated;
type WithdrawOrigin = EnsureAddressTruncated;
type AddressMapping = HashedAddressMapping;
Expand Down
6 changes: 4 additions & 2 deletions frame/ethereum/src/tests/eip1559.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ fn transaction_with_gas_limit_greater_than_max_extrinsic_should_fail_pre_dispatc
let limits: frame_system::limits::BlockWeights =
<Test as frame_system::Config>::BlockWeights::get();
let max_extrinsic = limits.get(DispatchClass::Normal).max_extrinsic.unwrap();
let max_extrinsic_gas =
<Test as pallet_evm::Config>::GasWeightMapping::weight_to_gas(max_extrinsic);
let base_extrinsic = limits.get(DispatchClass::Normal).base_extrinsic;
let max_extrinsic_gas = <Test as pallet_evm::Config>::GasWeightMapping::weight_to_gas(
max_extrinsic + base_extrinsic,
);

ext.execute_with(|| {
let transaction = EIP1559UnsignedTransaction {
Expand Down
2 changes: 1 addition & 1 deletion frame/evm/precompile/dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ where
}

if let Some(gas) = target_gas {
let valid_weight = info.weight <= T::GasWeightMapping::gas_to_weight(gas);
let valid_weight = info.weight <= T::GasWeightMapping::gas_to_weight(gas, false);
if !valid_weight {
return Err(PrecompileFailure::Error {
exit_status: ExitError::OutOfGas,
Expand Down
4 changes: 3 additions & 1 deletion frame/evm/precompile/dispatch/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,12 @@ impl FindAuthor<H160> for FindAuthorTruncated {
}
parameter_types! {
pub BlockGasLimit: U256 = U256::max_value();
pub WeightPerGas: u64 = 20_000;
}
impl pallet_evm::Config for Test {
type FeeCalculator = FixedGasPrice;
type GasWeightMapping = ();
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;

type CallOrigin = EnsureAddressRoot<Self::AccountId>;
type WithdrawOrigin = EnsureAddressNever<Self::AccountId>;
Expand Down
40 changes: 32 additions & 8 deletions frame/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ pub mod pallet {
/// Maps Ethereum gas to Substrate weight.
type GasWeightMapping: GasWeightMapping;

/// Weight corresponding to a gas unit.
type WeightPerGas: Get<u64>;

/// Block number to block hash.
type BlockHashMapping: BlockHashMapping;

Expand Down Expand Up @@ -176,7 +179,10 @@ pub mod pallet {
}

/// Issue an EVM call operation. This is similar to a message call transaction in Ethereum.
#[pallet::weight(T::GasWeightMapping::gas_to_weight(*gas_limit))]
#[pallet::weight({
let without_base_extrinsic_weight = true;
T::GasWeightMapping::gas_to_weight(*gas_limit, without_base_extrinsic_weight)
})]
pub fn call(
origin: OriginFor<T>,
source: H160,
Expand Down Expand Up @@ -231,14 +237,18 @@ pub mod pallet {
Ok(PostDispatchInfo {
actual_weight: Some(T::GasWeightMapping::gas_to_weight(
info.used_gas.unique_saturated_into(),
true,
)),
pays_fee: Pays::No,
})
}

/// Issue an EVM create operation. This is similar to a contract creation transaction in
/// Ethereum.
#[pallet::weight(T::GasWeightMapping::gas_to_weight(*gas_limit))]
#[pallet::weight({
let without_base_extrinsic_weight = true;
T::GasWeightMapping::gas_to_weight(*gas_limit, without_base_extrinsic_weight)
})]
pub fn create(
origin: OriginFor<T>,
source: H160,
Expand Down Expand Up @@ -303,13 +313,17 @@ pub mod pallet {
Ok(PostDispatchInfo {
actual_weight: Some(T::GasWeightMapping::gas_to_weight(
info.used_gas.unique_saturated_into(),
true,
)),
pays_fee: Pays::No,
})
}

/// Issue an EVM create2 operation.
#[pallet::weight(T::GasWeightMapping::gas_to_weight(*gas_limit))]
#[pallet::weight({
let without_base_extrinsic_weight = true;
T::GasWeightMapping::gas_to_weight(*gas_limit, without_base_extrinsic_weight)
})]
pub fn create2(
origin: OriginFor<T>,
source: H160,
Expand Down Expand Up @@ -376,6 +390,7 @@ pub mod pallet {
Ok(PostDispatchInfo {
actual_weight: Some(T::GasWeightMapping::gas_to_weight(
info.used_gas.unique_saturated_into(),
true,
)),
pays_fee: Pays::No,
})
Expand Down Expand Up @@ -618,16 +633,25 @@ impl<T: Config> BlockHashMapping for SubstrateBlockHashMapping<T> {

/// A mapping function that converts Ethereum gas to Substrate weight
pub trait GasWeightMapping {
fn gas_to_weight(gas: u64) -> Weight;
fn gas_to_weight(gas: u64, without_base_weight: bool) -> Weight;
fn weight_to_gas(weight: Weight) -> u64;
}

impl GasWeightMapping for () {
fn gas_to_weight(gas: u64) -> Weight {
gas as Weight
pub struct FixedGasWeightMapping<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> GasWeightMapping for FixedGasWeightMapping<T> {
fn gas_to_weight(gas: u64, without_base_weight: bool) -> Weight {
let mut weight = gas.saturating_mul(T::WeightPerGas::get());
if without_base_weight {
weight = weight.saturating_sub(
T::BlockWeights::get()
.get(frame_support::weights::DispatchClass::Normal)
.base_extrinsic,
);
}
weight
}
fn weight_to_gas(weight: Weight) -> u64 {
weight as u64
weight.wrapping_div(T::WeightPerGas::get())
}
}

Expand Down
4 changes: 3 additions & 1 deletion frame/evm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ impl FindAuthor<H160> for FindAuthorTruncated {
}
parameter_types! {
pub BlockGasLimit: U256 = U256::max_value();
pub WeightPerGas: u64 = 20_000;
}
impl crate::Config for Test {
type FeeCalculator = FixedGasPrice;
type GasWeightMapping = ();
type GasWeightMapping = crate::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;

type CallOrigin = EnsureAddressRoot<Self::AccountId>;
type WithdrawOrigin = EnsureAddressNever<Self::AccountId>;
Expand Down
30 changes: 17 additions & 13 deletions template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ use pallet_transaction_payment::CurrencyAdapter;
use fp_rpc::TransactionStatus;
use pallet_ethereum::{Call::transact, Transaction as EthereumTransaction};
use pallet_evm::{
Account as EVMAccount, EnsureAddressTruncated, FeeCalculator, GasWeightMapping,
HashedAddressMapping, Runner,
Account as EVMAccount, EnsureAddressTruncated, FeeCalculator, HashedAddressMapping, Runner,
};

// A few exports that help ease life for downstream crates.
Expand Down Expand Up @@ -309,24 +308,16 @@ impl<F: FindAuthor<u32>> FindAuthor<H160> for FindAuthorTruncated<F> {
}
}

pub struct FixedGasWeightMapping;
impl GasWeightMapping for FixedGasWeightMapping {
fn gas_to_weight(gas: u64) -> Weight {
gas.saturating_mul(WEIGHT_PER_GAS)
}
fn weight_to_gas(weight: Weight) -> u64 {
weight.wrapping_div(WEIGHT_PER_GAS)
}
}

parameter_types! {
pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WEIGHT_PER_GAS);
pub PrecompilesValue: FrontierPrecompiles<Runtime> = FrontierPrecompiles::<_>::new();
pub WeightPerGas: u64 = 20_000;
}

impl pallet_evm::Config for Runtime {
type FeeCalculator = BaseFee;
type GasWeightMapping = FixedGasWeightMapping;
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
type CallOrigin = EnsureAddressTruncated;
type WithdrawOrigin = EnsureAddressTruncated;
Expand Down Expand Up @@ -857,3 +848,16 @@ impl_runtime_apis! {
}
}
}

#[cfg(test)]
mod tests {
use super::{Runtime, WeightPerGas};
#[test]
fn configured_base_extrinsic_weight_is_evm_compatible() {
let min_ethereum_transaction_weight = WeightPerGas::get() * 21_000;
let base_extrinsic = <Runtime as frame_system::Config>::BlockWeights::get()
.get(frame_support::weights::DispatchClass::Normal)
.base_extrinsic;
assert!(base_extrinsic <= min_ethereum_transaction_weight);
}
}
4 changes: 2 additions & 2 deletions ts-tests/tests/test-gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ describeWithFrontier("Frontier RPC (Gas)", (context) => {
// Those test are ordered. In general this should be avoided, but due to the time it takes
// to spin up a frontier node, it saves a lot of time.

// EXTRINSIC_GAS_LIMIT = [BLOCK_GAS_LIMIT - BLOCK_GAS_LIMIT * (NORMAL_DISPATCH_RATIO - AVERAGE_ON_INITIALIZE_RATIO) - EXTRINSIC_BASE_Weight] / WEIGHT_PER_GAS = (1_000_000_000_000 * 2 * (0.75-0.1) - 125_000_000) / 20000
const EXTRINSIC_GAS_LIMIT = 64995685;
// EXTRINSIC_GAS_LIMIT = [BLOCK_GAS_LIMIT - BLOCK_GAS_LIMIT * (NORMAL_DISPATCH_RATIO - AVERAGE_ON_INITIALIZE_RATIO)] / WEIGHT_PER_GAS = (1_000_000_000_000 * 2 * (0.75-0.1) - 125_000_000) / 20000
const EXTRINSIC_GAS_LIMIT = 65000000;

it("eth_estimateGas for contract creation", async function () {
// The value returned as an estimation by the evm with estimate mode ON.
Expand Down