Skip to content

Commit

Permalink
Send priority fees to collators (#3120)
Browse files Browse the repository at this point in the history
* feat: send eth tips to collator

* style: fix import order

* fix: tests

* fix: tests

* style: fix formatting

* test: fix test

* test: fix test

* style: formatting

* fix: test

* fix: test

* fix: test

* fix: parameters tests.

* fix: contract tests.

* fix: fix test-eth-pool-resubmit-txn.ts

* fix: fix test-eth-pool-error.ts

* fix: Update balance transfer tests to use CHARLETH_ADDRESS in tests

* style: fix

* fix: Refactor xtokens test and disable tip fee burning

* fix: fix test-contract tests

* fix: commands in update-local-types

* refactor: fee calculation logic and improve modularity.

* fix: FeesTreasuryProportion test logic and helpers

* fix: argument order in calculateFeePortions function call

* test: Add verification for latest block fees and add a check for tips.

* refactor: separate fee and tip calculation

* fix: fee and tip handling logic for clarity and correctness

* refactor: clean up unused imports in Moonbeam runtime

* style: correct indentation in runtime lib.rs

* test: also check LatestBlockFees in eth transactions

* tmp: check if all tests pass

* refactor: remove unnecessary console logs in tests

* tmp: change default value

* Revert "tmp: change default value"

This reverts commit 7b16ab2.

* tmp: change default value

* tmp: change default value

* test: add comment explaining test file

* Revert "tmp: change default value"

This reverts commit 56b62d3.

* Revert "tmp: change default value"

This reverts commit fdab76f.

* feature: send substrate tips to block author

* fix: incorrect generics

* style: fix formatting

* test: refine fee and tip handling logic for runtime tests

* test(runtime): fix incorrect runtime references in tests

* refactor: move all deal with fees logic into common crate

* refactor: remove unused imports

* style: add copyright

* Update runtime/common/src/deal_with_fees.rs

* test: fix test

---------

Co-authored-by: Rodrigo Quelhas <[email protected]>
  • Loading branch information
TarekkMA and RomarQ authored Jan 14, 2025
1 parent fef3821 commit 08ce140
Show file tree
Hide file tree
Showing 25 changed files with 756 additions and 403 deletions.
114 changes: 114 additions & 0 deletions runtime/common/src/deal_with_fees.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2024 Moonbeam foundation
// 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 <http://www.gnu.org/licenses/>.

use frame_support::__private::Get;
use frame_support::pallet_prelude::TypedGet;
use frame_support::traits::fungible::Credit;
use frame_support::traits::tokens::imbalance::ResolveTo;
use frame_support::traits::Imbalance;
use frame_support::traits::OnUnbalanced;
use pallet_treasury::TreasuryAccountId;
use sp_runtime::Perbill;

/// Deal with substrate based fees and tip. This should be used with pallet_transaction_payment.
pub struct DealWithSubstrateFeesAndTip<R, FeesTreasuryProportion>(
sp_std::marker::PhantomData<(R, FeesTreasuryProportion)>,
);
impl<R, FeesTreasuryProportion> DealWithSubstrateFeesAndTip<R, FeesTreasuryProportion>
where
R: pallet_balances::Config + pallet_treasury::Config + pallet_author_inherent::Config,
pallet_author_inherent::Pallet<R>: Get<R::AccountId>,
FeesTreasuryProportion: Get<Perbill>,
{
fn deal_with_fees(amount: Credit<R::AccountId, pallet_balances::Pallet<R>>) {
// Balances pallet automatically burns dropped Credits by decreasing
// total_supply accordingly
let treasury_proportion = FeesTreasuryProportion::get();
let treasury_part = treasury_proportion.deconstruct();
let burn_part = Perbill::one().deconstruct() - treasury_part;
let (_, to_treasury) = amount.ration(burn_part, treasury_part);
ResolveTo::<TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(to_treasury);
}

fn deal_with_tip(amount: Credit<R::AccountId, pallet_balances::Pallet<R>>) {
ResolveTo::<BlockAuthorAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(amount);
}
}

impl<R, FeesTreasuryProportion> OnUnbalanced<Credit<R::AccountId, pallet_balances::Pallet<R>>>
for DealWithSubstrateFeesAndTip<R, FeesTreasuryProportion>
where
R: pallet_balances::Config + pallet_treasury::Config + pallet_author_inherent::Config,
pallet_author_inherent::Pallet<R>: Get<R::AccountId>,
FeesTreasuryProportion: Get<Perbill>,
{
fn on_unbalanceds(
mut fees_then_tips: impl Iterator<Item = Credit<R::AccountId, pallet_balances::Pallet<R>>>,
) {
if let Some(fees) = fees_then_tips.next() {
Self::deal_with_fees(fees);
if let Some(tip) = fees_then_tips.next() {
Self::deal_with_tip(tip);
}
}
}
}

/// Deal with ethereum based fees. To handle tips/priority fees, use DealWithEthereumPriorityFees.
pub struct DealWithEthereumBaseFees<R, FeesTreasuryProportion>(
sp_std::marker::PhantomData<(R, FeesTreasuryProportion)>,
);
impl<R, FeesTreasuryProportion> OnUnbalanced<Credit<R::AccountId, pallet_balances::Pallet<R>>>
for DealWithEthereumBaseFees<R, FeesTreasuryProportion>
where
R: pallet_balances::Config + pallet_treasury::Config,
FeesTreasuryProportion: Get<Perbill>,
{
fn on_nonzero_unbalanced(amount: Credit<R::AccountId, pallet_balances::Pallet<R>>) {
// Balances pallet automatically burns dropped Credits by decreasing
// total_supply accordingly
let treasury_proportion = FeesTreasuryProportion::get();
let treasury_part = treasury_proportion.deconstruct();
let burn_part = Perbill::one().deconstruct() - treasury_part;
let (_, to_treasury) = amount.ration(burn_part, treasury_part);
ResolveTo::<TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(to_treasury);
}
}

pub struct BlockAuthorAccountId<R>(sp_std::marker::PhantomData<R>);
impl<R> TypedGet for BlockAuthorAccountId<R>
where
R: frame_system::Config + pallet_author_inherent::Config,
pallet_author_inherent::Pallet<R>: Get<R::AccountId>,
{
type Type = R::AccountId;
fn get() -> Self::Type {
<pallet_author_inherent::Pallet<R> as Get<R::AccountId>>::get()
}
}

/// Deal with ethereum based priority fees/tips. See DealWithEthereumBaseFees for base fees.
pub struct DealWithEthereumPriorityFees<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<Credit<R::AccountId, pallet_balances::Pallet<R>>>
for DealWithEthereumPriorityFees<R>
where
R: pallet_balances::Config + pallet_author_inherent::Config,
pallet_author_inherent::Pallet<R>: Get<R::AccountId>,
{
fn on_nonzero_unbalanced(amount: Credit<R::AccountId, pallet_balances::Pallet<R>>) {
ResolveTo::<BlockAuthorAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(amount);
}
}
14 changes: 9 additions & 5 deletions runtime/common/src/impl_on_charge_evm_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ macro_rules! impl_on_charge_evm_transaction {
type BalanceFor<T> =
<<T as pallet_evm::Config>::Currency as Inspect<FungibleAccountId<T>>>::Balance;

pub struct OnChargeEVMTransaction<OU>(sp_std::marker::PhantomData<OU>);
pub struct OnChargeEVMTransaction<BaseFeesOU, PriorityFeesOU>(
sp_std::marker::PhantomData<(BaseFeesOU, PriorityFeesOU)>
);

impl<T, OU> OnChargeEVMTransactionT<T> for OnChargeEVMTransaction<OU>
impl<T, BaseFeesOU, PriorityFeesOU> OnChargeEVMTransactionT<T>
for OnChargeEVMTransaction<BaseFeesOU, PriorityFeesOU>
where
T: pallet_evm::Config,
T::Currency: Balanced<pallet_evm::AccountIdOf<T>>,
OU: OnUnbalanced<Credit<pallet_evm::AccountIdOf<T>, T::Currency>>,
BaseFeesOU: OnUnbalanced<Credit<pallet_evm::AccountIdOf<T>, T::Currency>>,
PriorityFeesOU: OnUnbalanced<Credit<pallet_evm::AccountIdOf<T>, T::Currency>>,
U256: UniqueSaturatedInto<<T::Currency as Inspect<pallet_evm::AccountIdOf<T>>>::Balance>,
T::AddressMapping: pallet_evm::AddressMapping<T::AccountId>,
{
Expand All @@ -48,14 +52,14 @@ macro_rules! impl_on_charge_evm_transaction {
base_fee: U256,
already_withdrawn: Self::LiquidityInfo,
) -> Self::LiquidityInfo {
<EVMFungibleAdapter<<T as pallet_evm::Config>::Currency, OU> as OnChargeEVMTransactionT<
<EVMFungibleAdapter<<T as pallet_evm::Config>::Currency, BaseFeesOU> 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);
PriorityFeesOU::on_unbalanced(tip);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
mod apis;
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarking;
pub mod deal_with_fees;
mod impl_moonbeam_xcm_call;
mod impl_moonbeam_xcm_call_tracing;
mod impl_on_charge_evm_transaction;
Expand Down
67 changes: 16 additions & 51 deletions runtime/moonbase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,9 @@ use frame_support::{
parameter_types,
traits::{
fungible::{Balanced, Credit, HoldConsideration, Inspect},
tokens::imbalance::ResolveTo,
tokens::{PayFromAccount, UnityAssetBalanceConversion},
ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse,
EqualPrivilegeOnly, FindAuthor, Imbalance, InstanceFilter, LinearStoragePrice, OnFinalize,
EqualPrivilegeOnly, FindAuthor, InstanceFilter, LinearStoragePrice, OnFinalize,
OnUnbalanced,
},
weights::{
Expand All @@ -90,7 +89,6 @@ use pallet_evm::{
OnChargeEVMTransaction as OnChargeEVMTransactionT, Runner,
};
use pallet_transaction_payment::{FungibleAdapter, Multiplier, TargetedFeeAdjustment};
use pallet_treasury::TreasuryAccountId;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use runtime_params::*;
use scale_info::TypeInfo;
Expand Down Expand Up @@ -338,52 +336,6 @@ impl pallet_balances::Config for Runtime {
type WeightInfo = moonbase_weights::pallet_balances::WeightInfo<Runtime>;
}

pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<Credit<R::AccountId, pallet_balances::Pallet<R>>> for DealWithFees<R>
where
R: pallet_balances::Config + pallet_treasury::Config,
{
// this seems to be called for substrate-based transactions
fn on_unbalanceds(
mut fees_then_tips: impl Iterator<Item = Credit<R::AccountId, pallet_balances::Pallet<R>>>,
) {
if let Some(fees) = fees_then_tips.next() {
let treasury_proportion =
runtime_params::dynamic_params::runtime_config::FeesTreasuryProportion::get();
let treasury_part = treasury_proportion.deconstruct();
let burn_part = Perbill::one().deconstruct() - treasury_part;
let (_, to_treasury) = fees.ration(burn_part, treasury_part);
// Balances pallet automatically burns dropped Credits by decreasing
// total_supply accordingly
ResolveTo::<TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(
to_treasury,
);

// handle tip if there is one
if let Some(tip) = fees_then_tips.next() {
// for now we use the same burn/treasury strategy used for regular fees
let (_, to_treasury) = tip.ration(burn_part, treasury_part);
ResolveTo::<TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(
to_treasury,
);
}
}
}

// this is called from pallet_evm for Ethereum-based transactions
// (technically, it calls on_unbalanced, which calls this when non-zero)
fn on_nonzero_unbalanced(amount: Credit<R::AccountId, pallet_balances::Pallet<R>>) {
// Balances pallet automatically burns dropped Credits by decreasing
// total_supply accordingly
let treasury_proportion =
runtime_params::dynamic_params::runtime_config::FeesTreasuryProportion::get();
let treasury_part = treasury_proportion.deconstruct();
let burn_part = Perbill::one().deconstruct() - treasury_part;
let (_, to_treasury) = amount.ration(burn_part, treasury_part);
ResolveTo::<TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(to_treasury);
}
}

pub struct LengthToFee;
impl WeightToFeePolynomial for LengthToFee {
type Balance = Balance;
Expand All @@ -408,7 +360,13 @@ impl WeightToFeePolynomial for LengthToFee {

impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = FungibleAdapter<Balances, DealWithFees<Runtime>>;
type OnChargeTransaction = FungibleAdapter<
Balances,
DealWithSubstrateFeesAndTip<
Runtime,
dynamic_params::runtime_config::FeesTreasuryProportion,
>,
>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = ConstantMultiplier<Balance, ConstU128<{ currency::WEIGHT_FEE }>>;
type LengthToFee = LengthToFee;
Expand Down Expand Up @@ -542,7 +500,10 @@ impl pallet_evm::Config for Runtime {
type PrecompilesType = MoonbasePrecompiles<Self>;
type PrecompilesValue = PrecompilesValue;
type ChainId = EthereumChainId;
type OnChargeTransaction = OnChargeEVMTransaction<DealWithFees<Runtime>>;
type OnChargeTransaction = OnChargeEVMTransaction<
DealWithEthereumBaseFees<Runtime, dynamic_params::runtime_config::FeesTreasuryProportion>,
DealWithEthereumPriorityFees<Runtime>,
>;
type BlockGasLimit = BlockGasLimit;
type FindAuthor = FindAuthorAdapter<AccountId20, H160, AuthorInherent>;
type OnCreate = ();
Expand Down Expand Up @@ -1496,6 +1457,10 @@ pub type Executive = frame_executive::Executive<

#[cfg(feature = "runtime-benchmarks")]
use moonbeam_runtime_common::benchmarking::BenchmarkHelper;
use moonbeam_runtime_common::deal_with_fees::{
DealWithEthereumBaseFees, DealWithEthereumPriorityFees, DealWithSubstrateFeesAndTip,
};

#[cfg(feature = "runtime-benchmarks")]
mod benches {
frame_support::parameter_types! {
Expand Down
3 changes: 3 additions & 0 deletions runtime/moonbase/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@ pub fn set_parachain_inherent_data() {
use cumulus_primitives_core::PersistedValidationData;
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;

let author = AccountId::from(<pallet_evm::Pallet<Runtime>>::find_author());
pallet_author_inherent::Author::<Runtime>::put(author);

let mut relay_sproof = RelayStateSproofBuilder::default();
relay_sproof.para_id = 100u32.into();
relay_sproof.included_para_head = Some(HeadData(vec![1, 2, 3]));
Expand Down
Loading

0 comments on commit 08ce140

Please sign in to comment.