Skip to content

Commit

Permalink
Merge pull request #17 from availproject/toufeeq/fix-fee-payment
Browse files Browse the repository at this point in the history
Backported fee payment fix
  • Loading branch information
ToufeeqP authored Oct 3, 2024
2 parents fc206fa + 1fa0dae commit f5587b3
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 20 deletions.
2 changes: 1 addition & 1 deletion substrate/bin/minimal/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl pallet_timestamp::Config for Runtime {}

#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)]
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter<Balances, ()>;
type WeightToFee = NoFee<<Self as pallet_balances::Config>::Balance>;
type LengthToFee = FixedFee<1, <Self as pallet_balances::Config>::Balance>;
}
Expand Down
4 changes: 2 additions & 2 deletions substrate/bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub use frame_support::{
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier};
use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier};
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{Perbill, Permill};
Expand Down Expand Up @@ -236,7 +236,7 @@ parameter_types! {

impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = IdentityFee<Balance>;
Expand Down
2 changes: 2 additions & 0 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use pallet_nfts::PalletFeatures;
use pallet_nis::WithMaximumOf;
use pallet_session::historical as pallet_session_historical;
#[allow(deprecated)]
pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment};
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use pallet_tx_pause::RuntimeCallNameOf;
Expand Down Expand Up @@ -544,6 +545,7 @@ parameter_types! {
pub MaximumMultiplier: Multiplier = Bounded::max_value();
}

