Skip to content

Commit

Permalink
Merge pull request paritytech#6 from availproject/marko/support-custo…
Browse files Browse the repository at this point in the history
…m-fees

Added Custom Dispatch Fee
  • Loading branch information
markopoloparadox authored May 31, 2024
2 parents b8f49aa + fcd92e9 commit 556f894
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
5 changes: 5 additions & 0 deletions substrate/frame/support/procedural/src/pallet/expand/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,15 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
dyn #frame_support::dispatch::PaysFee<( #( & #args_type, )* )>
>::pays_fee(&__pallet_base_weight, ( #( #args_name, )* ));

let __pallet_fee_modifier = <
dyn #frame_support::dispatch::CustomDispatchFee<( #( & #args_type, )* )>
>::custom_dispatch_fee(&__pallet_base_weight, ( #( #args_name, )* ));

#frame_support::dispatch::DispatchInfo {
weight: __pallet_weight,
class: __pallet_class,
pays_fee: __pallet_pays_fee,
fee_modifier: __pallet_fee_modifier,
}
},
)*
Expand Down
58 changes: 58 additions & 0 deletions substrate/frame/support/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,19 @@ pub trait PaysFee<T> {
fn pays_fee(&self, _target: T) -> Pays;
}

/// Indicates if dispatch function should customize how the fees are getting calculated.
pub trait CustomDispatchFee<T> {
fn custom_dispatch_fee(&self, _target: T) -> DispatchFeeModifier;
}

/// Defines how the fees are getting modified.
#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
pub struct DispatchFeeModifier {
pub weight_maximum_fee: Option<u128>,
pub weight_fee_divider: Option<u32>,
pub weight_fee_multiplier: Option<u32>
}

/// Explicit enum to denote if a transaction pays fee or not.
#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)]
pub enum Pays {
Expand Down Expand Up @@ -242,6 +255,8 @@ pub struct DispatchInfo {
pub class: DispatchClass,
/// Does this transaction pay fees.
pub pays_fee: Pays,
/// Does this transaction have custom fees.
pub fee_modifier: DispatchFeeModifier,
}

/// A `Dispatchable` function (aka transaction) that can carry some static information along with
Expand Down Expand Up @@ -400,6 +415,7 @@ impl<Call: Encode + GetDispatchInfo, Extra: Encode> GetDispatchInfo
weight: Weight::from_parts(self.encode().len() as _, 0),
pays_fee: Pays::Yes,
class: self.call.get_dispatch_info().class,
fee_modifier: DispatchFeeModifier::default(),
}
}
}
Expand Down Expand Up @@ -518,18 +534,36 @@ impl<T> WeighData<T> for (Weight, DispatchClass, Pays) {
}
}

impl<T> WeighData<T> for (Weight, DispatchClass, DispatchFeeModifier) {
fn weigh_data(&self, args: T) -> Weight {
return self.0.weigh_data(args)
}
}

impl<T> ClassifyDispatch<T> for (Weight, DispatchClass) {
fn classify_dispatch(&self, _: T) -> DispatchClass {
self.1
}
}

impl<T> ClassifyDispatch<T> for (Weight, DispatchClass, DispatchFeeModifier) {
fn classify_dispatch(&self, _: T) -> DispatchClass {
self.1
}
}

impl<T> PaysFee<T> for (Weight, DispatchClass) {
fn pays_fee(&self, _: T) -> Pays {
Pays::Yes
}
}

impl<T> PaysFee<T> for (Weight, DispatchClass, DispatchFeeModifier) {
fn pays_fee(&self, _: T) -> Pays {
Pays::Yes
}
}

impl<T> WeighData<T> for (Weight, Pays) {
fn weigh_data(&self, args: T) -> Weight {
return self.0.weigh_data(args)
Expand Down Expand Up @@ -579,6 +613,30 @@ impl<T> ClassifyDispatch<T> for (Weight, DispatchClass, Pays) {
}
}

impl<T> CustomDispatchFee<T> for Weight {
fn custom_dispatch_fee(&self, _: T) -> DispatchFeeModifier {
DispatchFeeModifier::default()
}
}

impl<T> CustomDispatchFee<T> for (Weight, DispatchClass) {
fn custom_dispatch_fee(&self, _: T) -> DispatchFeeModifier {
DispatchFeeModifier::default()
}
}

impl<T> CustomDispatchFee<T> for (Weight, DispatchFeeModifier) {
fn custom_dispatch_fee(&self, _: T) -> DispatchFeeModifier {
self.1
}
}

impl<T> CustomDispatchFee<T> for (Weight, DispatchClass, DispatchFeeModifier) {
fn custom_dispatch_fee(&self, _: T) -> DispatchFeeModifier {
self.2
}
}

// TODO: Eventually remove these

impl<T> ClassifyDispatch<T> for u64 {
Expand Down
23 changes: 21 additions & 2 deletions substrate/frame/transaction-payment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ use scale_info::TypeInfo;
use frame_support::{
dispatch::{
DispatchClass, DispatchInfo, DispatchResult, GetDispatchInfo, Pays, PostDispatchInfo,
DispatchFeeModifier,
},
traits::{Defensive, EstimateCallFee, Get},
weights::{Weight, WeightToFee},
Expand All @@ -71,6 +72,7 @@ use sp_runtime::{
};
use sp_std::prelude::*;
pub use types::{FeeDetails, InclusionFee, RuntimeDispatchInfo};
use sp_runtime::traits::CheckedDiv;

#[cfg(test)]
mod mock;
Expand Down Expand Up @@ -586,7 +588,7 @@ impl<T: Config> Pallet<T> {
where
T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
{
Self::compute_fee_raw(len, info.weight, tip, info.pays_fee, info.class)
Self::compute_fee_raw(len, info.weight, tip, info.pays_fee, info.class, info.fee_modifier)
}

/// Compute the actual post dispatch fee for a particular transaction.
Expand Down Expand Up @@ -621,6 +623,7 @@ impl<T: Config> Pallet<T> {
tip,
post_info.pays_fee(info),
info.class,
info.fee_modifier,
)
}

Expand All @@ -630,18 +633,34 @@ impl<T: Config> Pallet<T> {
tip: BalanceOf<T>,
pays_fee: Pays,
class: DispatchClass,
fee_modifier: DispatchFeeModifier,
) -> FeeDetails<BalanceOf<T>> {
if pays_fee == Pays::Yes {
// the adjustable part of the fee.
let unadjusted_weight_fee = Self::weight_to_fee(weight);
let multiplier = Self::next_fee_multiplier();
// final adjusted weight fee.
let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee);
let mut adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee);

// length fee. this is adjusted via `LengthToFee`.
let len_fee = Self::length_to_fee(len);

let base_fee = Self::weight_to_fee(T::BlockWeights::get().get(class).base_extrinsic);

// Custom code
if let Some(fee_multiplier) = fee_modifier.weight_fee_multiplier {
adjusted_weight_fee = adjusted_weight_fee.saturating_mul(fee_multiplier.into());
}

if let Some(fee_divider) = fee_modifier.weight_fee_divider {
adjusted_weight_fee = adjusted_weight_fee.checked_div(&fee_divider.into()).unwrap_or_else(|| adjusted_weight_fee);
}

if let Some(maximum_fee) = fee_modifier.weight_maximum_fee {
let maximum_fee = maximum_fee.saturated_into();
adjusted_weight_fee = adjusted_weight_fee.min(maximum_fee);
}

FeeDetails {
inclusion_fee: Some(InclusionFee { base_fee, len_fee, adjusted_weight_fee }),
tip,
Expand Down

0 comments on commit 556f894

Please sign in to comment.