Asset conversion nits (#2860)

* [asset-conv] Unused Balances type

* [asset-conv] native asset change

* Dedicated `AssetBalance` type for `pallet_assets` instances

* Improved local vs foreign asset handling + test for not allowing pool_assets in pool

* Removed `into_multiasset_id`

* Fix

* Refactor

* Fixed create_pool for benchmark with LocalAndForeignAssets (finally found it)

* ".git/.scripts/commands/fmt/fmt.sh"

* Revert

* fmt

* Migrates pools with `MultiLocation { parents: 0, interior: Here }` to `MultiLocation { parents: 1, interior: Here }`

* Allow `set_storage` for `AllowMultiAssetPools` / `LiquidityWithdrawalFee`

* Benchmarks work

* Removed comment + more defensive migration

* `T::Currency::transfer` -> `Balances::transfer_all` in migration

* Change pool_id in migration

* Update parachains/runtimes/assets/asset-hub-westend/src/lib.rs

* Bump substrate (manually)

* Bump polkadot

* Fixes from polkadot + clippy

* Fix for xcm-emulator tests (thank you Nacho)

---------

Co-authored-by: command-bot <>
Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>
This commit is contained in:
Branislav Kontur
2023-07-21 23:53:51 +02:00
committed by GitHub
parent 849964bf18
commit 8171890f9b
25 changed files with 1060 additions and 486 deletions
@@ -9,6 +9,7 @@ description = "Assets common utilities"
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.9.0", default-features = false, features = ["derive"] }
log = { version = "0.4.19", default-features = false }
impl-trait-for-tuples = "0.2.2"
# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
@@ -37,6 +37,19 @@ where
) -> Result<MultiAsset, FungiblesAccessError>;
}
/// Checks for `MultiLocation`.
pub trait MatchesMultiLocation<AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertBalance>:
MatchesFungibles<AssetId, Balance>
where
AssetId: Clone,
Balance: Clone,
MatchAssetId: Contains<MultiLocation>,
ConvertAssetId: MaybeEquivalence<MultiLocation, AssetId>,
ConvertBalance: MaybeEquivalence<u128, Balance>,
{
fn contains(location: &MultiLocation) -> bool;
}
impl<
AssetId: Clone,
Balance: Clone,
@@ -82,6 +95,38 @@ impl<
}
}
impl<
AssetId: Clone,
Balance: Clone,
MatchAssetId: Contains<MultiLocation>,
ConvertAssetId: MaybeEquivalence<MultiLocation, AssetId>,
ConvertBalance: MaybeEquivalence<u128, Balance>,
> MatchesMultiLocation<AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertBalance>
for MatchedConvertedConcreteId<AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertBalance>
{
fn contains(location: &MultiLocation) -> bool {
MatchAssetId::contains(location)
}
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl<
AssetId: Clone,
Balance: Clone,
MatchAssetId: Contains<MultiLocation>,
ConvertAssetId: MaybeEquivalence<MultiLocation, AssetId>,
ConvertBalance: MaybeEquivalence<u128, Balance>,
> MatchesMultiLocation<AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertBalance> for Tuple
{
fn contains(location: &MultiLocation) -> bool {
for_tuples!( #(
match Tuple::contains(location) { o @ true => return o, _ => () }
)* );
log::trace!(target: "xcm::contains", "did not match location: {:?}", &location);
false
}
}
/// Helper function to convert collections with [`(AssetId, Balance)`] to [`MultiAsset`]
pub fn convert<'a, AssetId, Balance, ConvertAssetId, ConvertBalance, Converter>(
items: impl Iterator<Item = &'a (AssetId, Balance)>,
@@ -13,92 +13,81 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::local_and_foreign_assets::fungibles::Inspect;
use cumulus_primitives_core::InteriorMultiLocation;
use frame_support::{
pallet_prelude::DispatchError,
traits::{
fungibles::{
self, Balanced, Create, HandleImbalanceDrop, Mutate as MutateFungible, Unbalanced,
fungibles::{Balanced, Create, HandleImbalanceDrop, Inspect, Mutate, Unbalanced},
tokens::{
DepositConsequence, Fortitude, Precision, Preservation, Provenance, WithdrawConsequence,
},
tokens::{DepositConsequence, Fortitude, Preservation, Provenance, WithdrawConsequence},
AccountTouch, ContainsPair, Get, PalletInfoAccess,
AccountTouch, Contains, ContainsPair, Get, PalletInfoAccess,
},
};
use pallet_asset_conversion::MultiAssetIdConverter;
use parachains_common::{AccountId, AssetIdForTrustBackedAssets};
use pallet_asset_conversion::{MultiAssetIdConversionResult, MultiAssetIdConverter};
use parachains_common::AccountId;
use sp_runtime::{traits::MaybeEquivalence, DispatchResult};
use sp_std::{boxed::Box, marker::PhantomData};
use xcm::{latest::MultiLocation, opaque::lts::Junctions::Here};
use xcm_builder::AsPrefixedGeneralIndex;
use xcm_executor::traits::JustTry;
use xcm::latest::MultiLocation;
/// Whether the multilocation refers to an asset in the local assets pallet or not,
/// and if return the asset id.
fn is_local<TrustBackedAssetsPalletLocation: Get<MultiLocation>>(
multilocation: MultiLocation,
) -> Option<u32> {
AsPrefixedGeneralIndex::<TrustBackedAssetsPalletLocation, AssetIdForTrustBackedAssets, JustTry>::convert(&multilocation)
pub struct MultiLocationConverter<NativeAssetLocation: Get<MultiLocation>, MultiLocationMatcher> {
_phantom: PhantomData<(NativeAssetLocation, MultiLocationMatcher)>,
}
pub struct MultiLocationConverter<Balances, ParachainLocation: Get<InteriorMultiLocation>> {
_phantom: PhantomData<(Balances, ParachainLocation)>,
}
impl<Balances, ParachainLocation> MultiAssetIdConverter<Box<MultiLocation>, MultiLocation>
for MultiLocationConverter<Balances, ParachainLocation>
impl<NativeAssetLocation, MultiLocationMatcher>
MultiAssetIdConverter<Box<MultiLocation>, MultiLocation>
for MultiLocationConverter<NativeAssetLocation, MultiLocationMatcher>
where
Balances: PalletInfoAccess,
ParachainLocation: Get<InteriorMultiLocation>,
NativeAssetLocation: Get<MultiLocation>,
MultiLocationMatcher: Contains<MultiLocation>,
{
fn get_native() -> Box<MultiLocation> {
Box::new(MultiLocation { parents: 0, interior: Here })
Box::new(NativeAssetLocation::get())
}
fn is_native(asset_id: &Box<MultiLocation>) -> bool {
let mut asset_id = asset_id.clone();
asset_id.simplify(&ParachainLocation::get());
*asset_id == *Self::get_native()
*asset_id == Self::get_native()
}
fn try_convert(asset_id: &Box<MultiLocation>) -> Result<MultiLocation, ()> {
let mut asset_id = asset_id.clone();
asset_id.simplify(&ParachainLocation::get());
fn try_convert(
asset_id: &Box<MultiLocation>,
) -> MultiAssetIdConversionResult<Box<MultiLocation>, MultiLocation> {
if Self::is_native(&asset_id) {
// Otherwise it will try and touch the asset to create an account.
return Err(())
return MultiAssetIdConversionResult::Native
}
// Return simplified MultiLocation:
Ok(*asset_id)
}
fn into_multiasset_id(asset_id: &MultiLocation) -> Box<MultiLocation> {
let mut asset_id = *asset_id;
asset_id.simplify(&ParachainLocation::get());
Box::new(asset_id)
if MultiLocationMatcher::contains(&asset_id) {
MultiAssetIdConversionResult::Converted(*asset_id.clone())
} else {
MultiAssetIdConversionResult::Unsupported(asset_id.clone())
}
}
}
pub struct LocalAndForeignAssets<Assets, ForeignAssets, Location> {
_phantom: PhantomData<(Assets, ForeignAssets, Location)>,
pub trait MatchesLocalAndForeignAssetsMultiLocation {
fn is_local(location: &MultiLocation) -> bool;
fn is_foreign(location: &MultiLocation) -> bool;
}
impl<Assets, ForeignAssets, Location> Unbalanced<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
pub struct LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets> {
_phantom: PhantomData<(Assets, LocalAssetIdConverter, ForeignAssets)>,
}
impl<Assets, LocalAssetIdConverter, ForeignAssets> Unbalanced<AccountId>
for LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
ForeignAssets: Inspect<AccountId, Balance = u128, AssetId = MultiLocation>
+ Unbalanced<AccountId>
+ Balanced<AccountId>,
Assets: Inspect<AccountId, Balance = u128, AssetId = u32>
+ Unbalanced<AccountId>
+ Balanced<AccountId>
+ PalletInfoAccess,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets: Inspect<AccountId, Balance = u128, AssetId = MultiLocation>
+ Unbalanced<AccountId>
+ Balanced<AccountId>,
{
fn handle_dust(dust: frame_support::traits::fungibles::Dust<AccountId, Self>) {
let credit = dust.into_credit();
if let Some(asset) = is_local::<Location>(credit.asset()) {
if let Some(asset) = LocalAssetIdConverter::convert(&credit.asset()) {
Assets::handle_raw_dust(asset, credit.peek());
} else {
ForeignAssets::handle_raw_dust(credit.asset(), credit.peek());
@@ -109,14 +98,11 @@ where
}
fn write_balance(
asset: <Self as frame_support::traits::fungibles::Inspect<AccountId>>::AssetId,
asset: <Self as Inspect<AccountId>>::AssetId,
who: &AccountId,
amount: <Self as frame_support::traits::fungibles::Inspect<AccountId>>::Balance,
) -> Result<
Option<<Self as frame_support::traits::fungibles::Inspect<AccountId>>::Balance>,
sp_runtime::DispatchError,
> {
if let Some(asset) = is_local::<Location>(asset) {
amount: <Self as Inspect<AccountId>>::Balance,
) -> Result<Option<<Self as Inspect<AccountId>>::Balance>, DispatchError> {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::write_balance(asset, who, amount)
} else {
ForeignAssets::write_balance(asset, who, amount)
@@ -125,27 +111,55 @@ where
/// Set the total issuance of `asset` to `amount`.
fn set_total_issuance(asset: Self::AssetId, amount: Self::Balance) {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::set_total_issuance(asset, amount)
} else {
ForeignAssets::set_total_issuance(asset, amount)
}
}
fn decrease_balance(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
precision: Precision,
preservation: Preservation,
force: Fortitude,
) -> Result<Self::Balance, DispatchError> {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::decrease_balance(asset, who, amount, precision, preservation, force)
} else {
ForeignAssets::decrease_balance(asset, who, amount, precision, preservation, force)
}
}
fn increase_balance(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
precision: Precision,
) -> Result<Self::Balance, DispatchError> {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::increase_balance(asset, who, amount, precision)
} else {
ForeignAssets::increase_balance(asset, who, amount, precision)
}
}
}
impl<Assets, ForeignAssets, Location> Inspect<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
impl<Assets, LocalAssetIdConverter, ForeignAssets> Inspect<AccountId>
for LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
ForeignAssets: Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets: Inspect<AccountId, Balance = u128, AssetId = u32>,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets: Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
{
type AssetId = MultiLocation;
type Balance = u128;
/// The total amount of issuance in the system.
fn total_issuance(asset: Self::AssetId) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::total_issuance(asset)
} else {
ForeignAssets::total_issuance(asset)
@@ -154,16 +168,27 @@ where
/// The minimum balance any single account may have.
fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::minimum_balance(asset)
} else {
ForeignAssets::minimum_balance(asset)
}
}
fn total_balance(
asset: <Self as Inspect<AccountId>>::AssetId,
account: &AccountId,
) -> <Self as Inspect<AccountId>>::Balance {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::total_balance(asset, account)
} else {
ForeignAssets::total_balance(asset, account)
}
}
/// Get the `asset` balance of `who`.
fn balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::balance(asset, who)
} else {
ForeignAssets::balance(asset, who)
@@ -177,7 +202,7 @@ where
presevation: Preservation,
fortitude: Fortitude,
) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::reducible_balance(asset, who, presevation, fortitude)
} else {
ForeignAssets::reducible_balance(asset, who, presevation, fortitude)
@@ -196,7 +221,7 @@ where
amount: Self::Balance,
mint: Provenance,
) -> DepositConsequence {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::can_deposit(asset, who, amount, mint)
} else {
ForeignAssets::can_deposit(asset, who, amount, mint)
@@ -210,7 +235,7 @@ where
who: &AccountId,
amount: Self::Balance,
) -> WithdrawConsequence<Self::Balance> {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::can_withdraw(asset, who, amount)
} else {
ForeignAssets::can_withdraw(asset, who, amount)
@@ -219,36 +244,25 @@ where
/// Returns `true` if an `asset` exists.
fn asset_exists(asset: Self::AssetId) -> bool {
if let Some(asset) = is_local::<Location>(asset) {
if let Some(asset) = LocalAssetIdConverter::convert(&asset) {
Assets::asset_exists(asset)
} else {
ForeignAssets::asset_exists(asset)
}
}
fn total_balance(
asset: <Self as frame_support::traits::fungibles::Inspect<AccountId>>::AssetId,
account: &AccountId,
) -> <Self as frame_support::traits::fungibles::Inspect<AccountId>>::Balance {
if let Some(asset) = is_local::<Location>(asset) {
Assets::total_balance(asset, account)
} else {
ForeignAssets::total_balance(asset, account)
}
}
}
impl<Assets, ForeignAssets, Location> MutateFungible<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
impl<Assets, LocalAssetIdConverter, ForeignAssets> Mutate<AccountId>
for LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
ForeignAssets: MutateFungible<AccountId, Balance = u128>
+ Inspect<AccountId, Balance = u128, AssetId = MultiLocation>
+ Balanced<AccountId>,
Assets: MutateFungible<AccountId>
Assets: Mutate<AccountId>
+ Inspect<AccountId, Balance = u128, AssetId = u32>
+ Balanced<AccountId>
+ PalletInfoAccess,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets: Mutate<AccountId, Balance = u128>
+ Inspect<AccountId, Balance = u128, AssetId = MultiLocation>
+ Balanced<AccountId>,
{
/// Transfer funds from one account into another.
fn transfer(
@@ -258,7 +272,7 @@ where
amount: Self::Balance,
keep_alive: Preservation,
) -> Result<Self::Balance, DispatchError> {
if let Some(asset_id) = is_local::<Location>(asset) {
if let Some(asset_id) = LocalAssetIdConverter::convert(&asset) {
Assets::transfer(asset_id, source, dest, amount, keep_alive)
} else {
ForeignAssets::transfer(asset, source, dest, amount, keep_alive)
@@ -266,12 +280,12 @@ where
}
}
impl<Assets, ForeignAssets, Location> Create<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
impl<Assets, LocalAssetIdConverter, ForeignAssets> Create<AccountId>
for LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
ForeignAssets: Create<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets: Create<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32>,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets: Create<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
{
/// Create a new fungible asset.
fn create(
@@ -280,7 +294,7 @@ where
is_sufficient: bool,
min_balance: Self::Balance,
) -> DispatchResult {
if let Some(asset_id) = is_local::<Location>(asset_id) {
if let Some(asset_id) = LocalAssetIdConverter::convert(&asset_id) {
Assets::create(asset_id, admin, is_sufficient, min_balance)
} else {
ForeignAssets::create(asset_id, admin, is_sufficient, min_balance)
@@ -288,19 +302,19 @@ where
}
}
impl<Assets, ForeignAssets, Location> AccountTouch<MultiLocation, AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
impl<Assets, LocalAssetIdConverter, ForeignAssets> AccountTouch<MultiLocation, AccountId>
for LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
ForeignAssets: AccountTouch<MultiLocation, AccountId, Balance = u128>,
Assets: AccountTouch<u32, AccountId, Balance = u128>,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets: AccountTouch<MultiLocation, AccountId, Balance = u128>,
{
type Balance = u128;
fn deposit_required(
asset_id: MultiLocation,
) -> <Self as AccountTouch<MultiLocation, AccountId>>::Balance {
if let Some(asset_id) = is_local::<Location>(asset_id) {
if let Some(asset_id) = LocalAssetIdConverter::convert(&asset_id) {
Assets::deposit_required(asset_id)
} else {
ForeignAssets::deposit_required(asset_id)
@@ -311,8 +325,8 @@ where
asset_id: MultiLocation,
who: AccountId,
depositor: AccountId,
) -> Result<(), sp_runtime::DispatchError> {
if let Some(asset_id) = is_local::<Location>(asset_id) {
) -> Result<(), DispatchError> {
if let Some(asset_id) = LocalAssetIdConverter::convert(&asset_id) {
Assets::touch(asset_id, who, depositor)
} else {
ForeignAssets::touch(asset_id, who, depositor)
@@ -321,16 +335,16 @@ where
}
/// Implements [`ContainsPair`] trait for a pair of asset and account IDs.
impl<Assets, ForeignAssets, Location> ContainsPair<MultiLocation, AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
impl<Assets, LocalAssetIdConverter, ForeignAssets> ContainsPair<MultiLocation, AccountId>
for LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
ForeignAssets: ContainsPair<MultiLocation, AccountId>,
Assets: PalletInfoAccess + ContainsPair<u32, AccountId>,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets: ContainsPair<MultiLocation, AccountId>,
{
/// Check if an account with the given asset ID and account address exists.
fn contains(asset_id: &MultiLocation, who: &AccountId) -> bool {
if let Some(asset_id) = is_local::<Location>(*asset_id) {
if let Some(asset_id) = LocalAssetIdConverter::convert(asset_id) {
Assets::contains(&asset_id, &who)
} else {
ForeignAssets::contains(&asset_id, &who)
@@ -338,33 +352,33 @@ where
}
}
impl<Assets, ForeignAssets, Location> Balanced<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
impl<Assets, LocalAssetIdConverter, ForeignAssets> Balanced<AccountId>
for LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
ForeignAssets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32> + PalletInfoAccess,
{
type OnDropDebt = DebtDropIndirection<Assets, ForeignAssets, Location>;
type OnDropCredit = CreditDropIndirection<Assets, ForeignAssets, Location>;
}
pub struct DebtDropIndirection<Assets, ForeignAssets, Location> {
_phantom: PhantomData<LocalAndForeignAssets<Assets, ForeignAssets, Location>>,
}
impl<Assets, ForeignAssets, Location> HandleImbalanceDrop<MultiLocation, u128>
for DebtDropIndirection<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
{
type OnDropDebt = DebtDropIndirection<Assets, LocalAssetIdConverter, ForeignAssets>;
type OnDropCredit = CreditDropIndirection<Assets, LocalAssetIdConverter, ForeignAssets>;
}
pub struct DebtDropIndirection<Assets, LocalAssetIdConverter, ForeignAssets> {
_phantom: PhantomData<LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>>,
}
impl<Assets, LocalAssetIdConverter, ForeignAssets> HandleImbalanceDrop<MultiLocation, u128>
for DebtDropIndirection<Assets, LocalAssetIdConverter, ForeignAssets>
where
Assets: Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32>,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
{
fn handle(asset: MultiLocation, amount: u128) {
if let Some(asset_id) = is_local::<Location>(asset) {
if let Some(asset_id) = LocalAssetIdConverter::convert(&asset) {
Assets::OnDropDebt::handle(asset_id, amount);
} else {
ForeignAssets::OnDropDebt::handle(asset, amount);
@@ -372,23 +386,87 @@ where
}
}
pub struct CreditDropIndirection<Assets, ForeignAssets, Location> {
_phantom: PhantomData<LocalAndForeignAssets<Assets, ForeignAssets, Location>>,
pub struct CreditDropIndirection<Assets, LocalAssetIdConverter, ForeignAssets> {
_phantom: PhantomData<LocalAndForeignAssets<Assets, LocalAssetIdConverter, ForeignAssets>>,
}
impl<Assets, ForeignAssets, Location> HandleImbalanceDrop<MultiLocation, u128>
for CreditDropIndirection<Assets, ForeignAssets, Location>
impl<Assets, LocalAssetIdConverter, ForeignAssets> HandleImbalanceDrop<MultiLocation, u128>
for CreditDropIndirection<Assets, LocalAssetIdConverter, ForeignAssets>
where
Location: Get<MultiLocation>,
Assets: Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32>,
LocalAssetIdConverter: MaybeEquivalence<MultiLocation, u32>,
ForeignAssets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets: Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32>,
{
fn handle(asset: MultiLocation, amount: u128) {
if let Some(asset_id) = is_local::<Location>(asset) {
if let Some(asset_id) = LocalAssetIdConverter::convert(&asset) {
Assets::OnDropCredit::handle(asset_id, amount);
} else {
ForeignAssets::OnDropCredit::handle(asset, amount);
}
}
}
#[cfg(test)]
mod tests {
use crate::{
local_and_foreign_assets::MultiLocationConverter, matching::StartsWith,
AssetIdForPoolAssetsConvert, AssetIdForTrustBackedAssetsConvert,
};
use frame_support::traits::EverythingBut;
use pallet_asset_conversion::{MultiAssetIdConversionResult, MultiAssetIdConverter};
use sp_runtime::traits::MaybeEquivalence;
use xcm::latest::prelude::*;
#[test]
fn test_multi_location_converter_works() {
frame_support::parameter_types! {
pub const WestendLocation: MultiLocation = MultiLocation::parent();
pub TrustBackedAssetsPalletLocation: MultiLocation = PalletInstance(50_u8).into();
pub PoolAssetsPalletLocation: MultiLocation = PalletInstance(55_u8).into();
}
type C = MultiLocationConverter<
WestendLocation,
EverythingBut<StartsWith<PoolAssetsPalletLocation>>,
>;
let native_asset = WestendLocation::get();
let local_asset =
AssetIdForTrustBackedAssetsConvert::<TrustBackedAssetsPalletLocation>::convert_back(
&123,
)
.unwrap();
let pool_asset =
AssetIdForPoolAssetsConvert::<PoolAssetsPalletLocation>::convert_back(&456).unwrap();
let foreign_asset1 = MultiLocation { parents: 1, interior: X1(Parachain(2222)) };
let foreign_asset2 = MultiLocation {
parents: 2,
interior: X2(GlobalConsensus(ByGenesis([1; 32])), Parachain(2222)),
};
assert!(C::is_native(&Box::new(native_asset)));
assert!(!C::is_native(&Box::new(local_asset)));
assert!(!C::is_native(&Box::new(pool_asset)));
assert!(!C::is_native(&Box::new(foreign_asset1)));
assert!(!C::is_native(&Box::new(foreign_asset2)));
assert_eq!(C::try_convert(&Box::new(native_asset)), MultiAssetIdConversionResult::Native);
assert_eq!(
C::try_convert(&Box::new(local_asset)),
MultiAssetIdConversionResult::Converted(local_asset)
);
assert_eq!(
C::try_convert(&Box::new(pool_asset)),
MultiAssetIdConversionResult::Unsupported(Box::new(pool_asset))
);
assert_eq!(
C::try_convert(&Box::new(foreign_asset1)),
MultiAssetIdConversionResult::Converted(foreign_asset1)
);
assert_eq!(
C::try_convert(&Box::new(foreign_asset2)),
MultiAssetIdConversionResult::Converted(foreign_asset2)
);
}
}