diff --git a/Cargo.lock b/Cargo.lock index 4323490ba19..cb2502d9b0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2669,7 +2669,7 @@ dependencies = [ [[package]] name = "fc-consensus" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "async-trait", "fc-db", @@ -2688,7 +2688,7 @@ dependencies = [ [[package]] name = "fc-db" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-storage", "kvdb-rocksdb", @@ -2704,7 +2704,7 @@ dependencies = [ [[package]] name = "fc-mapping-sync" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fc-db", "fp-consensus", @@ -2721,7 +2721,7 @@ dependencies = [ [[package]] name = "fc-rpc" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "ethereum", "ethereum-types", @@ -2763,7 +2763,7 @@ dependencies = [ [[package]] name = "fc-rpc-core" version = "1.1.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "ethereum", "ethereum-types", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "fp-consensus" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "ethereum", "parity-scale-codec", @@ -2905,7 +2905,7 @@ dependencies = [ [[package]] name = "fp-evm" version = "3.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "evm", "frame-support", @@ -2918,7 +2918,7 @@ dependencies = [ [[package]] name = "fp-rpc" version = "3.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "ethereum", "ethereum-types", @@ -2935,7 +2935,7 @@ dependencies = [ [[package]] name = "fp-self-contained" version = "1.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "ethereum", "frame-support", @@ -2951,7 +2951,7 @@ dependencies = [ [[package]] name = "fp-storage" version = "2.0.0" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "parity-scale-codec", ] @@ -6976,7 +6976,7 @@ dependencies = [ [[package]] name = "pallet-base-fee" version = "1.0.0" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-evm", "frame-support", @@ -7250,7 +7250,7 @@ dependencies = [ [[package]] name = "pallet-ethereum" version = "4.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "ethereum", "ethereum-types", @@ -7290,7 +7290,7 @@ dependencies = [ [[package]] name = "pallet-evm" version = "6.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "evm", "fp-evm", @@ -7373,7 +7373,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-blake2" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-evm", ] @@ -7381,7 +7381,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-bn128" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-evm", "sp-core", @@ -7391,7 +7391,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-dispatch" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-evm", "frame-support", @@ -7401,7 +7401,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-modexp" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-evm", "num", @@ -7410,7 +7410,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-sha3fips" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-evm", "tiny-keccak", @@ -7419,7 +7419,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-simple" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#7e3e5ff7352445400eb858776d828bf5d7b277be" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.20#ff71b5a8b940c716b1cfd4e9c1fe6b7c384a7fd0" dependencies = [ "fp-evm", "ripemd", diff --git a/runtime/common/src/impl_on_charge_evm_transaction.rs b/runtime/common/src/impl_on_charge_evm_transaction.rs new file mode 100644 index 00000000000..58bced6f145 --- /dev/null +++ b/runtime/common/src/impl_on_charge_evm_transaction.rs @@ -0,0 +1,63 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +#[macro_export] +macro_rules! impl_on_charge_evm_transaction { + {} => { + type CurrencyAccountId = ::AccountId; + + type BalanceFor = + <::Currency as CurrencyT>>::Balance; + + type PositiveImbalanceFor = + <::Currency as CurrencyT>>::PositiveImbalance; + + type NegativeImbalanceFor = + <::Currency as CurrencyT>>::NegativeImbalance; + + pub struct OnChargeEVMTransaction(sp_std::marker::PhantomData); + impl OnChargeEVMTransactionT for OnChargeEVMTransaction + where + T: pallet_evm::Config, + PositiveImbalanceFor: Imbalance, Opposite = NegativeImbalanceFor>, + NegativeImbalanceFor: Imbalance, Opposite = PositiveImbalanceFor>, + OU: OnUnbalanced>, + { + type LiquidityInfo = Option>; + + fn withdraw_fee(who: &H160, fee: U256) -> Result> { + EVMCurrencyAdapter::<::Currency, ()>::withdraw_fee(who, fee) + } + + fn correct_and_deposit_fee( + who: &H160, + corrected_fee: U256, + base_fee: U256, + already_withdrawn: Self::LiquidityInfo, + ) -> Self::LiquidityInfo { + ::Currency, OU> as OnChargeEVMTransactionT< + T, + >>::correct_and_deposit_fee(who, corrected_fee, base_fee, already_withdrawn) + } + + fn pay_priority_fee(tip: Self::LiquidityInfo) { + if let Some(tip) = tip { + OU::on_unbalanced(tip); + } + } + } + } +} diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 65503bd30cc..e8df123a42e 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -19,6 +19,7 @@ use sp_core::H160; mod apis; +mod impl_on_charge_evm_transaction; mod impl_self_contained_call; pub mod migrations; diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs index 2f4b0d49db8..90f07672f8c 100644 --- a/runtime/moonbase/src/lib.rs +++ b/runtime/moonbase/src/lib.rs @@ -423,43 +423,7 @@ where } } -type CurrencyAccountId = ::AccountId; - -type BalanceFor = - <::Currency as CurrencyT>>::Balance; - -type PositiveImbalanceFor = - <::Currency as CurrencyT>>::PositiveImbalance; - -type NegativeImbalanceFor = - <::Currency as CurrencyT>>::NegativeImbalance; - -pub struct OnChargeEVMTransaction(sp_std::marker::PhantomData); -impl OnChargeEVMTransactionT for OnChargeEVMTransaction -where - T: pallet_evm::Config, - PositiveImbalanceFor: Imbalance, Opposite = NegativeImbalanceFor>, - NegativeImbalanceFor: Imbalance, Opposite = PositiveImbalanceFor>, - OU: OnUnbalanced>, -{ - type LiquidityInfo = Option>; - - fn withdraw_fee(who: &H160, fee: U256) -> Result> { - EVMCurrencyAdapter::<::Currency, ()>::withdraw_fee(who, fee) - } - - fn correct_and_deposit_fee( - who: &H160, - corrected_fee: U256, - already_withdrawn: Self::LiquidityInfo, - ) { - ::Currency, OU> as OnChargeEVMTransactionT< - T, - >>::correct_and_deposit_fee(who, corrected_fee, already_withdrawn) - } - - fn pay_priority_fee(_tip: U256) {} -} +runtime_common::impl_on_charge_evm_transaction!(); impl pallet_evm::Config for Runtime { type FeeCalculator = FixedGasPrice; diff --git a/runtime/moonbase/tests/integration_test.rs b/runtime/moonbase/tests/integration_test.rs index f29b048accf..33902b3b22c 100644 --- a/runtime/moonbase/tests/integration_test.rs +++ b/runtime/moonbase/tests/integration_test.rs @@ -26,8 +26,8 @@ use frame_support::{ assert_noop, assert_ok, dispatch::Dispatchable, traits::{ - fungible::Inspect, fungibles::Inspect as FungiblesInspect, EnsureOrigin, PalletInfo, - StorageInfo, StorageInfoTrait, + fungible::Inspect, fungibles::Inspect as FungiblesInspect, Currency as CurrencyT, + EnsureOrigin, PalletInfo, StorageInfo, StorageInfoTrait, }, weights::{DispatchClass, Weight}, StorageHasher, Twox128, @@ -2444,6 +2444,112 @@ fn refund_ed_0_evm() { }); } +#[test] +fn author_does_not_receive_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * UNIT) + (21_000 * (500 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + // Some block author as seen by pallet-evm. + let author = AccountId::from(>::find_author()); + // Currently the default impl of the evm uses `deposit_into_existing`. + // If we were to use this implementation, and for an author to receive eventual tips, + // the account needs to be somehow initialized, otherwise the deposit would fail. + Balances::make_free_balance_be(&author, 100 * UNIT); + + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(300 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(200 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + // Author free balance didn't change. + assert_eq!(Balances::free_balance(author), 100 * UNIT,); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_with_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * UNIT) + (21_000 * (2 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(2 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(1 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 1 GWEI base fee + 1 GWEI tip. + let fee = ((2 * GIGAWEI) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbase_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_without_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * UNIT) + (21_000 * (2 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(1 * GIGAWEI), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 1 GWEI base fee. + let fee = ((1 * GIGAWEI) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbase_runtime::Treasury::pot(), expected_treasury); + }); +} + #[test] fn root_can_change_default_xcm_vers() { ExtBuilder::default() diff --git a/runtime/moonbeam/src/lib.rs b/runtime/moonbeam/src/lib.rs index 88d1c3b54e3..ead529dcda9 100644 --- a/runtime/moonbeam/src/lib.rs +++ b/runtime/moonbeam/src/lib.rs @@ -41,9 +41,9 @@ use frame_support::{ pallet_prelude::DispatchResult, parameter_types, traits::{ - ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, EnsureOneOf, - EqualPrivilegeOnly, Imbalance, InstanceFilter, OffchainWorker, OnFinalize, OnIdle, - OnInitialize, OnRuntimeUpgrade, OnUnbalanced, + ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, + Currency as CurrencyT, EnsureOneOf, EqualPrivilegeOnly, Imbalance, InstanceFilter, + OffchainWorker, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade, OnUnbalanced, }, weights::{ constants::{RocksDbWeight, WEIGHT_PER_SECOND}, @@ -61,8 +61,8 @@ use pallet_balances::NegativeImbalance; use pallet_ethereum::Call::transact; use pallet_ethereum::Transaction as EthereumTransaction; use pallet_evm::{ - Account as EVMAccount, EnsureAddressNever, EnsureAddressRoot, FeeCalculator, GasWeightMapping, - Runner, + Account as EVMAccount, EVMCurrencyAdapter, EnsureAddressNever, EnsureAddressRoot, + FeeCalculator, GasWeightMapping, OnChargeEVMTransaction as OnChargeEVMTransactionT, Runner, }; use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; pub use parachain_staking::{InflationInfo, Range}; @@ -393,6 +393,8 @@ where } } +runtime_common::impl_on_charge_evm_transaction!(); + impl pallet_evm::Config for Runtime { type FeeCalculator = FixedGasPrice; type GasWeightMapping = MoonbeamGasWeightMapping; @@ -406,7 +408,7 @@ impl pallet_evm::Config for Runtime { type PrecompilesType = MoonbeamPrecompiles; type PrecompilesValue = PrecompilesValue; type ChainId = EthereumChainId; - type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter>; + type OnChargeTransaction = OnChargeEVMTransaction>; type BlockGasLimit = BlockGasLimit; type FindAuthor = FindAuthorAdapter; type WeightInfo = pallet_evm::weights::SubstrateWeight; diff --git a/runtime/moonbeam/tests/integration_test.rs b/runtime/moonbeam/tests/integration_test.rs index 2dd64a2a953..c31b17ed8f8 100644 --- a/runtime/moonbeam/tests/integration_test.rs +++ b/runtime/moonbeam/tests/integration_test.rs @@ -26,8 +26,8 @@ use frame_support::{ assert_noop, assert_ok, dispatch::Dispatchable, traits::{ - fungible::Inspect, fungibles::Inspect as FungiblesInspect, EnsureOrigin, PalletInfo, - StorageInfo, StorageInfoTrait, + fungible::Inspect, fungibles::Inspect as FungiblesInspect, Currency as CurrencyT, + EnsureOrigin, PalletInfo, StorageInfo, StorageInfoTrait, }, weights::{DispatchClass, Weight}, StorageHasher, Twox128, @@ -1255,6 +1255,112 @@ fn refund_ed_0_evm() { }); } +#[test] +fn author_does_not_receive_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * GLMR) + (21_000 * (500 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + // Some block author as seen by pallet-evm. + let author = AccountId::from(>::find_author()); + // Currently the default impl of the evm uses `deposit_into_existing`. + // If we were to use this implementation, and for an author to receive eventual tips, + // the account needs to be somehow initialized, otherwise the deposit would fail. + Balances::make_free_balance_be(&author, 100 * GLMR); + + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(300 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(200 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + // Author free balance didn't change. + assert_eq!(Balances::free_balance(author), 100 * GLMR,); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_with_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * GLMR) + (21_000 * (200 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(200 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(100 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 100 GWEI base fee + 100 GWEI tip. + let fee = ((200 * GIGAWEI) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbeam_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_without_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * GLMR) + (21_000 * (200 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(100 * GIGAWEI), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 100 GWEI base fee. + let fee = ((100 * GIGAWEI) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbeam_runtime::Treasury::pot(), expected_treasury); + }); +} + #[test] fn root_can_change_default_xcm_vers() { ExtBuilder::default() diff --git a/runtime/moonriver/src/lib.rs b/runtime/moonriver/src/lib.rs index 4bc198f3f63..3c8538953f7 100644 --- a/runtime/moonriver/src/lib.rs +++ b/runtime/moonriver/src/lib.rs @@ -41,9 +41,9 @@ use frame_support::{ pallet_prelude::DispatchResult, parameter_types, traits::{ - ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, EnsureOneOf, - EqualPrivilegeOnly, Imbalance, InstanceFilter, OffchainWorker, OnFinalize, OnIdle, - OnInitialize, OnRuntimeUpgrade, OnUnbalanced, + ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, + Currency as CurrencyT, EnsureOneOf, EqualPrivilegeOnly, Imbalance, InstanceFilter, + OffchainWorker, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade, OnUnbalanced, }, weights::{ constants::{RocksDbWeight, WEIGHT_PER_SECOND}, @@ -62,8 +62,8 @@ use pallet_balances::NegativeImbalance; use pallet_ethereum::Call::transact; use pallet_ethereum::Transaction as EthereumTransaction; use pallet_evm::{ - Account as EVMAccount, EnsureAddressNever, EnsureAddressRoot, FeeCalculator, GasWeightMapping, - Runner, + Account as EVMAccount, EVMCurrencyAdapter, EnsureAddressNever, EnsureAddressRoot, + FeeCalculator, GasWeightMapping, OnChargeEVMTransaction as OnChargeEVMTransactionT, Runner, }; use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; pub use parachain_staking::{InflationInfo, Range}; @@ -415,6 +415,8 @@ where } } +runtime_common::impl_on_charge_evm_transaction!(); + impl pallet_evm::Config for Runtime { type FeeCalculator = FixedGasPrice; type GasWeightMapping = MoonbeamGasWeightMapping; @@ -428,7 +430,7 @@ impl pallet_evm::Config for Runtime { type PrecompilesType = MoonriverPrecompiles; type PrecompilesValue = PrecompilesValue; type ChainId = EthereumChainId; - type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter>; + type OnChargeTransaction = OnChargeEVMTransaction>; type BlockGasLimit = BlockGasLimit; type FindAuthor = FindAuthorAdapter; type WeightInfo = pallet_evm::weights::SubstrateWeight; diff --git a/runtime/moonriver/tests/integration_test.rs b/runtime/moonriver/tests/integration_test.rs index 928421532ed..c57ea17670c 100644 --- a/runtime/moonriver/tests/integration_test.rs +++ b/runtime/moonriver/tests/integration_test.rs @@ -26,8 +26,8 @@ use frame_support::{ assert_noop, assert_ok, dispatch::Dispatchable, traits::{ - fungible::Inspect, fungibles::Inspect as FungiblesInspect, EnsureOrigin, PalletInfo, - StorageInfo, StorageInfoTrait, + fungible::Inspect, fungibles::Inspect as FungiblesInspect, Currency as CurrencyT, + EnsureOrigin, PalletInfo, StorageInfo, StorageInfoTrait, }, weights::{DispatchClass, Weight}, StorageHasher, Twox128, @@ -1243,6 +1243,112 @@ fn refund_ed_0_evm() { }); } +#[test] +fn author_does_not_receive_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * MOVR) + (21_000 * (500 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + // Some block author as seen by pallet-evm. + let author = AccountId::from(>::find_author()); + // Currently the default impl of the evm uses `deposit_into_existing`. + // If we were to use this implementation, and for an author to receive eventual tips, + // the account needs to be somehow initialized, otherwise the deposit would fail. + Balances::make_free_balance_be(&author, 100 * MOVR); + + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(300 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(200 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + // Author free balance didn't change. + assert_eq!(Balances::free_balance(author), 100 * MOVR,); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_with_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * MOVR) + (21_000 * (2 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(2 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(1 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 1 GWEI base fee + 1 GWEI tip. + let fee = ((2 * GIGAWEI) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonriver_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_without_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * MOVR) + (21_000 * (2 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(Call::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(1 * GIGAWEI), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::Origin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 1 GWEI base fee. + let fee = ((1 * GIGAWEI) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonriver_runtime::Treasury::pot(), expected_treasury); + }); +} + #[test] fn root_can_change_default_xcm_vers() { ExtBuilder::default()