# Note for reviewer

Most changes are just syntax changes necessary for the new version.
Most important files should be the ones under the `xcm` folder.

# Description 

Added XCMv4.

## Removed `Multi` prefix
The following types have been renamed:
- MultiLocation -> Location
- MultiAsset -> Asset
- MultiAssets -> Assets
- InteriorMultiLocation -> InteriorLocation
- MultiAssetFilter -> AssetFilter
- VersionedMultiAsset -> VersionedAsset
- WildMultiAsset -> WildAsset
- VersionedMultiLocation -> VersionedLocation

In order to fix a name conflict, the `Assets` in `xcm-executor` were
renamed to `HoldingAssets`, as they represent assets in holding.

## Removed `Abstract` asset id

It was not being used anywhere and this simplifies the code.

Now assets are just constructed as follows:

```rust
let asset: Asset = (AssetId(Location::new(1, Here)), 100u128).into();
```

No need for specifying `Concrete` anymore.

## Outcome is now a named fields struct

Instead of

```rust
pub enum Outcome {
  Complete(Weight),
  Incomplete(Weight, Error),
  Error(Error),
}
```

we now have

```rust
pub enum Outcome {
  Complete { used: Weight },
  Incomplete { used: Weight, error: Error },
  Error { error: Error },
}
```

## Added Reanchorable trait

Now both locations and assets implement this trait, making it easier to
reanchor both.

## New syntax for building locations and junctions

Now junctions are built using the following methods:

```rust
let location = Location {
    parents: 1,
    interior: [Parachain(1000), PalletInstance(50), GeneralIndex(1984)].into()
};
```

or

```rust
let location = Location::new(1, [Parachain(1000), PalletInstance(50), GeneralIndex(1984)]);
```

And they are matched like so:

```rust
match location.unpack() {
  (1, [Parachain(id)]) => ...
  (0, Here) => ...,
  (1, [_]) => ...,
}
```

This syntax is mandatory in v4, and has been also implemented for v2 and
v3 for easier migration.

This was needed to make all sizes smaller.

# TODO
- [x] Scaffold v4
- [x] Port github.com/paritytech/polkadot/pull/7236
- [x] Remove `Multi` prefix
- [x] Remove `Abstract` asset id

---------

