From fbca52ee6b45b47703d3010f97c11a394da39aea Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Fri, 4 Aug 2023 01:47:31 -0300 Subject: [PATCH 01/15] Proper calculation for the WEIGHT_MILLISECS_PER_BLOCK for EVM --- crates/humanode-runtime/src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/humanode-runtime/src/lib.rs b/crates/humanode-runtime/src/lib.rs index d40a4d97b..665426dbe 100644 --- a/crates/humanode-runtime/src/lib.rs +++ b/crates/humanode-runtime/src/lib.rs @@ -104,6 +104,7 @@ pub use constants::{ equivocation::REPORT_LONGEVITY, im_online::{MAX_KEYS, MAX_PEER_DATA_ENCODING_SIZE, MAX_PEER_IN_HEARTBEATS}, }; +use static_assertions::const_assert; /// An index to a block. pub type BlockNumber = u32; @@ -232,11 +233,14 @@ pub fn native_version() -> NativeVersion { const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); const MAX_BLOCK_LENGTH: u32 = 5 * 1024 * 1024; +/// We allow for 2 seconds of compute with a 6 second average block time. +const EXPECTED_BLOCK_WEIGHT: Weight = + Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX); + parameter_types! { pub const Version: RuntimeVersion = VERSION; - /// We allow for 2 seconds of compute with a 6 second average block time. pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights - ::with_sensible_defaults(Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX), NORMAL_DISPATCH_RATIO); + ::with_sensible_defaults(EXPECTED_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength ::max_with_normal_ratio(MAX_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO); pub SS58Prefix: u16 = ChainProperties::ss58_prefix(); @@ -625,7 +629,11 @@ impl pallet_offences::Config for Runtime { } const BLOCK_GAS_LIMIT: u64 = 75_000_000; -const WEIGHT_MILLISECS_PER_BLOCK: u64 = 2000; + +const WEIGHT_MILLISECS_PER_BLOCK: u64 = EXPECTED_BLOCK_WEIGHT.ref_time() + / frame_support::weights::constants::WEIGHT_REF_TIME_PER_MILLIS; +// An assertion to ensure this value is what we expect it to be here. +const_assert!(WEIGHT_MILLISECS_PER_BLOCK == 2000u64); parameter_types! { pub BlockGasLimit: U256 = U256::from(BLOCK_GAS_LIMIT); From be0ff839e2023fa91521dc17385d4a75204a4501 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Fri, 4 Aug 2023 03:43:13 -0300 Subject: [PATCH 02/15] Zero out the DefaultElasticity --- crates/humanode-runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/humanode-runtime/src/lib.rs b/crates/humanode-runtime/src/lib.rs index 665426dbe..4ba3bce20 100644 --- a/crates/humanode-runtime/src/lib.rs +++ b/crates/humanode-runtime/src/lib.rs @@ -710,7 +710,7 @@ impl pallet_dynamic_fee::Config for Runtime { parameter_types! { pub DefaultBaseFeePerGas: U256 = U256::from(1_000_000_000); - pub DefaultElasticity: Permill = Permill::from_parts(125_000); + pub DefaultElasticity: Permill = Permill::from_parts(0); } pub struct BaseFeeThreshold; From a6c5d3284cb8b7762cdc91816274e738feccf53c Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Tue, 8 Aug 2023 06:20:59 -0300 Subject: [PATCH 03/15] Allow non_snake_case at runtime --- crates/humanode-runtime/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/humanode-runtime/src/lib.rs b/crates/humanode-runtime/src/lib.rs index 4ba3bce20..7fcd371aa 100644 --- a/crates/humanode-runtime/src/lib.rs +++ b/crates/humanode-runtime/src/lib.rs @@ -5,6 +5,8 @@ #![allow(missing_docs, clippy::missing_docs_in_private_items)] // Either generate code at stadard mode, or `no_std`, based on the `std` feature presence. #![cfg_attr(not(feature = "std"), no_std)] +// Runtime impl macros generate non-snake case names. +#![allow(non_snake_case)] // If we're in standard compilation mode, embed the build-script generated code that pulls in // the WASM portion of the runtime, so that it is invocable from the native (aka host) side code. From 8385c9d5e2339a9355b73e070f1097c7463c7e80 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Tue, 15 Aug 2023 03:58:02 -0300 Subject: [PATCH 04/15] Move DefaultBaseFeePerGas value to consts --- crates/humanode-runtime/src/constants.rs | 7 +++++++ crates/humanode-runtime/src/lib.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/humanode-runtime/src/constants.rs b/crates/humanode-runtime/src/constants.rs index 8eaa93f4e..7635f4bc6 100644 --- a/crates/humanode-runtime/src/constants.rs +++ b/crates/humanode-runtime/src/constants.rs @@ -98,3 +98,10 @@ pub mod fees { /// The multiplier to get the fee from length. pub const LENGTH_TO_FEE: Balance = 1; } + +/// EVM fees related constants. +pub mod evm_fees { + /// The multiplier to get the base (in a sense this is what is used as a base for elasticily) + /// fee per gas. + pub const BASE_FEE_PER_GAS: u128 = 1_000_000_000u128; +} diff --git a/crates/humanode-runtime/src/lib.rs b/crates/humanode-runtime/src/lib.rs index 7fcd371aa..27797d8f6 100644 --- a/crates/humanode-runtime/src/lib.rs +++ b/crates/humanode-runtime/src/lib.rs @@ -711,7 +711,7 @@ impl pallet_dynamic_fee::Config for Runtime { } parameter_types! { - pub DefaultBaseFeePerGas: U256 = U256::from(1_000_000_000); + pub DefaultBaseFeePerGas: U256 = U256::from(constants::evm_fees::BASE_FEE_PER_GAS); pub DefaultElasticity: Permill = Permill::from_parts(0); } From 209249c323ce88fc217cef89638209d66f3c71b0 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Tue, 15 Aug 2023 04:23:49 -0300 Subject: [PATCH 05/15] Adjust BLOCK_GAS_LIMIT and move it consts --- crates/humanode-runtime/src/constants.rs | 5 +++++ crates/humanode-runtime/src/lib.rs | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/humanode-runtime/src/constants.rs b/crates/humanode-runtime/src/constants.rs index 7635f4bc6..133aed7bd 100644 --- a/crates/humanode-runtime/src/constants.rs +++ b/crates/humanode-runtime/src/constants.rs @@ -101,6 +101,11 @@ pub mod fees { /// EVM fees related constants. pub mod evm_fees { + /// The max amount of gas per block. + /// Set to match the standard ethereum network block limit. + /// Ref: + pub const BLOCK_GAS_LIMIT: u64 = 15_000_000; + /// The multiplier to get the base (in a sense this is what is used as a base for elasticily) /// fee per gas. pub const BASE_FEE_PER_GAS: u128 = 1_000_000_000u128; diff --git a/crates/humanode-runtime/src/lib.rs b/crates/humanode-runtime/src/lib.rs index 27797d8f6..4448ae506 100644 --- a/crates/humanode-runtime/src/lib.rs +++ b/crates/humanode-runtime/src/lib.rs @@ -630,17 +630,19 @@ impl pallet_offences::Config for Runtime { type OnOffenceHandler = OffenceSlasher; } -const BLOCK_GAS_LIMIT: u64 = 75_000_000; - const WEIGHT_MILLISECS_PER_BLOCK: u64 = EXPECTED_BLOCK_WEIGHT.ref_time() / frame_support::weights::constants::WEIGHT_REF_TIME_PER_MILLIS; // An assertion to ensure this value is what we expect it to be here. const_assert!(WEIGHT_MILLISECS_PER_BLOCK == 2000u64); parameter_types! { - pub BlockGasLimit: U256 = U256::from(BLOCK_GAS_LIMIT); + pub BlockGasLimit: U256 = U256::from(constants::evm_fees::BLOCK_GAS_LIMIT); pub PrecompilesValue: FrontierPrecompiles = FrontierPrecompiles::<_>::default(); - pub WeightPerGas: Weight = Weight::from_ref_time(fp_evm::weight_per_gas(BLOCK_GAS_LIMIT, NORMAL_DISPATCH_RATIO, WEIGHT_MILLISECS_PER_BLOCK)); + pub WeightPerGas: Weight = Weight::from_ref_time(fp_evm::weight_per_gas( + constants::evm_fees::BLOCK_GAS_LIMIT, + NORMAL_DISPATCH_RATIO, + WEIGHT_MILLISECS_PER_BLOCK, + )); } impl pallet_evm_system::Config for Runtime { From a23d32f24e69f6343d2300a0f0155fa30ac84c5a Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Tue, 15 Aug 2023 03:54:09 -0300 Subject: [PATCH 06/15] Adjust the eth rpc E2E test to the target fee value --- utils/e2e-tests/ts/tests/rpc/eth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/e2e-tests/ts/tests/rpc/eth.ts b/utils/e2e-tests/ts/tests/rpc/eth.ts index fe573ca28..d3be04601 100644 --- a/utils/e2e-tests/ts/tests/rpc/eth.ts +++ b/utils/e2e-tests/ts/tests/rpc/eth.ts @@ -31,7 +31,7 @@ describe("eth rpc", () => { describe("fee", () => { describe("when transferring 1 eHMND", () => { const transferValue = ethers.parseEther("1"); - const expectedFee = ethers.parseEther("0.00004"); // TODO: adjust this to a real value of 0.2 + const expectedFee = ethers.parseEther("0.2"); const tolerance = expectedFee / 10n; it("is within the tolerance around the expected cost", async () => { From 139e1fbaebd87ca8fc3a0718b6ee86e614b1b7b9 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Fri, 4 Aug 2023 03:22:40 -0300 Subject: [PATCH 07/15] Adjust the max fee per gas estimates in the irrelevant tests --- crates/humanode-runtime/src/tests/currency_swap.rs | 3 ++- crates/humanode-runtime/src/tests/fixed_supply.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/humanode-runtime/src/tests/currency_swap.rs b/crates/humanode-runtime/src/tests/currency_swap.rs index 6f5a1f90d..887205c44 100644 --- a/crates/humanode-runtime/src/tests/currency_swap.rs +++ b/crates/humanode-runtime/src/tests/currency_swap.rs @@ -12,7 +12,8 @@ use crate::dev_utils::*; use crate::opaque::SessionKeys; pub(crate) static PRECOMPILE_ADDRESS: Lazy = Lazy::new(|| H160::from_low_u64_be(0x900)); -pub(crate) static GAS_PRICE: Lazy = Lazy::new(|| 1_000_000_000u128.into()); +pub(crate) static GAS_PRICE: Lazy = + Lazy::new(|| ::FeeCalculator::min_gas_price().0); const INIT_BALANCE: Balance = 10u128.pow(18 + 6); diff --git a/crates/humanode-runtime/src/tests/fixed_supply.rs b/crates/humanode-runtime/src/tests/fixed_supply.rs index 61780bd42..713727995 100644 --- a/crates/humanode-runtime/src/tests/fixed_supply.rs +++ b/crates/humanode-runtime/src/tests/fixed_supply.rs @@ -384,7 +384,7 @@ fn total_issuance_transaction_fee_ethereum_transact() { let evm_bob_origin = pallet_ethereum::RawOrigin::EthereumTransaction(evm_account_id("EvmBob")); - let gas_price = 20_000_000_000_u128; + let gas_price: u128 = ::FeeCalculator::min_gas_price().0.try_into().unwrap(); let gas_limit = 21000; // This test legacy data transaction obtained from From fe27dc4661ea3f39e0d58b743c42b4bbec436d97 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Fri, 4 Aug 2023 03:43:52 -0300 Subject: [PATCH 08/15] Add runtime unit test for EVM fee value --- crates/humanode-runtime/src/tests/fees.rs | 76 +++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/crates/humanode-runtime/src/tests/fees.rs b/crates/humanode-runtime/src/tests/fees.rs index 3850e5af4..5345ef7ff 100644 --- a/crates/humanode-runtime/src/tests/fees.rs +++ b/crates/humanode-runtime/src/tests/fees.rs @@ -3,6 +3,8 @@ // Allow simple integer arithmetic in tests. #![allow(clippy::integer_arithmetic)] +use ethereum::EIP1559Transaction; + use super::*; use crate::dev_utils::*; use crate::opaque::SessionKeys; @@ -128,6 +130,23 @@ fn assert_fee(call: RuntimeCall, len: u32, expected_fee: Balance, epsilon: Balan ); } +fn assert_evm_fee(call: RuntimeCall, len: u32, expected_fee: Balance, epsilon: Balance) { + let dispath_info = TransactionPayment::query_call_info(call, len); + let effective_fee = dispath_info.partial_fee; + + let lower_threshold = expected_fee - epsilon; + let upper_threshold = expected_fee + epsilon; + + assert!( + effective_fee <= upper_threshold, + "{effective_fee} is not within {epsilon} above {expected_fee} ({effective_fee} > {upper_threshold})" + ); + assert!( + effective_fee >= lower_threshold, + "{effective_fee} is not within {epsilon} below {expected_fee} ({effective_fee} < {lower_threshold})" + ); +} + /// The testing cryptography to match the real one we use for the accounts. /// We use it to simulate the signatures in the test to estimate the tx size. pub mod crypto { @@ -148,6 +167,16 @@ pub mod crypto { } } +fn switch_block() { + use frame_support::traits::{OnFinalize, OnInitialize}; + + if System::block_number() != 0 { + AllPalletsWithSystem::on_finalize(System::block_number()); + } + System::set_block_number(System::block_number() + 1); + AllPalletsWithSystem::on_initialize(System::block_number()); +} + /// A test that validates that a simple balance transfer with a keep alive costs 0.1 HMND. #[test] fn simple_balances_transfer_keep_alive() { @@ -192,3 +221,50 @@ fn simple_balances_transfer_keep_alive() { assert_fee(call, len, expected_fee, epsilon); }) } + +/// A test that validates that a simple EVM balance transfer with a keep alive costs 0.2 HMND. +#[test] +fn simple_evm_transaction() { + // Build the state from the config. + new_test_ext_with().execute_with(move || { + switch_block(); + Timestamp::set(RuntimeOrigin::none(), 1000).unwrap(); + switch_block(); + + // Prepare a sample call to transfer 1 HMND. + let max_fee_per_gas = ::FeeCalculator::min_gas_price().0; + assert_eq!( + max_fee_per_gas, + constants::evm_fees::BASE_FEE_PER_GAS.into() + ); + + let to = H160(hex_literal::hex!( + "0000000000000000000000000000000000000000" + )); + + let call = RuntimeCall::Ethereum(pallet_ethereum::Call::transact { + transaction: EthereumTransaction::EIP1559(EIP1559Transaction { + chain_id: ::ChainId::get(), + nonce: 0.into(), + max_priority_fee_per_gas: 0.into(), + max_fee_per_gas, + gas_limit: 21000.into(), // simple transfer + action: ethereum::TransactionAction::Call(to), + value: U256::from(ONE_BALANCE_UNIT), + input: Default::default(), + access_list: Default::default(), + odd_y_parity: false, + r: Default::default(), + s: Default::default(), + }), + }); + + // The expected fee that we aim to target: 0.2 HMND. + let expected_fee = ONE_BALANCE_UNIT / 5; + + // The tolerance within which the actual fee is allowed to be around the expected fee. + let epsilon = expected_fee / 200; + + assert_evm_fee(call, 0, expected_fee, epsilon); + }) +} From 7b3dab189d95a37651bf79e6f3dfa379d2bdacf5 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Tue, 15 Aug 2023 06:39:45 -0300 Subject: [PATCH 09/15] Drop all the sophisticated fee per gas calculation logic --- crates/humanode-peer/src/chain_spec.rs | 2 - crates/humanode-runtime/src/constants.rs | 4 +- crates/humanode-runtime/src/lib.rs | 48 ++++++----------------- crates/humanode-runtime/src/tests/fees.rs | 5 +-- 4 files changed, 13 insertions(+), 46 deletions(-) diff --git a/crates/humanode-peer/src/chain_spec.rs b/crates/humanode-peer/src/chain_spec.rs index 87d2cf1bf..237be5dbc 100644 --- a/crates/humanode-peer/src/chain_spec.rs +++ b/crates/humanode-peer/src/chain_spec.rs @@ -368,8 +368,6 @@ fn testnet_genesis( }, evm_accounts_mapping: Default::default(), ethereum: EthereumConfig {}, - dynamic_fee: Default::default(), - base_fee: Default::default(), transaction_payment: Default::default(), fees_pot: Default::default(), treasury_pot: Default::default(), diff --git a/crates/humanode-runtime/src/constants.rs b/crates/humanode-runtime/src/constants.rs index 133aed7bd..4c05d1a70 100644 --- a/crates/humanode-runtime/src/constants.rs +++ b/crates/humanode-runtime/src/constants.rs @@ -106,7 +106,5 @@ pub mod evm_fees { /// Ref: pub const BLOCK_GAS_LIMIT: u64 = 15_000_000; - /// The multiplier to get the base (in a sense this is what is used as a base for elasticily) - /// fee per gas. - pub const BASE_FEE_PER_GAS: u128 = 1_000_000_000u128; + pub const FEE_PER_GAS: u128 = 1_000_000_000u128; } diff --git a/crates/humanode-runtime/src/lib.rs b/crates/humanode-runtime/src/lib.rs index 4448ae506..20c9f6aaa 100644 --- a/crates/humanode-runtime/src/lib.rs +++ b/crates/humanode-runtime/src/lib.rs @@ -670,9 +670,18 @@ impl pallet_currency_swap::Config for Runtime { type WeightInfo = (); } +/// A simple fixed fee per gas calculator. +pub struct EvmFeePerGas; + +impl fp_evm::FeeCalculator for EvmFeePerGas { + fn min_gas_price() -> (U256, Weight) { + (constants::evm_fees::FEE_PER_GAS.into(), Weight::zero()) + } +} + impl pallet_evm::Config for Runtime { type AccountProvider = EvmSystem; - type FeeCalculator = BaseFee; + type FeeCalculator = EvmFeePerGas; type GasWeightMapping = pallet_evm::FixedGasWeightMapping; type WeightPerGas = WeightPerGas; type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; @@ -704,39 +713,6 @@ impl pallet_ethereum::Config for Runtime { type PostLogContent = PostBlockAndTxnHashes; } -parameter_types! { - pub BoundDivision: U256 = U256::from(1024); -} - -impl pallet_dynamic_fee::Config for Runtime { - type MinGasPriceBoundDivisor = BoundDivision; -} - -parameter_types! { - pub DefaultBaseFeePerGas: U256 = U256::from(constants::evm_fees::BASE_FEE_PER_GAS); - pub DefaultElasticity: Permill = Permill::from_parts(0); -} - -pub struct BaseFeeThreshold; -impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold { - fn lower() -> Permill { - Permill::zero() - } - fn ideal() -> Permill { - Permill::from_parts(500_000) - } - fn upper() -> Permill { - Permill::from_parts(1_000_000) - } -} - -impl pallet_base_fee::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Threshold = BaseFeeThreshold; - type DefaultBaseFeePerGas = DefaultBaseFeePerGas; - type DefaultElasticity = DefaultElasticity; -} - impl pallet_chain_properties::Config for Runtime {} impl pallet_ethereum_chain_id::Config for Runtime {} @@ -844,8 +820,6 @@ construct_runtime!( Grandpa: pallet_grandpa = 20, Ethereum: pallet_ethereum = 21, EVM: pallet_evm = 22, - DynamicFee: pallet_dynamic_fee = 23, - BaseFee: pallet_base_fee = 24, ImOnline: pallet_im_online = 25, EvmAccountsMapping: pallet_evm_accounts_mapping = 26, TokenClaims: pallet_token_claims = 27, @@ -1406,7 +1380,7 @@ impl_runtime_apis! { } fn elasticity() -> Option { - Some(BaseFee::elasticity()) + None } fn gas_limit_multiplier_support() {} diff --git a/crates/humanode-runtime/src/tests/fees.rs b/crates/humanode-runtime/src/tests/fees.rs index 5345ef7ff..4349015aa 100644 --- a/crates/humanode-runtime/src/tests/fees.rs +++ b/crates/humanode-runtime/src/tests/fees.rs @@ -233,10 +233,7 @@ fn simple_evm_transaction() { // Prepare a sample call to transfer 1 HMND. let max_fee_per_gas = ::FeeCalculator::min_gas_price().0; - assert_eq!( - max_fee_per_gas, - constants::evm_fees::BASE_FEE_PER_GAS.into() - ); + assert_eq!(max_fee_per_gas, constants::evm_fees::FEE_PER_GAS.into()); let to = H160(hex_literal::hex!( "0000000000000000000000000000000000000000" From 316b839451dd35dd564da6b597628e61a62940b6 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Tue, 15 Aug 2023 06:40:18 -0300 Subject: [PATCH 10/15] Set a sensible FEE_PER_GAS value with a proper rationale --- crates/humanode-runtime/src/constants.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/humanode-runtime/src/constants.rs b/crates/humanode-runtime/src/constants.rs index 4c05d1a70..bbc3760a7 100644 --- a/crates/humanode-runtime/src/constants.rs +++ b/crates/humanode-runtime/src/constants.rs @@ -106,5 +106,11 @@ pub mod evm_fees { /// Ref: pub const BLOCK_GAS_LIMIT: u64 = 15_000_000; - pub const FEE_PER_GAS: u128 = 1_000_000_000u128; + /// The amount of fee per gas unit. + /// Comes from the following rationale: + /// - a simple transfer costs 21000 gas + /// - we want the cost of this transfer to be around ~0.2 HMND + /// - so we must charge about 0.2 * 10^18 / 21000 fee per a unit of gas + /// The value below is a nice round number that fits the requirements outlined above. + pub const FEE_PER_GAS: u128 = 10_000_000_000_000; } From df8af2bc260ec93c08c69283126be01e1d074f8b Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Tue, 15 Aug 2023 06:51:50 -0300 Subject: [PATCH 11/15] Cleanup the obsolete base and dynamic fee pallet integrations --- Cargo.lock | 1 - crates/humanode-peer/Cargo.toml | 2 -- crates/humanode-peer/src/benchmarking.rs | 8 ++------ crates/humanode-peer/src/cli/config.rs | 8 -------- crates/humanode-peer/src/configuration.rs | 9 --------- crates/humanode-peer/src/service/inherents.rs | 15 ++------------- crates/humanode-peer/src/service/mod.rs | 4 ---- .../src/tests/claims_and_vesting.rs | 8 -------- .../humanode-runtime/src/tests/genesis_config.rs | 10 +--------- 9 files changed, 5 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00756169a..bc77dc657 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3590,7 +3590,6 @@ dependencies = [ "ngrok-api", "pallet-balances", "pallet-bioauth", - "pallet-dynamic-fee", "pallet-im-online", "pallet-token-claims", "pallet-transaction-payment", diff --git a/crates/humanode-peer/Cargo.toml b/crates/humanode-peer/Cargo.toml index 1dbed2cec..bbf95cabe 100644 --- a/crates/humanode-peer/Cargo.toml +++ b/crates/humanode-peer/Cargo.toml @@ -43,7 +43,6 @@ futures = "0.3" hex = "0.4.3" hex-literal = "0.4" pallet-balances = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } -pallet-dynamic-fee = { default-features = false, git = "https://github.com/humanode-network/frontier", branch = "locked/polkadot-v0.9.38" } pallet-im-online = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } pallet-transaction-payment = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } qr2term = "0.3" @@ -114,7 +113,6 @@ try-runtime = [ "humanode-runtime/try-runtime", "pallet-balances/try-runtime", "pallet-bioauth/try-runtime", - "pallet-dynamic-fee/try-runtime", "pallet-im-online/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-token-claims/try-runtime", diff --git a/crates/humanode-peer/src/benchmarking.rs b/crates/humanode-peer/src/benchmarking.rs index b524558d9..acd3e7581 100644 --- a/crates/humanode-peer/src/benchmarking.rs +++ b/crates/humanode-peer/src/benchmarking.rs @@ -11,7 +11,7 @@ use humanode_runtime::{AccountId, Balance, BalancesCall, SystemCall, SLOT_DURATI use sc_client_api::BlockBackend; use sp_api::ProvideRuntimeApi; use sp_consensus_babe::SlotDuration; -use sp_core::{Encode, Pair, U256}; +use sp_core::{Encode, Pair}; use sp_inherents::{InherentData, InherentDataProvider}; use sp_keyring::Sr25519Keyring; use sp_runtime::{generic, OpaqueExtrinsic, SaturatedConversion}; @@ -87,7 +87,7 @@ impl ExtrinsicBuilder for TransferKeepAliveBuilder { } /// Generates inherent data for the `benchmark overhead` command. -pub fn inherent_benchmark_data(config: &Configuration) -> sc_cli::Result { +pub fn inherent_benchmark_data(_config: &Configuration) -> sc_cli::Result { let mut inherent_data = InherentData::new(); let d = Duration::from_millis(0); @@ -103,10 +103,6 @@ pub fn inherent_benchmark_data(config: &Configuration) -> sc_cli::Result, - /// EVM configuration. - pub evm: Evm, - /// Ethereum RPC configuration. pub ethereum_rpc: Option, @@ -58,12 +55,6 @@ impl BioauthFlow { } } -/// EVM configuration parameters. -pub struct Evm { - /// The dynamic-fee pallet target gas price set by block author. - pub target_gas_price: u64, -} - /// Ethereum RPC configuration parameters. pub struct EthereumRpc { /// Maximum number of blocks to keep the log information available diff --git a/crates/humanode-peer/src/service/inherents.rs b/crates/humanode-peer/src/service/inherents.rs index 1952b0454..787e1d39e 100644 --- a/crates/humanode-peer/src/service/inherents.rs +++ b/crates/humanode-peer/src/service/inherents.rs @@ -2,7 +2,6 @@ use sc_client_api::ProvideUncles; use sc_service::Arc; -use sp_core::U256; use sp_runtime::traits::Block; use crate::time_warp::TimeWarp; @@ -12,8 +11,6 @@ use crate::time_warp::TimeWarp; pub struct Creator { /// Consensus slot duration. pub raw_slot_duration: sp_consensus_babe::SlotDuration, - /// Ethereum gas target price. - pub eth_target_gas_price: u64, /// Time warp peer mode. pub time_warp: Option, /// Client. @@ -25,7 +22,6 @@ pub struct Creator { type InherentDataProviders = ( sp_consensus_babe::inherents::InherentDataProvider, sp_timestamp::InherentDataProvider, - pallet_dynamic_fee::InherentDataProvider, ); /// The inherents creator for block production. @@ -63,10 +59,7 @@ where self.0.raw_slot_duration, ); - let dynamic_fee = - pallet_dynamic_fee::InherentDataProvider(U256::from(self.0.eth_target_gas_price)); - - Ok((slot, timestamp, dynamic_fee)) + Ok((slot, timestamp)) } } @@ -98,10 +91,7 @@ where self.0.raw_slot_duration, ); - let dynamic_fee = - pallet_dynamic_fee::InherentDataProvider(U256::from(self.0.eth_target_gas_price)); - - Ok((slot, timestamp, dynamic_fee)) + Ok((slot, timestamp)) } } @@ -109,7 +99,6 @@ impl Clone for Creator { fn clone(&self) -> Self { Self { raw_slot_duration: self.raw_slot_duration, - eth_target_gas_price: self.eth_target_gas_price, time_warp: self.time_warp.clone(), client: Arc::clone(&self.client), } diff --git a/crates/humanode-peer/src/service/mod.rs b/crates/humanode-peer/src/service/mod.rs index f1fb0b1cc..97e62354e 100644 --- a/crates/humanode-peer/src/service/mod.rs +++ b/crates/humanode-peer/src/service/mod.rs @@ -108,7 +108,6 @@ pub fn new_partial( > { let Configuration { substrate: config, - evm: evm_config, time_warp: time_warp_config, .. } = config; @@ -181,10 +180,8 @@ pub fn new_partial( ); let raw_slot_duration = babe_link.config().slot_duration(); - let eth_target_gas_price = evm_config.target_gas_price; let inherent_data_providers_creator = inherents::Creator { raw_slot_duration, - eth_target_gas_price, client: Arc::clone(&client), time_warp: time_warp_config.clone(), }; @@ -243,7 +240,6 @@ pub async fn new_full(config: Configuration) -> Result St }} }} }}, - "dynamicFee": {{ - "minGasPrice": "0x0" - }}, - "baseFee": {{ - "baseFeePerGas": "0x0", - "elasticity": 0, - "marker": null - }}, "imOnline": {{ "keys": [] }}, diff --git a/crates/humanode-runtime/src/tests/genesis_config.rs b/crates/humanode-runtime/src/tests/genesis_config.rs index 04545e621..b1685ad9f 100644 --- a/crates/humanode-runtime/src/tests/genesis_config.rs +++ b/crates/humanode-runtime/src/tests/genesis_config.rs @@ -94,14 +94,6 @@ fn works() { } } }, - "dynamicFee": { - "minGasPrice": "0x0" - }, - "baseFee": { - "baseFeePerGas": "0x0", - "elasticity": 0, - "marker": null - }, "imOnline": { "keys": [] }, @@ -136,7 +128,7 @@ fn unknown_field() { "unknown field `qwe`, expected one of \ `system`, `bootnodes`, `bioauth`, `babe`, `balances`, `treasuryPot`, \ `feesPot`, `tokenClaimsPot`, `transactionPayment`, `session`, `chainProperties`, \ - `ethereumChainId`, `sudo`, `grandpa`, `ethereum`, `evm`, `dynamicFee`, `baseFee`, \ + `ethereumChainId`, `sudo`, `grandpa`, `ethereum`, `evm`, \ `imOnline`, `evmAccountsMapping`, `tokenClaims`, `nativeToEvmSwapBridgePot`, \ `evmToNativeSwapBridgePot`, `balancedCurrencySwapBridgesInitializer` at line 1 column 6" ); From 5ed6ca8bf17ce85ed4aeb2373976229247084be5 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Wed, 16 Aug 2023 07:01:46 -0300 Subject: [PATCH 12/15] Tweak BLOCK_GAS_LIMIT and EVM fee unit test epsilon --- crates/humanode-runtime/src/constants.rs | 4 ++-- crates/humanode-runtime/src/tests/fees.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/humanode-runtime/src/constants.rs b/crates/humanode-runtime/src/constants.rs index bbc3760a7..53db59cfc 100644 --- a/crates/humanode-runtime/src/constants.rs +++ b/crates/humanode-runtime/src/constants.rs @@ -102,9 +102,9 @@ pub mod fees { /// EVM fees related constants. pub mod evm_fees { /// The max amount of gas per block. - /// Set to match the standard ethereum network block limit. + /// Set to the value that fits our fee requirements. /// Ref: - pub const BLOCK_GAS_LIMIT: u64 = 15_000_000; + pub const BLOCK_GAS_LIMIT: u64 = 60_000_000; /// The amount of fee per gas unit. /// Comes from the following rationale: diff --git a/crates/humanode-runtime/src/tests/fees.rs b/crates/humanode-runtime/src/tests/fees.rs index 4349015aa..2e073f0f6 100644 --- a/crates/humanode-runtime/src/tests/fees.rs +++ b/crates/humanode-runtime/src/tests/fees.rs @@ -260,7 +260,7 @@ fn simple_evm_transaction() { let expected_fee = ONE_BALANCE_UNIT / 5; // The tolerance within which the actual fee is allowed to be around the expected fee. - let epsilon = expected_fee / 200; + let epsilon = expected_fee / 10; assert_evm_fee(call, 0, expected_fee, epsilon); }) From cb85c6e5016de4d864e09b20dcccbafbe4f54ded Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Wed, 16 Aug 2023 07:06:31 -0300 Subject: [PATCH 13/15] Rename the simple_evm_transaction to simple_evm_transaction_via_query_call_info --- crates/humanode-runtime/src/tests/fees.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/humanode-runtime/src/tests/fees.rs b/crates/humanode-runtime/src/tests/fees.rs index 2e073f0f6..ed6c0093c 100644 --- a/crates/humanode-runtime/src/tests/fees.rs +++ b/crates/humanode-runtime/src/tests/fees.rs @@ -223,8 +223,9 @@ fn simple_balances_transfer_keep_alive() { } /// A test that validates that a simple EVM balance transfer with a keep alive costs 0.2 HMND. +/// Computes the fee via [`TransactionPayment::query_call_info`]. #[test] -fn simple_evm_transaction() { +fn simple_evm_transaction_via_query_call_info() { // Build the state from the config. new_test_ext_with().execute_with(move || { switch_block(); From 24d30dea7dbcfbd07f25d3a452ae496efba3af2e Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Wed, 16 Aug 2023 07:07:42 -0300 Subject: [PATCH 14/15] Share the assert_fee fn --- crates/humanode-runtime/src/tests/fees.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/crates/humanode-runtime/src/tests/fees.rs b/crates/humanode-runtime/src/tests/fees.rs index ed6c0093c..ea39cb205 100644 --- a/crates/humanode-runtime/src/tests/fees.rs +++ b/crates/humanode-runtime/src/tests/fees.rs @@ -130,23 +130,6 @@ fn assert_fee(call: RuntimeCall, len: u32, expected_fee: Balance, epsilon: Balan ); } -fn assert_evm_fee(call: RuntimeCall, len: u32, expected_fee: Balance, epsilon: Balance) { - let dispath_info = TransactionPayment::query_call_info(call, len); - let effective_fee = dispath_info.partial_fee; - - let lower_threshold = expected_fee - epsilon; - let upper_threshold = expected_fee + epsilon; - - assert!( - effective_fee <= upper_threshold, - "{effective_fee} is not within {epsilon} above {expected_fee} ({effective_fee} > {upper_threshold})" - ); - assert!( - effective_fee >= lower_threshold, - "{effective_fee} is not within {epsilon} below {expected_fee} ({effective_fee} < {lower_threshold})" - ); -} - /// The testing cryptography to match the real one we use for the accounts. /// We use it to simulate the signatures in the test to estimate the tx size. pub mod crypto { @@ -263,6 +246,6 @@ fn simple_evm_transaction_via_query_call_info() { // The tolerance within which the actual fee is allowed to be around the expected fee. let epsilon = expected_fee / 10; - assert_evm_fee(call, 0, expected_fee, epsilon); + assert_fee(call, 0, expected_fee, epsilon); }) } From 4abd3074737eb7ba95358f06fa35176384f7367d Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Wed, 16 Aug 2023 08:04:59 -0300 Subject: [PATCH 15/15] Add a proper EVM runtime estimate test for the fee cost --- crates/humanode-runtime/src/tests/fees.rs | 126 +++++++++++++++++++--- 1 file changed, 110 insertions(+), 16 deletions(-) diff --git a/crates/humanode-runtime/src/tests/fees.rs b/crates/humanode-runtime/src/tests/fees.rs index ea39cb205..f82818db6 100644 --- a/crates/humanode-runtime/src/tests/fees.rs +++ b/crates/humanode-runtime/src/tests/fees.rs @@ -4,6 +4,7 @@ #![allow(clippy::integer_arithmetic)] use ethereum::EIP1559Transaction; +use frame_support::traits::Currency; use super::*; use crate::dev_utils::*; @@ -12,6 +13,10 @@ use crate::opaque::SessionKeys; const INIT_BALANCE: Balance = 10u128.pow(18 + 6); const ONE_BALANCE_UNIT: Balance = 10u128.pow(18); +const EVM_TEST_ACCOUNT: H160 = H160(hex_literal::hex!( + "FFFF000000000000000000000000000000000000" +)); + /// Build test externalities from the custom genesis. /// Using this call requires manual assertions on the genesis init logic. fn new_test_ext_with() -> sp_io::TestExternalities { @@ -71,21 +76,34 @@ fn new_test_ext_with() -> sp_io::TestExternalities { }, evm: EVMConfig { accounts: { - let evm_pot_accounts = - vec![( + let evm_accounts = vec![ + ( EvmToNativeSwapBridgePot::account_id(), - fp_evm::GenesisAccount { - balance: >::minimum_balance() - .into(), - code: Default::default(), - nonce: Default::default(), - storage: Default::default(), - }, - )]; - - evm_pot_accounts.into_iter().collect() + .into() + ), + ( + EVM_TEST_ACCOUNT, + INIT_BALANCE.into() + ), + ]; + + evm_accounts + .into_iter() + .map(|(account_id, balance)| { + ( + account_id, + fp_evm::GenesisAccount { + balance, + code: Default::default(), + nonce: Default::default(), + storage: Default::default(), + }, + ) + }) + .collect() }, }, ..Default::default() @@ -113,10 +131,7 @@ fn keystore() -> sp_keystore::testing::KeyStore { } #[allow(clippy::integer_arithmetic)] -fn assert_fee(call: RuntimeCall, len: u32, expected_fee: Balance, epsilon: Balance) { - let dispath_info = TransactionPayment::query_call_info(call, len); - let effective_fee = dispath_info.partial_fee; - +fn assert_within(effective_fee: Balance, expected_fee: Balance, epsilon: Balance) { let lower_threshold = expected_fee - epsilon; let upper_threshold = expected_fee + epsilon; @@ -130,6 +145,11 @@ fn assert_fee(call: RuntimeCall, len: u32, expected_fee: Balance, epsilon: Balan ); } +fn assert_fee(call: RuntimeCall, len: u32, expected_fee: Balance, epsilon: Balance) { + let dispath_info = TransactionPayment::query_call_info(call, len); + assert_within(dispath_info.partial_fee, expected_fee, epsilon) +} + /// The testing cryptography to match the real one we use for the accounts. /// We use it to simulate the signatures in the test to estimate the tx size. pub mod crypto { @@ -249,3 +269,77 @@ fn simple_evm_transaction_via_query_call_info() { assert_fee(call, 0, expected_fee, epsilon); }) } + +/// A test that validates that a simple EVM balance transfer with a keep alive costs 0.2 HMND. +/// Computes the fee via an estimate EVM runner invocation. +#[test] +fn simple_evm_transaction_via_runner_estimate() { + // Build the state from the config. + new_test_ext_with().execute_with(move || { + switch_block(); + Timestamp::set(RuntimeOrigin::none(), 1000).unwrap(); + switch_block(); + + let config = ::config(); + + // Prepare a sample call to transfer 1 HMND. + let raw_value = ONE_BALANCE_UNIT; + + let max_fee_per_gas = ::FeeCalculator::min_gas_price().0; + assert_eq!(max_fee_per_gas, constants::evm_fees::FEE_PER_GAS.into()); + + let before = EvmBalances::total_balance(&EVM_TEST_ACCOUNT); + + let from = EVM_TEST_ACCOUNT; + let to = H160(hex_literal::hex!( + "0000000000000000000000000000000000000000" + )); + let data = Default::default(); + let value = raw_value.into(); + let gas_limit = 21000; + let max_fee_per_gas = Some(max_fee_per_gas); + let max_priority_fee_per_gas = None; + let nonce = None; + let access_list = Default::default(); + let is_transactional = true; + let validate = true; + + let call_info = + <::Runner as pallet_evm::Runner>::call( + from, + to, + data, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + is_transactional, + validate, + config, + ) + .unwrap(); + assert_eq!( + call_info, + fp_evm::CallInfo { + exit_reason: fp_evm::ExitReason::Succeed(fp_evm::ExitSucceed::Stopped), + value: vec![], + used_gas: 21000.into(), + logs: vec![] + } + ); + + // The expected fee that we aim to target: 0.2 HMND. + let expected_fee = ONE_BALANCE_UNIT / 5; + + // The tolerance within which the actual fee is allowed to be around the expected fee. + let epsilon = expected_fee / 10; + + let after = EvmBalances::total_balance(&EVM_TEST_ACCOUNT); + + let effective_fee = before - after - raw_value; + + assert_within(effective_fee, expected_fee, epsilon); + }) +}