Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tx Payment: drop ED requirements for tx payments with exchangeable asset #4488

Merged
merged 18 commits into from
Jul 24, 2024
Merged
17 changes: 13 additions & 4 deletions cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureSigned, EnsureSignedBy,
};
use pallet_asset_conversion_tx_payment::AssetConversionAdapter;
use pallet_asset_conversion_tx_payment::SwapAssetAdapter;
use pallet_nfts::PalletFeatures;
use parachains_common::{
impls::DealWithFees,
Expand Down Expand Up @@ -766,11 +766,20 @@ impl pallet_collator_selection::Config for Runtime {
type WeightInfo = weights::pallet_collator_selection::WeightInfo<Runtime>;
}

parameter_types! {
pub StakingPot: AccountId = CollatorSelection::account_id();
}

impl pallet_asset_conversion_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = LocalAndForeignAssets;
type OnChargeAssetTransaction =
AssetConversionAdapter<Balances, AssetConversion, TokenLocationV3>;
type AssetId = xcm::v3::Location;
type OnChargeAssetTransaction = SwapAssetAdapter<
TokenLocationV3,
NativeAndAssets,
AssetConversion,
ResolveAssetTo<StakingPot, NativeAndAssets>,
ResolveAssetTo<StakingPot, NativeAndAssets>,
>;
}

parameter_types! {
Expand Down
17 changes: 13 additions & 4 deletions cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureSigned, EnsureSignedBy,
};
use pallet_asset_conversion_tx_payment::AssetConversionAdapter;
use pallet_asset_conversion_tx_payment::SwapAssetAdapter;
use pallet_nfts::{DestroyWitness, PalletFeatures};
use pallet_xcm::EnsureXcm;
use parachains_common::{
Expand Down Expand Up @@ -758,11 +758,20 @@ impl pallet_collator_selection::Config for Runtime {
type WeightInfo = weights::pallet_collator_selection::WeightInfo<Runtime>;
}

parameter_types! {
pub StakingPot: AccountId = CollatorSelection::account_id();
}

impl pallet_asset_conversion_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = LocalAndForeignAssets;
type OnChargeAssetTransaction =
AssetConversionAdapter<Balances, AssetConversion, WestendLocationV3>;
type AssetId = xcm::v3::Location;
type OnChargeAssetTransaction = SwapAssetAdapter<
WestendLocationV3,
NativeAndAssets,
AssetConversion,
ResolveAssetTo<StakingPot, NativeAndAssets>,
ResolveAssetTo<StakingPot, NativeAndAssets>,
>;
}

parameter_types! {
Expand Down
22 changes: 22 additions & 0 deletions prdoc/pr_4488.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
title: "Tx Payment: drop ED requirements for tx payments with exchangeable asset"

doc:
- audience: Runtime Dev
description: |
Drop the Existential Deposit requirement for the asset amount exchangeable for the fee asset
(eg. DOT/KSM) during transaction payments.

This achieved by using `SwapCredit` implementation of asset conversion, which works with
imbalances and does not require a temporary balance account within the transaction payment.

crates:
- name: pallet-asset-conversion-tx-payment
bump: major
- name: pallet-transaction-payment
bump: patch
- name: pallet-asset-conversion
bump: patch
- name: asset-hub-rococo-runtime
bump: patch
- name: asset-hub-westend-runtime
bump: patch
30 changes: 12 additions & 18 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ use frame_system::{
pub use node_primitives::{AccountId, Signature};
use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Moment, Nonce};
use pallet_asset_conversion::{AccountIdConverter, Ascending, Chain, WithFirstAsset};
use pallet_asset_conversion_tx_payment::SwapAssetAdapter;
use pallet_broker::{CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600};
use pallet_election_provider_multi_phase::{GeometricDepositBase, SolutionAccuracyOf};
use pallet_identity::legacy::IdentityInfo;
Expand Down Expand Up @@ -119,7 +120,7 @@ pub use sp_runtime::BuildStorage;
pub mod impls;
#[cfg(not(feature = "runtime-benchmarks"))]
use impls::AllianceIdentityVerifier;
use impls::{AllianceProposalProvider, Author, CreditToBlockAuthor};
use impls::{AllianceProposalProvider, Author};

/// Constant values used within the runtime.
pub mod constants;
Expand Down Expand Up @@ -570,22 +571,15 @@ impl pallet_transaction_payment::Config for Runtime {
>;
}

impl pallet_asset_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = Assets;
type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter<
pallet_assets::BalanceToAssetBalance<Balances, Runtime, ConvertInto, Instance1>,
CreditToBlockAuthor,
>;
}

