mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 12:51:02 +00:00
Add Support for Foreign Assets (#2133)
* add foreign assets to westmint * add foreign assets to statemine * use updated api for ensure origin trait * Assets/ForeignAssets tests and fixes (#2167) * Test for create and transfer `TrustBackedAssets` with AssetTransactor * Test for transfer `local Currency` with AssetTransactor * Test for create foreign assets (covers foreign relaychain currency) * Added `ForeignFungiblesTransactor` and test for transfer `ForeignAssets` with AssetTransactor * Removed unused `pub const Local: MultiLocation` * Changed `ParaId -> Sibling` for `SiblingParachainConvertsVia` * Test for create foreign assets (covers local sibling parachain assets) * Reverted stuff for ForeignCreators from different global consensus (moved to transfer asset branch) * Refactor `weight_limit` for `execute_xcm` * Added test for `set_metadata` by ForeignCreator with `xcm::Transact(set_metadata)` * Renamed `receive_teleported_asset_works` -> `receive_teleported_asset_for_native_asset_works` * Allow `ForeignCreators` only for sibling parachains * Unify ReservedDmpWeight/ReservedXcmpWeight usage * Removed hack - replaced with `MatchedConvertedConcreteId` * Refactor `ForeignCreators` to assets-common * Add `ReceiveTeleportedAsset` test * Change test - `Utility::batch` -> Multiple `xcm::Transact` * Reusing the same deposits as for TrustBackedAssets * missing `try_successful_origin` ? * Finished `ForeignAssets` for westmint (converter, FungiblesApi, tests) * Refactoring tests - receive_teleported_asset_for_native_asset_works * ForeignAssets for statemine + refactored `receive_teleported_asset_from_foreign_creator_works` * Add `ForeignAssets` to statemine `FungiblesApi` * Add `asset_transactor_transfer_with_local_consensus_currency_works` to all runtimes * Added `asset_transactor_transfer_with_trust_backed_assets_works` test * Added `asset_transactor_transfer_with_foreign_assets_works` * Fix `missing `try_successful_origin` in implementation` * Added `create_and_manage_foreign_assets_for_local_consensus_parachain_assets_works` * Added `ExpectTransactStatus` check * Small rename * Extended `test_assets_balances_api_works` with ForeignAssets for `statemine` * PR fixes * Update parachains/runtimes/assets/test-utils/src/test_cases.rs --------- Co-authored-by: parity-processbot <> Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Added `StartsWithExplicitGlobalConsensus` to ignores (#2338) * Update parachains/runtimes/assets/common/src/lib.rs Co-authored-by: Gavin Wood <gavin@parity.io> * include mint and burn in SafeCallFilter * include mint and burn in SafeCallFilter (statemine) * clarify doc * Fix compilation (moved trait `InspectMetadata`) * Fix test * Extended test for `teleport` from/to relaychain + `CheckingAccount` (Part I) * Extended test for `teleport` from/to foreign parachain + `CheckingAccount` (Part II) * Fixed TODO - `NonLocal` for `ForeignAssets` * Changed `NonLocal` to `NoChecking` * Fix weight in test --------- Co-authored-by: parity-processbot <> Co-authored-by: muharem <ismailov.m.h@gmail.com> Co-authored-by: Branislav Kontur <bkontur@gmail.com> Co-authored-by: Gavin Wood <gavin@parity.io>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2023 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use frame_support::traits::{
|
||||
ContainsPair, EnsureOrigin, EnsureOriginWithArg, Everything, OriginTrait,
|
||||
};
|
||||
use pallet_xcm::{EnsureXcm, Origin as XcmOrigin};
|
||||
use xcm::latest::MultiLocation;
|
||||
use xcm_executor::traits::Convert;
|
||||
|
||||
// `EnsureOriginWithArg` impl for `CreateOrigin` that allows only XCM origins that are locations
|
||||
// containing the class location.
|
||||
pub struct ForeignCreators<IsForeign, AccountOf, AccountId>(
|
||||
sp_std::marker::PhantomData<(IsForeign, AccountOf, AccountId)>,
|
||||
);
|
||||
impl<
|
||||
IsForeign: ContainsPair<MultiLocation, MultiLocation>,
|
||||
AccountOf: Convert<MultiLocation, AccountId>,
|
||||
AccountId: Clone,
|
||||
RuntimeOrigin: From<XcmOrigin> + OriginTrait + Clone,
|
||||
> EnsureOriginWithArg<RuntimeOrigin, MultiLocation>
|
||||
for ForeignCreators<IsForeign, AccountOf, AccountId>
|
||||
where
|
||||
RuntimeOrigin::PalletsOrigin:
|
||||
From<XcmOrigin> + TryInto<XcmOrigin, Error = RuntimeOrigin::PalletsOrigin>,
|
||||
{
|
||||
type Success = AccountId;
|
||||
|
||||
fn try_origin(
|
||||
origin: RuntimeOrigin,
|
||||
asset_location: &MultiLocation,
|
||||
) -> sp_std::result::Result<Self::Success, RuntimeOrigin> {
|
||||
let origin_location = EnsureXcm::<Everything>::try_origin(origin.clone())?;
|
||||
if !IsForeign::contains(&asset_location, &origin_location) {
|
||||
return Err(origin)
|
||||
}
|
||||
AccountOf::convert(origin_location).map_err(|_| origin)
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn try_successful_origin(a: &MultiLocation) -> Result<RuntimeOrigin, ()> {
|
||||
Ok(pallet_xcm::Origin::Xcm(a.clone()).into())
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,25 @@
|
||||
// This file is part of Substrate.
|
||||
// Copyright (C) 2023 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Copyright (C) 2018-2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Runtime API definition for assets.
|
||||
|
||||
use crate::runtime_api::FungiblesAccessError;
|
||||
use frame_support::traits::Contains;
|
||||
use sp_std::{borrow::Borrow, vec::Vec};
|
||||
use xcm::latest::{MultiAsset, MultiLocation};
|
||||
use xcm_builder::ConvertedConcreteId;
|
||||
use xcm_builder::{ConvertedConcreteId, MatchedConvertedConcreteId};
|
||||
use xcm_executor::traits::{Convert, MatchesFungibles};
|
||||
|
||||
/// Converting any [`(AssetId, Balance)`] to [`MultiAsset`]
|
||||
@@ -60,6 +58,29 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
MatchAssetId: Contains<MultiLocation>,
|
||||
ConvertAssetId: Convert<MultiLocation, AssetId>,
|
||||
ConvertBalance: Convert<u128, Balance>,
|
||||
> MultiAssetConverter<AssetId, Balance, ConvertAssetId, ConvertBalance>
|
||||
for MatchedConvertedConcreteId<AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn convert_ref(
|
||||
value: impl Borrow<(AssetId, Balance)>,
|
||||
) -> Result<MultiAsset, FungiblesAccessError> {
|
||||
let (asset_id, balance) = value.borrow();
|
||||
match ConvertAssetId::reverse_ref(asset_id) {
|
||||
Ok(asset_id_as_multilocation) => match ConvertBalance::reverse_ref(balance) {
|
||||
Ok(amount) => Ok((asset_id_as_multilocation, amount).into()),
|
||||
Err(_) => Err(FungiblesAccessError::AmountToBalanceConversionFailed),
|
||||
},
|
||||
Err(_) => Err(FungiblesAccessError::AssetIdConversionFailed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)>,
|
||||
@@ -90,11 +111,12 @@ pub fn convert_balance<
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use frame_support::traits::Everything;
|
||||
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::traits::{Identity, JustTry};
|
||||
|
||||
type Converter = ConvertedConcreteId<MultiLocation, u64, Identity, JustTry>;
|
||||
type Converter = MatchedConvertedConcreteId<MultiLocation, u64, Everything, Identity, JustTry>;
|
||||
|
||||
#[test]
|
||||
fn converted_concrete_id_fungible_multi_asset_conversion_roundtrip_works() {
|
||||
|
||||
@@ -15,39 +15,79 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub mod foreign_creators;
|
||||
pub mod fungible_conversion;
|
||||
pub mod matching;
|
||||
pub mod runtime_api;
|
||||
|
||||
use crate::matching::{Equals, LocalMultiLocationPattern, ParentLocation, StartsWith};
|
||||
use frame_support::traits::EverythingBut;
|
||||
use parachains_common::AssetIdForTrustBackedAssets;
|
||||
use xcm_builder::{AsPrefixedGeneralIndex, ConvertedConcreteId};
|
||||
use xcm_executor::traits::JustTry;
|
||||
use xcm::prelude::MultiLocation;
|
||||
use xcm_builder::{AsPrefixedGeneralIndex, MatchedConvertedConcreteId};
|
||||
use xcm_executor::traits::{Identity, JustTry};
|
||||
|
||||
/// `MultiLocation` vs `AssetIdForTrustBackedAssets` converter for `TrustBackedAssets`
|
||||
pub type AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation> =
|
||||
AsPrefixedGeneralIndex<TrustBackedAssetsPalletLocation, AssetIdForTrustBackedAssets, JustTry>;
|
||||
|
||||
/// [`ConvertedConcreteId`] converter dedicated for `TrustBackedAssets`
|
||||
/// [`MatchedConvertedConcreteId`] converter dedicated for `TrustBackedAssets`
|
||||
pub type TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, Balance> =
|
||||
ConvertedConcreteId<
|
||||
MatchedConvertedConcreteId<
|
||||
AssetIdForTrustBackedAssets,
|
||||
Balance,
|
||||
StartsWith<TrustBackedAssetsPalletLocation>,
|
||||
AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation>,
|
||||
JustTry,
|
||||
>;
|
||||
|
||||
/// AssetId used for identifying assets by MultiLocation.
|
||||
pub type MultiLocationForAssetId = MultiLocation;
|
||||
|
||||
/// [`MatchedConvertedConcreteId`] converter dedicated for storing `AssetId` as `MultiLocation`.
|
||||
pub type MultiLocationConvertedConcreteId<MultiLocationFilter, Balance> =
|
||||
MatchedConvertedConcreteId<
|
||||
MultiLocationForAssetId,
|
||||
Balance,
|
||||
MultiLocationFilter,
|
||||
Identity,
|
||||
JustTry,
|
||||
>;
|
||||
|
||||
/// [`MatchedConvertedConcreteId`] converter dedicated for storing `ForeignAssets` with `AssetId` as `MultiLocation`.
|
||||
///
|
||||
/// Excludes by default:
|
||||
/// - parent as relay chain
|
||||
/// - all local MultiLocations
|
||||
///
|
||||
/// `AdditionalMultiLocationExclusionFilter` can customize additional excluded MultiLocations
|
||||
pub type ForeignAssetsConvertedConcreteId<AdditionalMultiLocationExclusionFilter, Balance> =
|
||||
MultiLocationConvertedConcreteId<
|
||||
EverythingBut<(
|
||||
// Excludes relay/parent chain currency
|
||||
Equals<ParentLocation>,
|
||||
// Here we rely on fact that something like this works:
|
||||
// assert!(MultiLocation::new(1, X1(Parachain(100))).starts_with(&MultiLocation::parent()));
|
||||
// assert!(X1(Parachain(100)).starts_with(&Here));
|
||||
StartsWith<LocalMultiLocationPattern>,
|
||||
// Here we can exclude more stuff or leave it as `()`
|
||||
AdditionalMultiLocationExclusionFilter,
|
||||
)>,
|
||||
Balance,
|
||||
>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::matching::StartsWithExplicitGlobalConsensus;
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::traits::Convert;
|
||||
|
||||
frame_support::parameter_types! {
|
||||
pub TrustBackedAssetsPalletLocation: MultiLocation = MultiLocation::new(5, X1(PalletInstance(13)));
|
||||
}
|
||||
use xcm_executor::traits::{Convert, Error as MatchError, MatchesFungibles};
|
||||
|
||||
#[test]
|
||||
fn asset_id_for_trust_backed_assets_convert_works() {
|
||||
frame_support::parameter_types! {
|
||||
pub TrustBackedAssetsPalletLocation: MultiLocation = MultiLocation::new(5, X1(PalletInstance(13)));
|
||||
}
|
||||
let local_asset_id = 123456789 as AssetIdForTrustBackedAssets;
|
||||
let expected_reverse_ref =
|
||||
MultiLocation::new(5, X2(PalletInstance(13), GeneralIndex(local_asset_id.into())));
|
||||
@@ -67,4 +107,201 @@ mod tests {
|
||||
local_asset_id
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trust_backed_assets_match_fungibles_works() {
|
||||
frame_support::parameter_types! {
|
||||
pub TrustBackedAssetsPalletLocation: MultiLocation = MultiLocation::new(0, X1(PalletInstance(13)));
|
||||
}
|
||||
// setup convert
|
||||
type TrustBackedAssetsConvert =
|
||||
TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, u128>;
|
||||
|
||||
let test_data = vec![
|
||||
// missing GeneralIndex
|
||||
(ma_1000(0, X1(PalletInstance(13))), Err(MatchError::AssetIdConversionFailed)),
|
||||
(
|
||||
ma_1000(0, X2(PalletInstance(13), GeneralKey { data: [0; 32], length: 32 })),
|
||||
Err(MatchError::AssetIdConversionFailed),
|
||||
),
|
||||
(
|
||||
ma_1000(0, X2(PalletInstance(13), Parachain(1000))),
|
||||
Err(MatchError::AssetIdConversionFailed),
|
||||
),
|
||||
// OK
|
||||
(ma_1000(0, X2(PalletInstance(13), GeneralIndex(1234))), Ok((1234, 1000))),
|
||||
(
|
||||
ma_1000(0, X3(PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222))),
|
||||
Ok((1234, 1000)),
|
||||
),
|
||||
(
|
||||
ma_1000(
|
||||
0,
|
||||
X4(
|
||||
PalletInstance(13),
|
||||
GeneralIndex(1234),
|
||||
GeneralIndex(2222),
|
||||
GeneralKey { data: [0; 32], length: 32 },
|
||||
),
|
||||
),
|
||||
Ok((1234, 1000)),
|
||||
),
|
||||
// wrong pallet instance
|
||||
(
|
||||
ma_1000(0, X2(PalletInstance(77), GeneralIndex(1234))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
(
|
||||
ma_1000(0, X3(PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
// wrong parent
|
||||
(
|
||||
ma_1000(1, X2(PalletInstance(13), GeneralIndex(1234))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
(
|
||||
ma_1000(1, X3(PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
(
|
||||
ma_1000(1, X2(PalletInstance(77), GeneralIndex(1234))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
(
|
||||
ma_1000(1, X3(PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
// wrong parent
|
||||
(
|
||||
ma_1000(2, X2(PalletInstance(13), GeneralIndex(1234))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
(
|
||||
ma_1000(2, X3(PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
// missing GeneralIndex
|
||||
(ma_1000(0, X1(PalletInstance(77))), Err(MatchError::AssetNotHandled)),
|
||||
(ma_1000(1, X1(PalletInstance(13))), Err(MatchError::AssetNotHandled)),
|
||||
(ma_1000(2, X1(PalletInstance(13))), Err(MatchError::AssetNotHandled)),
|
||||
];
|
||||
|
||||
for (multi_asset, expected_result) in test_data {
|
||||
assert_eq!(
|
||||
<TrustBackedAssetsConvert as MatchesFungibles<AssetIdForTrustBackedAssets, u128>>::matches_fungibles(&multi_asset),
|
||||
expected_result, "multi_asset: {:?}", multi_asset);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_location_converted_concrete_id_converter_works() {
|
||||
frame_support::parameter_types! {
|
||||
pub Parachain100Pattern: MultiLocation = MultiLocation::new(1, X1(Parachain(100)));
|
||||
pub UniversalLocationNetworkId: NetworkId = NetworkId::ByGenesis([9; 32]);
|
||||
}
|
||||
|
||||
// setup convert
|
||||
type Convert = ForeignAssetsConvertedConcreteId<
|
||||
(
|
||||
StartsWith<Parachain100Pattern>,
|
||||
StartsWithExplicitGlobalConsensus<UniversalLocationNetworkId>,
|
||||
),
|
||||
u128,
|
||||
>;
|
||||
|
||||
let test_data = vec![
|
||||
// excluded as local
|
||||
(ma_1000(0, Here), Err(MatchError::AssetNotHandled)),
|
||||
(ma_1000(0, X1(Parachain(100))), Err(MatchError::AssetNotHandled)),
|
||||
(
|
||||
ma_1000(0, X2(PalletInstance(13), GeneralIndex(1234))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
// excluded as parent
|
||||
(ma_1000(1, Here), Err(MatchError::AssetNotHandled)),
|
||||
// excluded as additional filter - Parachain100Pattern
|
||||
(ma_1000(1, X1(Parachain(100))), Err(MatchError::AssetNotHandled)),
|
||||
(ma_1000(1, X2(Parachain(100), GeneralIndex(1234))), Err(MatchError::AssetNotHandled)),
|
||||
(
|
||||
ma_1000(1, X3(Parachain(100), PalletInstance(13), GeneralIndex(1234))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
// excluded as additional filter - StartsWithExplicitGlobalConsensus
|
||||
(
|
||||
ma_1000(1, X1(GlobalConsensus(NetworkId::ByGenesis([9; 32])))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
(
|
||||
ma_1000(2, X1(GlobalConsensus(NetworkId::ByGenesis([9; 32])))),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
(
|
||||
ma_1000(
|
||||
2,
|
||||
X3(
|
||||
GlobalConsensus(NetworkId::ByGenesis([9; 32])),
|
||||
Parachain(200),
|
||||
GeneralIndex(1234),
|
||||
),
|
||||
),
|
||||
Err(MatchError::AssetNotHandled),
|
||||
),
|
||||
// ok
|
||||
(ma_1000(1, X1(Parachain(200))), Ok((MultiLocation::new(1, X1(Parachain(200))), 1000))),
|
||||
(ma_1000(2, X1(Parachain(200))), Ok((MultiLocation::new(2, X1(Parachain(200))), 1000))),
|
||||
(
|
||||
ma_1000(1, X2(Parachain(200), GeneralIndex(1234))),
|
||||
Ok((MultiLocation::new(1, X2(Parachain(200), GeneralIndex(1234))), 1000)),
|
||||
),
|
||||
(
|
||||
ma_1000(2, X2(Parachain(200), GeneralIndex(1234))),
|
||||
Ok((MultiLocation::new(2, X2(Parachain(200), GeneralIndex(1234))), 1000)),
|
||||
),
|
||||
(
|
||||
ma_1000(2, X1(GlobalConsensus(NetworkId::ByGenesis([7; 32])))),
|
||||
Ok((
|
||||
MultiLocation::new(2, X1(GlobalConsensus(NetworkId::ByGenesis([7; 32])))),
|
||||
1000,
|
||||
)),
|
||||
),
|
||||
(
|
||||
ma_1000(
|
||||
2,
|
||||
X3(
|
||||
GlobalConsensus(NetworkId::ByGenesis([7; 32])),
|
||||
Parachain(200),
|
||||
GeneralIndex(1234),
|
||||
),
|
||||
),
|
||||
Ok((
|
||||
MultiLocation::new(
|
||||
2,
|
||||
X3(
|
||||
GlobalConsensus(NetworkId::ByGenesis([7; 32])),
|
||||
Parachain(200),
|
||||
GeneralIndex(1234),
|
||||
),
|
||||
),
|
||||
1000,
|
||||
)),
|
||||
),
|
||||
];
|
||||
|
||||
for (multi_asset, expected_result) in test_data {
|
||||
assert_eq!(
|
||||
<Convert as MatchesFungibles<MultiLocationForAssetId, u128>>::matches_fungibles(
|
||||
&multi_asset
|
||||
),
|
||||
expected_result,
|
||||
"multi_asset: {:?}",
|
||||
multi_asset
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create MultiAsset
|
||||
fn ma_1000(parents: u8, interior: Junctions) -> MultiAsset {
|
||||
(MultiLocation::new(parents, interior), 1000).into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2023 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use cumulus_primitives_core::ParaId;
|
||||
use frame_support::{
|
||||
pallet_prelude::Get,
|
||||
traits::{Contains, ContainsPair},
|
||||
};
|
||||
use xcm::{
|
||||
latest::prelude::{MultiAsset, MultiLocation},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
pub struct StartsWith<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<Location: Get<MultiLocation>> Contains<MultiLocation> for StartsWith<Location> {
|
||||
fn contains(t: &MultiLocation) -> bool {
|
||||
t.starts_with(&Location::get())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Equals<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<Location: Get<MultiLocation>> Contains<MultiLocation> for Equals<Location> {
|
||||
fn contains(t: &MultiLocation) -> bool {
|
||||
t == &Location::get()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StartsWithExplicitGlobalConsensus<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<Network: Get<NetworkId>> Contains<MultiLocation>
|
||||
for StartsWithExplicitGlobalConsensus<Network>
|
||||
{
|
||||
fn contains(t: &MultiLocation) -> bool {
|
||||
match t.interior.global_consensus() {
|
||||
Ok(requested_network) if requested_network.eq(&Network::get()) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame_support::parameter_types! {
|
||||
pub LocalMultiLocationPattern: MultiLocation = MultiLocation::new(0, Here);
|
||||
pub ParentLocation: MultiLocation = MultiLocation::parent();
|
||||
}
|
||||
|
||||
/// Accepts an asset if it is from the origin.
|
||||
pub struct IsForeignConcreteAsset<IsForeign>(sp_std::marker::PhantomData<IsForeign>);
|
||||
impl<IsForeign: ContainsPair<MultiLocation, MultiLocation>> ContainsPair<MultiAsset, MultiLocation>
|
||||
for IsForeignConcreteAsset<IsForeign>
|
||||
{
|
||||
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
|
||||
log::trace!(target: "xcm::contains", "IsForeignConcreteAsset asset: {:?}, origin: {:?}", asset, origin);
|
||||
matches!(asset.id, Concrete(ref id) if IsForeign::contains(id, &origin))
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `a` is from sibling location `b`. Checks that `MultiLocation-a` starts with
|
||||
/// `MultiLocation-b`, and that the `ParaId` of `b` is not equal to `a`.
|
||||
pub struct FromSiblingParachain<SelfParaId>(sp_std::marker::PhantomData<SelfParaId>);
|
||||
impl<SelfParaId: Get<ParaId>> ContainsPair<MultiLocation, MultiLocation>
|
||||
for FromSiblingParachain<SelfParaId>
|
||||
{
|
||||
fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool {
|
||||
// `a` needs to be from `b` at least
|
||||
if !a.starts_with(&b) {
|
||||
return false
|
||||
}
|
||||
|
||||
// here we check if sibling
|
||||
match a {
|
||||
MultiLocation { parents: 1, interior } => match interior.first() {
|
||||
Some(Parachain(sibling_para_id))
|
||||
if sibling_para_id.ne(&u32::from(SelfParaId::get())) =>
|
||||
true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user