XCM WeightTrader: Swap Fee Asset for Native Asset (#1845)

Implements an XCM executor `WeightTrader`, facilitating fee payments in
any asset that can be exchanged for a native asset.

A few constraints need to be observed:
- `buy_weight` and `refund` operations must be atomic, as another weight
trader implementation might be attempted in case of failure.
- swap credit must be utilized since there isn’t an account to which an
asset of some class can be deposited with a guarantee to meet the
existential deposit requirement. Also, operating with credits enhances
the efficiency of the weight trader -
https://github.com/paritytech/polkadot-sdk/pull/1677

related PRs:
- (depends) https://github.com/paritytech/polkadot-sdk/pull/2031
- (depends) https://github.com/paritytech/polkadot-sdk/pull/1677
- (caused) https://github.com/paritytech/polkadot-sdk/pull/1847
- (caused) https://github.com/paritytech/polkadot-sdk/pull/1876

// DONE: impl `OnUnbalanced` for a `fungible/s` credit
// DONE: make the trader free from a concept of a native currency and
drop few fallible conversions. related issue -
https://github.com/paritytech/polkadot-sdk/issues/1842
// DONE: tests

---------

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
Muharem
2024-01-16 15:34:48 +08:00
committed by GitHub
parent 4c4963a192
commit 2cb39f8dc9
25 changed files with 1769 additions and 861 deletions
@@ -15,17 +15,21 @@
use super::{
AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee,
FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo, ParachainSystem, PolkadotXcm,
PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, ToWestendXcmRouter,
TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue,
CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo,
ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
ToWestendXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue,
};
use assets_common::{
local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation,
matching::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset},
TrustBackedAssetsAsMultiLocation,
};
use frame_support::{
match_types, parameter_types,
traits::{ConstU32, Contains, Equals, Everything, Nothing, PalletInfoAccess},
traits::{
tokens::imbalance::ResolveAssetTo, ConstU32, Contains, Equals, Everything, Nothing,
PalletInfoAccess,
},
};
use frame_system::EnsureRoot;
use pallet_xcm::XcmPassthrough;
@@ -73,6 +77,7 @@ parameter_types! {
pub PoolAssetsPalletLocation: MultiLocation =
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub StakingPot: AccountId = CollatorSelection::account_id();
pub const GovernanceLocation: MultiLocation = MultiLocation::parent();
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
@@ -550,31 +555,17 @@ impl xcm_executor::Config for XcmConfig {
>;
type Trader = (
UsingComponents<WeightToFee, TokenLocation, AccountId, Balances, ToStakingPot<Runtime>>,
// This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated
// `pallet_assets` instance - `Assets`.
cumulus_primitives_utility::TakeFirstAssetTrader<
cumulus_primitives_utility::SwapFirstAssetTrader<
TokenLocation,
crate::AssetConversion,
WeightToFee,
crate::NativeAndAssets,
(
TrustBackedAssetsAsMultiLocation<TrustBackedAssetsPalletLocation, Balance>,
ForeignAssetsConvertedConcreteId,
),
ResolveAssetTo<StakingPot, crate::NativeAndAssets>,
AccountId,
AssetFeeAsExistentialDepositMultiplierFeeCharger,
TrustBackedAssetsConvertedConcreteId,
Assets,
cumulus_primitives_utility::XcmFeesTo32ByteAccount<
FungiblesTransactor,
AccountId,
XcmAssetFeesReceiver,
>,
>,
// This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated
// `pallet_assets` instance - `ForeignAssets`.
cumulus_primitives_utility::TakeFirstAssetTrader<
AccountId,
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger,
ForeignAssetsConvertedConcreteId,
ForeignAssets,
cumulus_primitives_utility::XcmFeesTo32ByteAccount<
ForeignFungiblesTransactor,
AccountId,
XcmAssetFeesReceiver,
>,
>,
);
type ResponseHandler = PolkadotXcm;