diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 0f31271e06..dc9b86146b 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -641,14 +641,13 @@ pub trait OnChargeEVMTransaction { /// After the transaction was executed the actual fee can be calculated. /// This function should refund any overpaid fees and optionally deposit /// the corrected amount. + /// `actual_priority_fee`: Introduced in EIP1559 to handle the priority tip payment to the block Author. fn correct_and_deposit_fee( who: &H160, corrected_fee: U256, + actual_priority_fee: Option, already_withdrawn: Self::LiquidityInfo, ); - - /// Introduced in EIP1559 to handle the priority tip payment to the block Author. - fn pay_priority_fee(tip: U256); } /// Implements the transaction payment for a pallet implementing the `Currency` @@ -692,6 +691,7 @@ where fn correct_and_deposit_fee( who: &H160, corrected_fee: U256, + actual_priority_fee: Option, already_withdrawn: Self::LiquidityInfo, ) { if let Some(paid) = already_withdrawn { @@ -730,13 +730,17 @@ where .offset(refund_imbalance) .same() .unwrap_or_else(|_| C::NegativeImbalance::zero()); - OU::on_unbalanced(adjusted_paid); - } - } - fn pay_priority_fee(tip: U256) { - let account_id = T::AddressMapping::into_account_id(>::find_author()); - let _ = C::deposit_into_existing(&account_id, tip.low_u128().unique_saturated_into()); + let tip = if let Some(priority_tip) = actual_priority_fee { + priority_tip.low_u128().unique_saturated_into() + } else { + C::Balance::zero() + }; + + // Call someone else to handle the imbalance (fee and tip separately) + let (tip, base_fee) = adjusted_paid.split(tip); + OU::on_unbalanceds(Some(base_fee).into_iter().chain(Some(tip))); + } } } @@ -761,12 +765,9 @@ impl OnChargeEVMTransaction for () fn correct_and_deposit_fee( who: &H160, corrected_fee: U256, + tip: Option, already_withdrawn: Self::LiquidityInfo, ) { - ::Currency, ()> as OnChargeEVMTransaction>::correct_and_deposit_fee(who, corrected_fee, already_withdrawn) - } - - fn pay_priority_fee(tip: U256) { - ::Currency, ()> as OnChargeEVMTransaction>::pay_priority_fee(tip); + ::Currency, ()> as OnChargeEVMTransaction>::correct_and_deposit_fee(who, corrected_fee, tip, already_withdrawn) } } diff --git a/frame/evm/src/mock.rs b/frame/evm/src/mock.rs index 39d580d2ca..fc39c41a31 100644 --- a/frame/evm/src/mock.rs +++ b/frame/evm/src/mock.rs @@ -19,7 +19,7 @@ use frame_support::{ parameter_types, - traits::{ConstU32, FindAuthor}, + traits::{ConstU32, Currency, FindAuthor, OnUnbalanced}, ConsensusEngineId, }; use sp_core::{H160, H256, U256}; @@ -29,7 +29,10 @@ use sp_runtime::{ }; use sp_std::{boxed::Box, prelude::*, str::FromStr}; -use crate::{EnsureAddressNever, EnsureAddressRoot, FeeCalculator, IdentityAddressMapping}; +use crate::{ + AddressMapping, EVMCurrencyAdapter, EnsureAddressNever, EnsureAddressRoot, FeeCalculator, + IdentityAddressMapping, +}; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -122,6 +125,30 @@ impl FindAuthor for FindAuthorTruncated { } } +type NegativeImbalance = >::NegativeImbalance; + +impl OnUnbalanced for FindAuthorTruncated { + fn on_nonzero_unbalanced(amount: NegativeImbalance) { + let author = H160::from_str("1234500000000000000000000000000000000000").unwrap(); + let author_substrate = ::AddressMapping::into_account_id(author); + Balances::resolve_creating(&author_substrate, amount); + } +} + +pub struct DealWithFees; +impl OnUnbalanced for DealWithFees { + fn on_unbalanceds(mut fees_then_tips: impl Iterator) { + if let Some(_fees) = fees_then_tips.next() { + // 1. for fee, default to be burned. + + // 2. for tips, if any, 100% to author. + if let Some(tips) = fees_then_tips.next() { + FindAuthorTruncated::on_unbalanced(tips); + } + } + } +} + impl crate::Config for Test { type FeeCalculator = FixedGasPrice; type GasWeightMapping = (); @@ -138,7 +165,7 @@ impl crate::Config for Test { type PrecompilesValue = (); type ChainId = (); type BlockGasLimit = (); - type OnChargeTransaction = (); + type OnChargeTransaction = EVMCurrencyAdapter; type BlockHashMapping = crate::SubstrateBlockHashMapping; type FindAuthor = FindAuthorTruncated; } diff --git a/frame/evm/src/runner/stack.rs b/frame/evm/src/runner/stack.rs index 47cf2751fe..91be595809 100644 --- a/frame/evm/src/runner/stack.rs +++ b/frame/evm/src/runner/stack.rs @@ -171,10 +171,15 @@ impl Runner { // Refunded 200 - 40 = 160. // Tip 5 * 6 = 30. // Burned 200 - (160 + 30) = 10. Which is equivalent to gas_used * base_fee. - T::OnChargeTransaction::correct_and_deposit_fee(&source, actual_fee, fee); - if let Some(actual_priority_fee) = actual_priority_fee { - T::OnChargeTransaction::pay_priority_fee(actual_priority_fee); - } + // + // The `refund` = `fee` - `actual_fee`, and `actual_fee` = `base` + `tip` will be handled by `OnUnbalanced` + // The `actual_fee` can be burned or reward to block authors. + T::OnChargeTransaction::correct_and_deposit_fee( + &source, + actual_fee, + actual_priority_fee, + fee, + ); let state = executor.into_state(); diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index 8e2fafe2fb..c29bb45560 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -126,8 +126,8 @@ fn fee_deduction() { let imbalance = <::OnChargeTransaction as OnChargeEVMTransaction>::withdraw_fee(&evm_addr, U256::from(10)).unwrap(); assert_eq!(Balances::free_balance(&substrate_addr), 90); - // Refund fees as 5 units - <::OnChargeTransaction as OnChargeEVMTransaction>::correct_and_deposit_fee(&evm_addr, U256::from(5), imbalance); + // Refund fees as 5 units, priority fees as 0 uints + <::OnChargeTransaction as OnChargeEVMTransaction>::correct_and_deposit_fee(&evm_addr, U256::from(5), None,imbalance); assert_eq!(Balances::free_balance(&substrate_addr), 95); }); }