#[allow(deprecated)]
impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/balances/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use frame_support::{
weights::{IdentityFee, Weight},
};
use frame_system::{self as system, RawOrigin};
use pallet_transaction_payment::{ChargeTransactionPayment, CurrencyAdapter, Multiplier};
use pallet_transaction_payment::{ChargeTransactionPayment, FungibleAdapter, Multiplier};
use scale_info::TypeInfo;
use sp_core::{hexdisplay::HexDisplay, H256};
use sp_io;
Expand Down Expand Up @@ -119,7 +119,7 @@ impl frame_system::Config for Test {

impl pallet_transaction_payment::Config for Test {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Pallet<Test>, ()>;
type OnChargeTransaction = FungibleAdapter<Pallet<Test>, ()>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<u64>;
type LengthToFee = IdentityFee<u64>;
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ mod tests {
};
use frame_system::{ChainContext, LastRuntimeUpgrade, LastRuntimeUpgradeInfo};
use pallet_balances::Call as BalancesCall;
use pallet_transaction_payment::CurrencyAdapter;
use pallet_transaction_payment::FungibleAdapter;

const TEST_KEY: &[u8] = b":test:key:";

Expand Down Expand Up @@ -966,7 +966,7 @@ mod tests {
}
impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use frame_support::{
use frame_system as system;
use frame_system::{EnsureRoot, EnsureSignedBy};
use pallet_asset_conversion::{Ascending, Chain, WithFirstAsset};
use pallet_transaction_payment::CurrencyAdapter;
use pallet_transaction_payment::FungibleAdapter;
use sp_core::H256;
use sp_runtime::{
traits::{AccountIdConversion, BlakeTwo256, IdentityLookup, SaturatedConversion},
Expand Down Expand Up @@ -170,7 +170,7 @@ impl OnUnbalanced<pallet_balances::NegativeImbalance<Runtime>> for DealWithFees

impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
type OnChargeTransaction = FungibleAdapter<Balances, DealWithFees>;
type WeightToFee = WeightToFee;
type LengthToFee = TransactionByteFee;
type FeeMultiplierUpdate = ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use frame_support::{
};
use frame_system as system;
use frame_system::EnsureRoot;
use pallet_transaction_payment::CurrencyAdapter;
use pallet_transaction_payment::FungibleAdapter;
use sp_core::H256;
use sp_runtime::traits::{BlakeTwo256, ConvertInto, IdentityLookup, SaturatedConversion};

Expand Down Expand Up @@ -138,7 +138,7 @@ impl WeightToFeeT for TransactionByteFee {

impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
type WeightToFee = WeightToFee;
type LengthToFee = TransactionByteFee;
type FeeMultiplierUpdate = ();
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/transaction-payment/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ impl OnUnbalanced<pallet_balances::NegativeImbalance<Runtime>> for DealWithFees

impl Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
type OnChargeTransaction = FungibleAdapter<Balances, DealWithFees>;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = WeightToFee;
type LengthToFee = TransactionByteFee;
Expand Down
90 changes: 83 additions & 7 deletions substrate/frame/transaction-payment/src/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ use sp_runtime::{
use sp_std::marker::PhantomData;

use frame_support::{
traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReasons},
traits::{
fungible::{Balanced, Credit, Debt, Inspect},
tokens::Precision,
Currency, ExistenceRequirement, Imbalance, OnUnbalanced, TryDrop, WithdrawReasons,
},
unsigned::TransactionValidityError,
};

Expand Down Expand Up @@ -66,18 +70,90 @@ pub trait OnChargeTransaction<T: Config> {
) -> Result<(), TransactionValidityError>;
}

/// Implements the transaction payment for a pallet implementing the `Currency`
/// Implements transaction payment for a pallet implementing the [`fungible`]
/// trait (eg. pallet_balances) using an unbalance handler (implementing
/// [`OnUnbalanced`]).
///
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: `fee` and
/// then `tip`.
pub struct FungibleAdapter<F, OU>(PhantomData<(F, OU)>);

impl<T, F, OU> OnChargeTransaction<T> for FungibleAdapter<F, OU>
where
T: Config,
F: Balanced<T::AccountId>,
OU: OnUnbalanced<Credit<T::AccountId, F>>,
{
type LiquidityInfo = Option<Credit<T::AccountId, F>>;
type Balance = <F as Inspect<<T as frame_system::Config>::AccountId>>::Balance;

fn withdraw_fee(
who: &<T>::AccountId,
_call: &<T>::RuntimeCall,
_dispatch_info: &DispatchInfoOf<<T>::RuntimeCall>,
fee: Self::Balance,
_tip: Self::Balance,
) -> Result<Self::LiquidityInfo, TransactionValidityError> {
if fee.is_zero() {
return Ok(None)
}

match F::withdraw(
who,
fee,
Precision::Exact,
frame_support::traits::tokens::Preservation::Preserve,
frame_support::traits::tokens::Fortitude::Polite,
) {
Ok(imbalance) => Ok(Some(imbalance)),
Err(_) => Err(InvalidTransaction::Payment.into()),
}
}

fn correct_and_deposit_fee(
who: &<T>::AccountId,
_dispatch_info: &DispatchInfoOf<<T>::RuntimeCall>,
_post_info: &PostDispatchInfoOf<<T>::RuntimeCall>,
corrected_fee: Self::Balance,
tip: Self::Balance,
already_withdrawn: Self::LiquidityInfo,
) -> Result<(), TransactionValidityError> {
if let Some(paid) = already_withdrawn {
// Calculate how much refund we should return
let refund_amount = paid.peek().saturating_sub(corrected_fee);
// refund to the the account that paid the fees. If this fails, the
// account might have dropped below the existential balance. In
// that case we don't refund anything.
let refund_imbalance = F::deposit(who, refund_amount, Precision::BestEffort)
.unwrap_or_else(|_| Debt::<T::AccountId, F>::zero());
// merge the imbalance caused by paying the fees and refunding parts of it again.
let adjusted_paid: Credit<T::AccountId, F> = paid
.offset(refund_imbalance)
.same()
.map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?;
// Call someone else to handle the imbalance (fee and tip separately)
let (tip, fee) = adjusted_paid.split(tip);
OU::on_unbalanceds(Some(fee).into_iter().chain(Some(tip)));
}

Ok(())
}
}

/// Implements the transaction payment for a pallet implementing the [`Currency`]
/// trait (eg. the pallet_balances) using an unbalance handler (implementing
/// `OnUnbalanced`).
/// [`OnUnbalanced`]).
///
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: fee and
/// then tip.
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: `fee` and
/// then `tip`.
#[deprecated(note = "Please use the fungible trait and FungibleAdapter instead where possible.")]
pub struct CurrencyAdapter<C, OU>(PhantomData<(C, OU)>);

/// Default implementation for a Currency and an OnUnbalanced handler.
///
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: fee and
/// then tip.
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: `fee` and
/// then `tip`.
#[allow(deprecated)]
impl<T, C, OU> OnChargeTransaction<T> for CurrencyAdapter<C, OU>
where
T: Config,
Expand Down
14 changes: 13 additions & 1 deletion substrate/frame/treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ use sp_runtime::{
traits::{AccountIdConversion, CheckedAdd, Saturating, StaticLookup, Zero},
Permill, RuntimeDebug,
};
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData, prelude::*};

use frame_support::{
dispatch::{DispatchResult, DispatchResultWithPostInfo},
Expand Down Expand Up @@ -1120,3 +1120,15 @@ impl<T: Config<I>, I: 'static> OnUnbalanced<NegativeImbalanceOf<T, I>> for Palle
Self::deposit_event(Event::Deposit { value: numeric_amount });
}
}

/// TypedGet implementation to get the AccountId of the Treasury.
pub struct TreasuryAccountId<R>(PhantomData<R>);
impl<R> sp_runtime::traits::TypedGet for TreasuryAccountId<R>
where
R: crate::Config,
{
type Type = <R as frame_system::Config>::AccountId;
fn get() -> Self::Type {
crate::Pallet::<R>::account_id()
}
}

0 comments on commit f5587b3

Please sign in to comment.