From 0ccc1951966e21404be6cec8dfa4783e850051b4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 13 Nov 2023 16:13:35 +0400 Subject: [PATCH 1/4] create FungibleAdapter --- .../frame/transaction-payment/src/payment.rs | 89 +++++++++++++++++-- 1 file changed, 82 insertions(+), 7 deletions(-) diff --git a/substrate/frame/transaction-payment/src/payment.rs b/substrate/frame/transaction-payment/src/payment.rs index 22b0ac7c74240..6a46659c5e43c 100644 --- a/substrate/frame/transaction-payment/src/payment.rs +++ b/substrate/frame/transaction-payment/src/payment.rs @@ -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, }; @@ -66,18 +70,89 @@ pub trait OnChargeTransaction { ) -> 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(PhantomData<(F, OU)>); + +impl OnChargeTransaction for FungibleAdapter +where + T: Config, + F: Balanced, + OU: OnUnbalanced>, +{ + type LiquidityInfo = Option>; + type Balance = ::AccountId>>::Balance; + + fn withdraw_fee( + who: &::AccountId, + _call: &::RuntimeCall, + _dispatch_info: &DispatchInfoOf<::RuntimeCall>, + fee: Self::Balance, + _tip: Self::Balance, + ) -> Result { + 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: &::AccountId, + _dispatch_info: &DispatchInfoOf<::RuntimeCall>, + _post_info: &PostDispatchInfoOf<::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::::zero()); + // merge the imbalance caused by paying the fees and refunding parts of it again. + let adjusted_paid: Credit = 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(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`. impl OnChargeTransaction for CurrencyAdapter where T: Config, From 803e8f29f0a62617b4a53cbdd56310f430a15fb6 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 13 Nov 2023 16:24:01 +0400 Subject: [PATCH 2/4] allow deprecated --- substrate/frame/transaction-payment/src/payment.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/frame/transaction-payment/src/payment.rs b/substrate/frame/transaction-payment/src/payment.rs index 6a46659c5e43c..b476d71bf744e 100644 --- a/substrate/frame/transaction-payment/src/payment.rs +++ b/substrate/frame/transaction-payment/src/payment.rs @@ -153,6 +153,7 @@ pub struct CurrencyAdapter(PhantomData<(C, OU)>); /// /// The unbalance handler is given 2 unbalanceds in [`OnUnbalanced::on_unbalanceds`]: `fee` and /// then `tip`. +#[allow(deprecated)] impl OnChargeTransaction for CurrencyAdapter where T: Config, From fac4743309526d3bfd0cd1a96f87a3d452516fd5 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 13 Nov 2023 16:13:35 +0400 Subject: [PATCH 3/4] migrated to FungibleAdapter --- substrate/bin/minimal/runtime/src/lib.rs | 2 +- substrate/bin/node-template/runtime/src/lib.rs | 4 ++-- substrate/bin/node/runtime/src/lib.rs | 2 ++ substrate/frame/balances/src/tests/mod.rs | 4 ++-- substrate/frame/executive/src/lib.rs | 4 ++-- .../asset-conversion-tx-payment/src/mock.rs | 4 ++-- .../frame/transaction-payment/asset-tx-payment/src/mock.rs | 4 ++-- substrate/frame/transaction-payment/src/mock.rs | 2 +- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/substrate/bin/minimal/runtime/src/lib.rs b/substrate/bin/minimal/runtime/src/lib.rs index 610289693d91b..e2bea5a8a2a3f 100644 --- a/substrate/bin/minimal/runtime/src/lib.rs +++ b/substrate/bin/minimal/runtime/src/lib.rs @@ -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; + type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter; type WeightToFee = NoFee<::Balance>; type LengthToFee = FixedFee<1, ::Balance>; } diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/substrate/bin/node-template/runtime/src/lib.rs index 3b6a74be2512c..e4a203c1aefbe 100644 --- a/substrate/bin/node-template/runtime/src/lib.rs +++ b/substrate/bin/node-template/runtime/src/lib.rs @@ -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}; @@ -236,7 +236,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; + type OnChargeTransaction = FungibleAdapter; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 02d084c6c62b5..25ca4c331bd93 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -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; @@ -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; diff --git a/substrate/frame/balances/src/tests/mod.rs b/substrate/frame/balances/src/tests/mod.rs index 91452b292b56f..d01f0925fd038 100644 --- a/substrate/frame/balances/src/tests/mod.rs +++ b/substrate/frame/balances/src/tests/mod.rs @@ -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; @@ -119,7 +119,7 @@ impl frame_system::Config for Test { impl pallet_transaction_payment::Config for Test { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter, ()>; + type OnChargeTransaction = FungibleAdapter, ()>; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; diff --git a/substrate/frame/executive/src/lib.rs b/substrate/frame/executive/src/lib.rs index 48ff675f8082d..3a56c0d6d0cf8 100644 --- a/substrate/frame/executive/src/lib.rs +++ b/substrate/frame/executive/src/lib.rs @@ -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:"; @@ -966,7 +966,7 @@ mod tests { } impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; + type OnChargeTransaction = FungibleAdapter; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type LengthToFee = ConstantMultiplier; diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs index c8bf2eb8f440f..f5cb60de5ae08 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs @@ -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}, @@ -170,7 +170,7 @@ impl OnUnbalanced> for DealWithFees impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; + type OnChargeTransaction = FungibleAdapter; type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; type FeeMultiplierUpdate = (); diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs index 1f335b4f6c4ab..774518fca46de 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs @@ -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}; @@ -138,7 +138,7 @@ impl WeightToFeeT for TransactionByteFee { impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; + type OnChargeTransaction = FungibleAdapter; type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; type FeeMultiplierUpdate = (); diff --git a/substrate/frame/transaction-payment/src/mock.rs b/substrate/frame/transaction-payment/src/mock.rs index 1ca2e3d734720..0d80d801a9f88 100644 --- a/substrate/frame/transaction-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/src/mock.rs @@ -152,7 +152,7 @@ impl OnUnbalanced> for DealWithFees impl Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; + type OnChargeTransaction = FungibleAdapter; type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; From 1fa0daead3fc95a7116e377467e1891576172169 Mon Sep 17 00:00:00 2001 From: Toufeeq Pasha Date: Thu, 29 Aug 2024 17:45:24 +0530 Subject: [PATCH 4/4] added TypedGet implementation to get treasury account --- substrate/frame/treasury/src/lib.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/substrate/frame/treasury/src/lib.rs b/substrate/frame/treasury/src/lib.rs index 5e429d3914bd0..f70993cd433e3 100644 --- a/substrate/frame/treasury/src/lib.rs +++ b/substrate/frame/treasury/src/lib.rs @@ -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}, @@ -1120,3 +1120,15 @@ impl, I: 'static> OnUnbalanced> for Palle Self::deposit_event(Event::Deposit { value: numeric_amount }); } } + +/// TypedGet implementation to get the AccountId of the Treasury. +pub struct TreasuryAccountId(PhantomData); +impl sp_runtime::traits::TypedGet for TreasuryAccountId +where + R: crate::Config, +{ + type Type = ::AccountId; + fn get() -> Self::Type { + crate::Pallet::::account_id() + } +}