impl pallet_asset_conversion_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = Assets;
type OnChargeAssetTransaction = pallet_asset_conversion_tx_payment::AssetConversionAdapter<
Balances,
AssetConversion,
type AssetId = NativeOrWithId<u32>;
type OnChargeAssetTransaction = SwapAssetAdapter<
Native,
NativeAndAssets,
AssetConversion,
ResolveAssetTo<TreasuryAccount, NativeAndAssets>,
ResolveAssetTo<TreasuryAccount, NativeAndAssets>,
>;
}

Expand Down Expand Up @@ -1701,12 +1695,15 @@ parameter_types! {
pub const Native: NativeOrWithId<u32> = NativeOrWithId::Native;
}

pub type NativeAndAssets =
UnionOf<Balances, Assets, NativeFromLeft, NativeOrWithId<u32>, AccountId>;

impl pallet_asset_conversion::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = u128;
type HigherPrecisionBalance = sp_core::U256;
type AssetKind = NativeOrWithId<u32>;
type Assets = UnionOf<Balances, Assets, NativeFromLeft, NativeOrWithId<u32>, AccountId>;
type Assets = NativeAndAssets;
type PoolId = (Self::AssetKind, Self::AssetKind);
type PoolLocator = Chain<
WithFirstAsset<
Expand Down Expand Up @@ -2281,9 +2278,6 @@ mod runtime {
#[runtime::pallet_index(7)]
pub type TransactionPayment = pallet_transaction_payment;

#[runtime::pallet_index(8)]
pub type AssetTxPayment = pallet_asset_tx_payment;

#[runtime::pallet_index(9)]
pub type AssetConversionTxPayment = pallet_asset_conversion_tx_payment;

Expand Down
52 changes: 52 additions & 0 deletions substrate/frame/asset-conversion/src/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,37 @@ pub trait SwapCredit<AccountId> {
) -> Result<(Self::Credit, Self::Credit), (Self::Credit, DispatchError)>;
}

/// Trait providing methods to quote swap prices between asset classes.
///
/// The quoted price is only guaranteed if no other swaps are made after the price is quoted and
/// before the target swap (e.g., the swap is made immediately within the same transaction).
pub trait QuotePrice {
/// Measurement units of the asset classes for pricing.
type Balance: Balance;
/// Type representing the kind of assets for which the price is being quoted.
type AssetKind;
/// Quotes the amount of `asset1` required to obtain the exact `amount` of `asset2`.
///
/// If `include_fee` is set to `true`, the price will include the pool's fee.
/// If the pool does not exist or the swap cannot be made, `None` is returned.
fn quote_price_tokens_for_exact_tokens(
asset1: Self::AssetKind,
asset2: Self::AssetKind,
amount: Self::Balance,
include_fee: bool,
) -> Option<Self::Balance>;
/// Quotes the amount of `asset2` resulting from swapping the exact `amount` of `asset1`.
///
/// If `include_fee` is set to `true`, the price will include the pool's fee.
/// If the pool does not exist or the swap cannot be made, `None` is returned.
fn quote_price_exact_tokens_for_tokens(
asset1: Self::AssetKind,
asset2: Self::AssetKind,
amount: Self::Balance,
include_fee: bool,
) -> Option<Self::Balance>;
}

impl<T: Config> Swap<T::AccountId> for Pallet<T> {
type Balance = T::Balance;
type AssetKind = T::AssetKind;
Expand Down Expand Up @@ -210,3 +241,24 @@ impl<T: Config> SwapCredit<T::AccountId> for Pallet<T> {
.map_err(|_| (Self::Credit::zero(credit_asset), DispatchError::Corruption))?
}
}

impl<T: Config> QuotePrice for Pallet<T> {
type Balance = T::Balance;
type AssetKind = T::AssetKind;
fn quote_price_exact_tokens_for_tokens(
asset1: Self::AssetKind,
asset2: Self::AssetKind,
amount: Self::Balance,
include_fee: bool,
) -> Option<Self::Balance> {
Self::quote_price_exact_tokens_for_tokens(asset1, asset2, amount, include_fee)
}
fn quote_price_tokens_for_exact_tokens(
asset1: Self::AssetKind,
asset2: Self::AssetKind,
amount: Self::Balance,
include_fee: bool,
) -> Option<Self::Balance> {
Self::quote_price_tokens_for_exact_tokens(asset1, asset2, amount, include_fee)
}
}
Loading
Loading