Co-authored-by: command-bot <>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
This commit is contained in:
Francisco Aguirre
2024-01-16 19:18:04 +01:00
committed by GitHub
parent ec7bfae00a
commit 8428f678fe
255 changed files with 12425 additions and 6726 deletions
@@ -23,15 +23,24 @@ pub mod local_and_foreign_assets;
pub mod matching;
pub mod runtime_api;
use crate::matching::{LocalMultiLocationPattern, ParentLocation};
use crate::matching::{LocalLocationPattern, ParentLocation};
use frame_support::traits::{Equals, EverythingBut};
use parachains_common::AssetIdForTrustBackedAssets;
use xcm::prelude::MultiLocation;
use xcm_builder::{AsPrefixedGeneralIndex, MatchedConvertedConcreteId, StartsWith};
use xcm_executor::traits::{Identity, JustTry};
use xcm_builder::{
AsPrefixedGeneralIndex, MatchedConvertedConcreteId, StartsWith, V4V3LocationConverter,
};
use xcm_executor::traits::JustTry;
/// `MultiLocation` vs `AssetIdForTrustBackedAssets` converter for `TrustBackedAssets`
/// `Location` vs `AssetIdForTrustBackedAssets` converter for `TrustBackedAssets`
pub type AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation> =
AsPrefixedGeneralIndex<
TrustBackedAssetsPalletLocation,
AssetIdForTrustBackedAssets,
JustTry,
xcm::v3::Location,
>;
pub type AssetIdForTrustBackedAssetsConvertLatest<TrustBackedAssetsPalletLocation> =
AsPrefixedGeneralIndex<TrustBackedAssetsPalletLocation, AssetIdForTrustBackedAssets, JustTry>;
/// [`MatchedConvertedConcreteId`] converter dedicated for `TrustBackedAssets`
@@ -40,59 +49,55 @@ pub type TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, B
AssetIdForTrustBackedAssets,
Balance,
StartsWith<TrustBackedAssetsPalletLocation>,
AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation>,
AssetIdForTrustBackedAssetsConvertLatest<TrustBackedAssetsPalletLocation>,
JustTry,
>;
/// AssetId used for identifying assets by MultiLocation.
pub type MultiLocationForAssetId = MultiLocation;
/// [`MatchedConvertedConcreteId`] converter dedicated for storing `AssetId` as `Location`.
pub type LocationConvertedConcreteId<LocationFilter, Balance> = MatchedConvertedConcreteId<
xcm::v3::Location,
Balance,
LocationFilter,
V4V3LocationConverter,
JustTry,
>;
/// [`MatchedConvertedConcreteId`] converter dedicated for `TrustBackedAssets`
pub type TrustBackedAssetsAsMultiLocation<TrustBackedAssetsPalletLocation, Balance> =
pub type TrustBackedAssetsAsLocation<TrustBackedAssetsPalletLocation, Balance> =
MatchedConvertedConcreteId<
MultiLocationForAssetId,
xcm::v3::Location,
Balance,
StartsWith<TrustBackedAssetsPalletLocation>,
Identity,
JustTry,
>;
/// [`MatchedConvertedConcreteId`] converter dedicated for storing `AssetId` as `MultiLocation`.
pub type MultiLocationConvertedConcreteId<MultiLocationFilter, Balance> =
MatchedConvertedConcreteId<
MultiLocationForAssetId,
Balance,
MultiLocationFilter,
Identity,
V4V3LocationConverter,
JustTry,
>;
/// [`MatchedConvertedConcreteId`] converter dedicated for storing `ForeignAssets` with `AssetId` as
/// `MultiLocation`.
/// `Location`.
///
/// Excludes by default:
/// - parent as relay chain
/// - all local MultiLocations
/// - all local Locations
///
/// `AdditionalMultiLocationExclusionFilter` can customize additional excluded MultiLocations
pub type ForeignAssetsConvertedConcreteId<AdditionalMultiLocationExclusionFilter, Balance> =
MultiLocationConvertedConcreteId<
/// `AdditionalLocationExclusionFilter` can customize additional excluded Locations
pub type ForeignAssetsConvertedConcreteId<AdditionalLocationExclusionFilter, Balance> =
LocationConvertedConcreteId<
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>,
// assert!(Location::new(1,
// [Parachain(100)]).starts_with(&Location::parent()));
// assert!([Parachain(100)].into().starts_with(&Here));
StartsWith<LocalLocationPattern>,
// Here we can exclude more stuff or leave it as `()`
AdditionalMultiLocationExclusionFilter,
AdditionalLocationExclusionFilter,
)>,
Balance,
>;
type AssetIdForPoolAssets = u32;
/// `MultiLocation` vs `AssetIdForPoolAssets` converter for `PoolAssets`.
/// `Location` vs `AssetIdForPoolAssets` converter for `PoolAssets`.
pub type AssetIdForPoolAssetsConvert<PoolAssetsPalletLocation> =
AsPrefixedGeneralIndex<PoolAssetsPalletLocation, AssetIdForPoolAssets, JustTry>;
/// [`MatchedConvertedConcreteId`] converter dedicated for `PoolAssets`
@@ -109,28 +114,28 @@ pub type PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance> =
mod tests {
use super::*;
use sp_runtime::traits::MaybeEquivalence;
use xcm::latest::prelude::*;
use xcm::prelude::*;
use xcm_builder::StartsWithExplicitGlobalConsensus;
use xcm_executor::traits::{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)));
pub TrustBackedAssetsPalletLocation: Location = Location::new(5, [PalletInstance(13)]);
}
let local_asset_id = 123456789 as AssetIdForTrustBackedAssets;
let expected_reverse_ref =
MultiLocation::new(5, X2(PalletInstance(13), GeneralIndex(local_asset_id.into())));
Location::new(5, [PalletInstance(13), GeneralIndex(local_asset_id.into())]);
assert_eq!(
AssetIdForTrustBackedAssetsConvert::<TrustBackedAssetsPalletLocation>::convert_back(
AssetIdForTrustBackedAssetsConvertLatest::<TrustBackedAssetsPalletLocation>::convert_back(
&local_asset_id
)
.unwrap(),
expected_reverse_ref
);
assert_eq!(
AssetIdForTrustBackedAssetsConvert::<TrustBackedAssetsPalletLocation>::convert(
AssetIdForTrustBackedAssetsConvertLatest::<TrustBackedAssetsPalletLocation>::convert(
&expected_reverse_ref
)
.unwrap(),
@@ -141,7 +146,7 @@ mod tests {
#[test]
fn trust_backed_assets_match_fungibles_works() {
frame_support::parameter_types! {
pub TrustBackedAssetsPalletLocation: MultiLocation = MultiLocation::new(0, X1(PalletInstance(13)));
pub TrustBackedAssetsPalletLocation: Location = Location::new(0, [PalletInstance(13)]);
}
// setup convert
type TrustBackedAssetsConvert =
@@ -149,85 +154,86 @@ mod tests {
let test_data = vec![
// missing GeneralIndex
(ma_1000(0, X1(PalletInstance(13))), Err(MatchError::AssetIdConversionFailed)),
(ma_1000(0, [PalletInstance(13)].into()), Err(MatchError::AssetIdConversionFailed)),
(
ma_1000(0, X2(PalletInstance(13), GeneralKey { data: [0; 32], length: 32 })),
ma_1000(0, [PalletInstance(13), GeneralKey { data: [0; 32], length: 32 }].into()),
Err(MatchError::AssetIdConversionFailed),
),
(
ma_1000(0, X2(PalletInstance(13), Parachain(1000))),
ma_1000(0, [PalletInstance(13), Parachain(1000)].into()),
Err(MatchError::AssetIdConversionFailed),
),
// OK
(ma_1000(0, X2(PalletInstance(13), GeneralIndex(1234))), Ok((1234, 1000))),
(ma_1000(0, [PalletInstance(13), GeneralIndex(1234)].into()), Ok((1234, 1000))),
(
ma_1000(0, X3(PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222))),
ma_1000(0, [PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222)].into()),
Ok((1234, 1000)),
),
(
ma_1000(
0,
X4(
[
PalletInstance(13),
GeneralIndex(1234),
GeneralIndex(2222),
GeneralKey { data: [0; 32], length: 32 },
),
]
.into(),
),
Ok((1234, 1000)),
),
// wrong pallet instance
(
ma_1000(0, X2(PalletInstance(77), GeneralIndex(1234))),
ma_1000(0, [PalletInstance(77), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(0, X3(PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222))),
ma_1000(0, [PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222)].into()),
Err(MatchError::AssetNotHandled),
),
// wrong parent
(
ma_1000(1, X2(PalletInstance(13), GeneralIndex(1234))),
ma_1000(1, [PalletInstance(13), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, X3(PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222))),
ma_1000(1, [PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, X2(PalletInstance(77), GeneralIndex(1234))),
ma_1000(1, [PalletInstance(77), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, X3(PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222))),
ma_1000(1, [PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222)].into()),
Err(MatchError::AssetNotHandled),
),
// wrong parent
(
ma_1000(2, X2(PalletInstance(13), GeneralIndex(1234))),
ma_1000(2, [PalletInstance(13), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(2, X3(PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222))),
ma_1000(2, [PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222)].into()),
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)),
(ma_1000(0, [PalletInstance(77)].into()), Err(MatchError::AssetNotHandled)),
(ma_1000(1, [PalletInstance(13)].into()), Err(MatchError::AssetNotHandled)),
(ma_1000(2, [PalletInstance(13)].into()), Err(MatchError::AssetNotHandled)),
];
for (multi_asset, expected_result) in test_data {
for (asset, expected_result) in test_data {
assert_eq!(
<TrustBackedAssetsConvert as MatchesFungibles<AssetIdForTrustBackedAssets, u128>>::matches_fungibles(&multi_asset),
expected_result, "multi_asset: {:?}", multi_asset);
<TrustBackedAssetsConvert as MatchesFungibles<AssetIdForTrustBackedAssets, u128>>::matches_fungibles(&asset.clone().try_into().unwrap()),
expected_result, "asset: {:?}", asset);
}
}
#[test]
fn multi_location_converted_concrete_id_converter_works() {
fn location_converted_concrete_id_converter_works() {
frame_support::parameter_types! {
pub Parachain100Pattern: MultiLocation = MultiLocation::new(1, X1(Parachain(100)));
pub Parachain100Pattern: Location = Location::new(1, [Parachain(100)]);
pub UniversalLocationNetworkId: NetworkId = NetworkId::ByGenesis([9; 32]);
}
@@ -243,95 +249,125 @@ mod tests {
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, [Parachain(100)].into()), Err(MatchError::AssetNotHandled)),
(
ma_1000(0, X2(PalletInstance(13), GeneralIndex(1234))),
ma_1000(0, [PalletInstance(13), GeneralIndex(1234)].into()),
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, [Parachain(100)].into()), Err(MatchError::AssetNotHandled)),
(
ma_1000(1, X3(Parachain(100), PalletInstance(13), GeneralIndex(1234))),
ma_1000(1, [Parachain(100), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [Parachain(100), PalletInstance(13), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
// excluded as additional filter - StartsWithExplicitGlobalConsensus
(
ma_1000(1, X1(GlobalConsensus(NetworkId::ByGenesis([9; 32])))),
ma_1000(1, [GlobalConsensus(NetworkId::ByGenesis([9; 32]))].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(2, X1(GlobalConsensus(NetworkId::ByGenesis([9; 32])))),
ma_1000(2, [GlobalConsensus(NetworkId::ByGenesis([9; 32]))].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(
2,
X3(
[
GlobalConsensus(NetworkId::ByGenesis([9; 32])),
Parachain(200),
GeneralIndex(1234),
),
]
.into(),
),
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(1, [Parachain(200)].into()),
Ok((xcm::v3::Location::new(1, [xcm::v3::Junction::Parachain(200)]), 1000)),
),
(
ma_1000(2, X2(Parachain(200), GeneralIndex(1234))),
Ok((MultiLocation::new(2, X2(Parachain(200), GeneralIndex(1234))), 1000)),
ma_1000(2, [Parachain(200)].into()),
Ok((xcm::v3::Location::new(2, [xcm::v3::Junction::Parachain(200)]), 1000)),
),
(
ma_1000(2, X1(GlobalConsensus(NetworkId::ByGenesis([7; 32])))),
ma_1000(1, [Parachain(200), GeneralIndex(1234)].into()),
Ok((
MultiLocation::new(2, X1(GlobalConsensus(NetworkId::ByGenesis([7; 32])))),
xcm::v3::Location::new(
1,
[xcm::v3::Junction::Parachain(200), xcm::v3::Junction::GeneralIndex(1234)],
),
1000,
)),
),
(
ma_1000(2, [Parachain(200), GeneralIndex(1234)].into()),
Ok((
xcm::v3::Location::new(
2,
[xcm::v3::Junction::Parachain(200), xcm::v3::Junction::GeneralIndex(1234)],
),
1000,
)),
),
(
ma_1000(2, [GlobalConsensus(NetworkId::ByGenesis([7; 32]))].into()),
Ok((
xcm::v3::Location::new(
2,
[xcm::v3::Junction::GlobalConsensus(xcm::v3::NetworkId::ByGenesis(
[7; 32],
))],
),
1000,
)),
),
(
ma_1000(
2,
X3(
[
GlobalConsensus(NetworkId::ByGenesis([7; 32])),
Parachain(200),
GeneralIndex(1234),
),
]
.into(),
),
Ok((
MultiLocation::new(
xcm::v3::Location::new(
2,
X3(
GlobalConsensus(NetworkId::ByGenesis([7; 32])),
Parachain(200),
GeneralIndex(1234),
),
[
xcm::v3::Junction::GlobalConsensus(xcm::v3::NetworkId::ByGenesis(
[7; 32],
)),
xcm::v3::Junction::Parachain(200),
xcm::v3::Junction::GeneralIndex(1234),
],
),
1000,
)),
),
];
for (multi_asset, expected_result) in test_data {
for (asset, expected_result) in test_data {
assert_eq!(
<Convert as MatchesFungibles<MultiLocationForAssetId, u128>>::matches_fungibles(
&multi_asset
<Convert as MatchesFungibles<xcm::v3::MultiLocation, u128>>::matches_fungibles(
&asset.clone().try_into().unwrap()
),
expected_result,
"multi_asset: {:?}",
multi_asset
"asset: {:?}",
asset
);
}
}
// Create MultiAsset
fn ma_1000(parents: u8, interior: Junctions) -> MultiAsset {
(MultiLocation::new(parents, interior), 1000).into()
// Create Asset
fn ma_1000(parents: u8, interior: Junctions) -> Asset {
(Location::new(parents, interior), 1000).into()
}
}