Skip to content

Commit f5587b3

Browse files
authored
Merge pull request #17 from availproject/toufeeq/fix-fee-payment
Backported fee payment fix
2 parents fc206fa + 1fa0dae commit f5587b3

File tree

10 files changed

+110
-20
lines changed

10 files changed

+110
-20
lines changed

substrate/bin/minimal/runtime/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl pallet_timestamp::Config for Runtime {}
9898

9999
#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)]
100100
impl pallet_transaction_payment::Config for Runtime {
101-
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
101+
type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter<Balances, ()>;
102102
type WeightToFee = NoFee<<Self as pallet_balances::Config>::Balance>;
103103
type LengthToFee = FixedFee<1, <Self as pallet_balances::Config>::Balance>;
104104
}

substrate/bin/node-template/runtime/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub use frame_support::{
4040
pub use frame_system::Call as SystemCall;
4141
pub use pallet_balances::Call as BalancesCall;
4242
pub use pallet_timestamp::Call as TimestampCall;
43-
use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier};
43+
use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier};
4444
#[cfg(any(feature = "std", test))]
4545
pub use sp_runtime::BuildStorage;
4646
pub use sp_runtime::{Perbill, Permill};
@@ -236,7 +236,7 @@ parameter_types! {
236236

237237
impl pallet_transaction_payment::Config for Runtime {
238238
type RuntimeEvent = RuntimeEvent;
239-
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
239+
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
240240
type OperationalFeeMultiplier = ConstU8<5>;
241241
type WeightToFee = IdentityFee<Balance>;
242242
type LengthToFee = IdentityFee<Balance>;

substrate/bin/node/runtime/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
7070
use pallet_nfts::PalletFeatures;
7171
use pallet_nis::WithMaximumOf;
7272
use pallet_session::historical as pallet_session_historical;
73+
#[allow(deprecated)]
7374
pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment};
7475
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
7576
use pallet_tx_pause::RuntimeCallNameOf;
@@ -544,6 +545,7 @@ parameter_types! {
544545
pub MaximumMultiplier: Multiplier = Bounded::max_value();
545546
}
546547

548+
#[allow(deprecated)]
547549
impl pallet_transaction_payment::Config for Runtime {
548550
type RuntimeEvent = RuntimeEvent;
549551
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;

substrate/frame/balances/src/tests/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use frame_support::{
3232
weights::{IdentityFee, Weight},
3333
};
3434
use frame_system::{self as system, RawOrigin};
35-
use pallet_transaction_payment::{ChargeTransactionPayment, CurrencyAdapter, Multiplier};
35+
use pallet_transaction_payment::{ChargeTransactionPayment, FungibleAdapter, Multiplier};
3636
use scale_info::TypeInfo;
3737
use sp_core::{hexdisplay::HexDisplay, H256};
3838
use sp_io;
@@ -119,7 +119,7 @@ impl frame_system::Config for Test {
119119

120120
impl pallet_transaction_payment::Config for Test {
121121
type RuntimeEvent = RuntimeEvent;
122-
type OnChargeTransaction = CurrencyAdapter<Pallet<Test>, ()>;
122+
type OnChargeTransaction = FungibleAdapter<Pallet<Test>, ()>;
123123
type OperationalFeeMultiplier = ConstU8<5>;
124124
type WeightToFee = IdentityFee<u64>;
125125
type LengthToFee = IdentityFee<u64>;

substrate/frame/executive/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ mod tests {
768768
};
769769
use frame_system::{ChainContext, LastRuntimeUpgrade, LastRuntimeUpgradeInfo};
770770
use pallet_balances::Call as BalancesCall;
771-
use pallet_transaction_payment::CurrencyAdapter;
771+
use pallet_transaction_payment::FungibleAdapter;
772772

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

@@ -966,7 +966,7 @@ mod tests {
966966
}
967967
impl pallet_transaction_payment::Config for Runtime {
968968
type RuntimeEvent = RuntimeEvent;
969-
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
969+
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
970970
type OperationalFeeMultiplier = ConstU8<5>;
971971
type WeightToFee = IdentityFee<Balance>;
972972
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;

substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use frame_support::{
3636
use frame_system as system;
3737
use frame_system::{EnsureRoot, EnsureSignedBy};
3838
use pallet_asset_conversion::{Ascending, Chain, WithFirstAsset};
39-
use pallet_transaction_payment::CurrencyAdapter;
39+
use pallet_transaction_payment::FungibleAdapter;
4040
use sp_core::H256;
4141
use sp_runtime::{
4242
traits::{AccountIdConversion, BlakeTwo256, IdentityLookup, SaturatedConversion},
@@ -170,7 +170,7 @@ impl OnUnbalanced<pallet_balances::NegativeImbalance<Runtime>> for DealWithFees
170170

171171
impl pallet_transaction_payment::Config for Runtime {
172172
type RuntimeEvent = RuntimeEvent;
173-
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
173+
type OnChargeTransaction = FungibleAdapter<Balances, DealWithFees>;
174174
type WeightToFee = WeightToFee;
175175
type LengthToFee = TransactionByteFee;
176176
type FeeMultiplierUpdate = ();

substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use frame_support::{
2828
};
2929
use frame_system as system;
3030
use frame_system::EnsureRoot;
31-
use pallet_transaction_payment::CurrencyAdapter;
31+
use pallet_transaction_payment::FungibleAdapter;
3232
use sp_core::H256;
3333
use sp_runtime::traits::{BlakeTwo256, ConvertInto, IdentityLookup, SaturatedConversion};
3434

@@ -138,7 +138,7 @@ impl WeightToFeeT for TransactionByteFee {
138138

139139
impl pallet_transaction_payment::Config for Runtime {
140140
type RuntimeEvent = RuntimeEvent;
141-
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
141+
type OnChargeTransaction = FungibleAdapter<Balances, ()>;
142142
type WeightToFee = WeightToFee;
143143
type LengthToFee = TransactionByteFee;
144144
type FeeMultiplierUpdate = ();

substrate/frame/transaction-payment/src/mock.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ impl OnUnbalanced<pallet_balances::NegativeImbalance<Runtime>> for DealWithFees
152152

153153
impl Config for Runtime {
154154
type RuntimeEvent = RuntimeEvent;
155-
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
155+
type OnChargeTransaction = FungibleAdapter<Balances, DealWithFees>;
156156
type OperationalFeeMultiplier = OperationalFeeMultiplier;
157157
type WeightToFee = WeightToFee;
158158
type LengthToFee = TransactionByteFee;

substrate/frame/transaction-payment/src/payment.rs

+83-7
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ use sp_runtime::{
2525
use sp_std::marker::PhantomData;
2626

2727
use frame_support::{
28-
traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReasons},
28+
traits::{
29+
fungible::{Balanced, Credit, Debt, Inspect},
30+
tokens::Precision,
31+
Currency, ExistenceRequirement, Imbalance, OnUnbalanced, TryDrop, WithdrawReasons,
32+
},
2933
unsigned::TransactionValidityError,
3034
};
3135

@@ -66,18 +70,90 @@ pub trait OnChargeTransaction<T: Config> {
6670
) -> Result<(), TransactionValidityError>;
6771
}
6872

69-
/// Implements the transaction payment for a pallet implementing the `Currency`
73+
/// Implements transaction payment for a pallet implementing the [`fungible`]
74+
/// trait (eg. pallet_balances) using an unbalance handler (implementing
75+
/// [`OnUnbalanced`]).
76+
///
77+
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: `fee` and
78+
/// then `tip`.
79+
pub struct FungibleAdapter<F, OU>(PhantomData<(F, OU)>);
80+
81+
impl<T, F, OU> OnChargeTransaction<T> for FungibleAdapter<F, OU>
82+
where
83+
T: Config,
84+
F: Balanced<T::AccountId>,
85+
OU: OnUnbalanced<Credit<T::AccountId, F>>,
86+
{
87+
type LiquidityInfo = Option<Credit<T::AccountId, F>>;
88+
type Balance = <F as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
89+
90+
fn withdraw_fee(
91+
who: &<T>::AccountId,
92+
_call: &<T>::RuntimeCall,
93+
_dispatch_info: &DispatchInfoOf<<T>::RuntimeCall>,
94+
fee: Self::Balance,
95+
_tip: Self::Balance,
96+
) -> Result<Self::LiquidityInfo, TransactionValidityError> {
97+
if fee.is_zero() {
98+
return Ok(None)
99+
}
100+
101+
match F::withdraw(
102+
who,
103+
fee,
104+
Precision::Exact,
105+
frame_support::traits::tokens::Preservation::Preserve,
106+
frame_support::traits::tokens::Fortitude::Polite,
107+
) {
108+
Ok(imbalance) => Ok(Some(imbalance)),
109+
Err(_) => Err(InvalidTransaction::Payment.into()),
110+
}
111+
}
112+
113+
fn correct_and_deposit_fee(
114+
who: &<T>::AccountId,
115+
_dispatch_info: &DispatchInfoOf<<T>::RuntimeCall>,
116+
_post_info: &PostDispatchInfoOf<<T>::RuntimeCall>,
117+
corrected_fee: Self::Balance,
118+
tip: Self::Balance,
119+
already_withdrawn: Self::LiquidityInfo,
120+
) -> Result<(), TransactionValidityError> {
121+
if let Some(paid) = already_withdrawn {
122+
// Calculate how much refund we should return
123+
let refund_amount = paid.peek().saturating_sub(corrected_fee);
124+
// refund to the the account that paid the fees. If this fails, the
125+
// account might have dropped below the existential balance. In
126+
// that case we don't refund anything.
127+
let refund_imbalance = F::deposit(who, refund_amount, Precision::BestEffort)
128+
.unwrap_or_else(|_| Debt::<T::AccountId, F>::zero());
129+
// merge the imbalance caused by paying the fees and refunding parts of it again.
130+
let adjusted_paid: Credit<T::AccountId, F> = paid
131+
.offset(refund_imbalance)
132+
.same()
133+
.map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?;
134+
// Call someone else to handle the imbalance (fee and tip separately)
135+
let (tip, fee) = adjusted_paid.split(tip);
136+
OU::on_unbalanceds(Some(fee).into_iter().chain(Some(tip)));
137+
}
138+
139+
Ok(())
140+
}
141+
}
142+
143+
/// Implements the transaction payment for a pallet implementing the [`Currency`]
70144
/// trait (eg. the pallet_balances) using an unbalance handler (implementing
71-
/// `OnUnbalanced`).
145+
/// [`OnUnbalanced`]).
72146
///
73-
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: fee and
74-
/// then tip.
147+
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: `fee` and
148+
/// then `tip`.
149+
#[deprecated(note = "Please use the fungible trait and FungibleAdapter instead where possible.")]
75150
pub struct CurrencyAdapter<C, OU>(PhantomData<(C, OU)>);
76151

77152
/// Default implementation for a Currency and an OnUnbalanced handler.
78153
///
79-
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: fee and
80-
/// then tip.
154+
/// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: `fee` and
155+
/// then `tip`.
156+
#[allow(deprecated)]
81157
impl<T, C, OU> OnChargeTransaction<T> for CurrencyAdapter<C, OU>
82158
where
83159
T: Config,

substrate/frame/treasury/src/lib.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ use sp_runtime::{
8686
traits::{AccountIdConversion, CheckedAdd, Saturating, StaticLookup, Zero},
8787
Permill, RuntimeDebug,
8888
};
89-
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
89+
use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData, prelude::*};
9090

9191
use frame_support::{
9292
dispatch::{DispatchResult, DispatchResultWithPostInfo},
@@ -1120,3 +1120,15 @@ impl<T: Config<I>, I: 'static> OnUnbalanced<NegativeImbalanceOf<T, I>> for Palle
11201120
Self::deposit_event(Event::Deposit { value: numeric_amount });
11211121
}
11221122
}
1123+
1124+
/// TypedGet implementation to get the AccountId of the Treasury.
1125+
pub struct TreasuryAccountId<R>(PhantomData<R>);
1126+
impl<R> sp_runtime::traits::TypedGet for TreasuryAccountId<R>
1127+
where
1128+
R: crate::Config,
1129+
{
1130+
type Type = <R as frame_system::Config>::AccountId;
1131+
fn get() -> Self::Type {
1132+
crate::Pallet::<R>::account_id()
1133+
}
1134+
}

0 commit comments

Comments
 (0)