# 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
+9 -9
View File
@@ -24,8 +24,8 @@ use pallet_asset_tx_payment::HandleCredit;
use sp_runtime::traits::Zero;
use sp_std::{marker::PhantomData, prelude::*};
use xcm::latest::{
AssetId, Fungibility, Fungibility::Fungible, Junction, Junctions::Here, MultiAsset,
MultiLocation, Parent, WeightLimit,
Asset, AssetId, Fungibility, Fungibility::Fungible, Junction, Junctions::Here, Location,
Parent, WeightLimit,
};
use xcm_executor::traits::ConvertLocation;
@@ -113,11 +113,11 @@ where
/// Asset filter that allows all assets from a certain location.
pub struct AssetsFrom<T>(PhantomData<T>);
impl<T: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation> for AssetsFrom<T> {
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
impl<T: Get<Location>> ContainsPair<Asset, Location> for AssetsFrom<T> {
fn contains(asset: &Asset, origin: &Location) -> bool {
let loc = T::get();
&loc == origin &&
matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) }
matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) }
if asset_loc.match_and_split(&loc).is_some())
}
}
@@ -148,7 +148,7 @@ where
Err(amount) => amount,
};
let imbalance = amount.peek();
let root_location: MultiLocation = Here.into();
let root_location: Location = Here.into();
let root_account: AccountIdOf<T> =
match AccountIdConverter::convert_location(&root_location) {
Some(a) => a,
@@ -329,13 +329,13 @@ mod tests {
#[test]
fn assets_from_filters_correctly() {
parameter_types! {
pub SomeSiblingParachain: MultiLocation = MultiLocation::new(1, X1(Parachain(1234)));
pub SomeSiblingParachain: Location = (Parent, Parachain(1234)).into();
}
let asset_location = SomeSiblingParachain::get()
.pushed_with_interior(GeneralIndex(42))
.expect("multilocation will only have 2 junctions; qed");
let asset = MultiAsset { id: Concrete(asset_location), fun: 1_000_000u128.into() };
.expect("location will only have 2 junctions; qed");
let asset = Asset { id: AssetId(asset_location), fun: 1_000_000u128.into() };
assert!(
AssetsFrom::<SomeSiblingParachain>::contains(&asset, &SomeSiblingParachain::get()),
"AssetsFrom should allow assets from any of its interior locations"
+40 -48
View File
@@ -66,37 +66,36 @@ where
}
}
/// Accepts an asset if it is a native asset from a particular `MultiLocation`.
pub struct ConcreteNativeAssetFrom<Location>(PhantomData<Location>);
impl<Location: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation>
for ConcreteNativeAssetFrom<Location>
/// Accepts an asset if it is a native asset from a particular `Location`.
pub struct ConcreteNativeAssetFrom<LocationValue>(PhantomData<LocationValue>);
impl<LocationValue: Get<Location>> ContainsPair<Asset, Location>
for ConcreteNativeAssetFrom<LocationValue>
{
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
fn contains(asset: &Asset, origin: &Location) -> bool {
log::trace!(target: "xcm::filter_asset_location",
"ConcreteNativeAsset asset: {:?}, origin: {:?}, location: {:?}",
asset, origin, Location::get());
matches!(asset.id, Concrete(ref id) if id == origin && origin == &Location::get())
asset, origin, LocationValue::get());
asset.id.0 == *origin && origin == &LocationValue::get()
}
}
pub struct RelayOrOtherSystemParachains<
SystemParachainMatcher: Contains<MultiLocation>,
SystemParachainMatcher: Contains<Location>,
Runtime: parachain_info::Config,
> {
_runtime: PhantomData<(SystemParachainMatcher, Runtime)>,
}
impl<SystemParachainMatcher: Contains<MultiLocation>, Runtime: parachain_info::Config>
Contains<MultiLocation> for RelayOrOtherSystemParachains<SystemParachainMatcher, Runtime>
impl<SystemParachainMatcher: Contains<Location>, Runtime: parachain_info::Config> Contains<Location>
for RelayOrOtherSystemParachains<SystemParachainMatcher, Runtime>
{
fn contains(l: &MultiLocation) -> bool {
fn contains(l: &Location) -> bool {
let self_para_id: u32 = parachain_info::Pallet::<Runtime>::get().into();
if let MultiLocation { parents: 0, interior: X1(Parachain(para_id)) } = l {
if let (0, [Parachain(para_id)]) = l.unpack() {
if *para_id == self_para_id {
return false
}
}
matches!(l, MultiLocation { parents: 1, interior: Here }) ||
SystemParachainMatcher::contains(l)
matches!(l.unpack(), (1, [])) || SystemParachainMatcher::contains(l)
}
}
@@ -105,14 +104,12 @@ impl<SystemParachainMatcher: Contains<MultiLocation>, Runtime: parachain_info::C
/// This structure can only be used at a parachain level. In the Relay Chain, please use
/// the `xcm_builder::IsChildSystemParachain` matcher.
pub struct AllSiblingSystemParachains;
impl Contains<MultiLocation> for AllSiblingSystemParachains {
fn contains(l: &MultiLocation) -> bool {
impl Contains<Location> for AllSiblingSystemParachains {
fn contains(l: &Location) -> bool {
log::trace!(target: "xcm::contains", "AllSiblingSystemParachains location: {:?}", l);
match *l {
match l.unpack() {
// System parachain
MultiLocation { parents: 1, interior: X1(Parachain(id)) } =>
ParaId::from(id).is_system(),
(1, [Parachain(id)]) => ParaId::from(*id).is_system(),
// Everything else
_ => false,
}
@@ -121,21 +118,20 @@ impl Contains<MultiLocation> for AllSiblingSystemParachains {
/// Accepts an asset if it is a concrete asset from the system (Relay Chain or system parachain).
pub struct ConcreteAssetFromSystem<AssetLocation>(PhantomData<AssetLocation>);
impl<AssetLocation: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation>
impl<AssetLocation: Get<Location>> ContainsPair<Asset, Location>
for ConcreteAssetFromSystem<AssetLocation>
{
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
fn contains(asset: &Asset, origin: &Location) -> bool {
log::trace!(target: "xcm::contains", "ConcreteAssetFromSystem asset: {:?}, origin: {:?}", asset, origin);
let is_system = match origin {
let is_system = match origin.unpack() {
// The Relay Chain
MultiLocation { parents: 1, interior: Here } => true,
(1, []) => true,
// System parachain
MultiLocation { parents: 1, interior: X1(Parachain(id)) } =>
ParaId::from(*id).is_system(),
(1, [Parachain(id)]) => ParaId::from(*id).is_system(),
// Others
_ => false,
};
matches!(asset.id, Concrete(id) if id == AssetLocation::get()) && is_system
asset.id.0 == AssetLocation::get() && is_system
}
}
@@ -144,13 +140,9 @@ impl<AssetLocation: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation>
/// This type should only be used within the context of a parachain, since it does not verify that
/// the parent is indeed a Relay Chain.
pub struct ParentRelayOrSiblingParachains;
impl Contains<MultiLocation> for ParentRelayOrSiblingParachains {
fn contains(location: &MultiLocation) -> bool {
matches!(
location,
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Parachain(_)) }
)
impl Contains<Location> for ParentRelayOrSiblingParachains {
fn contains(location: &Location) -> bool {
matches!(location.unpack(), (1, []) | (1, [Parachain(_)]))
}
}
@@ -159,20 +151,20 @@ mod tests {
use frame_support::{parameter_types, traits::Contains};
use super::{
AllSiblingSystemParachains, ConcreteAssetFromSystem, ContainsPair, GeneralIndex, Here,
MultiAsset, MultiLocation, PalletInstance, Parachain, Parent,
AllSiblingSystemParachains, Asset, ConcreteAssetFromSystem, ContainsPair, GeneralIndex,
Here, Location, PalletInstance, Parachain, Parent,
};
use polkadot_primitives::LOWEST_PUBLIC_ID;
use xcm::latest::prelude::*;
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayLocation: Location = Location::parent();
}
#[test]
fn concrete_asset_from_relay_works() {
let expected_asset: MultiAsset = (Parent, 1000000).into();
let expected_origin: MultiLocation = (Parent, Here).into();
let expected_asset: Asset = (Parent, 1000000).into();
let expected_origin: Location = (Parent, Here).into();
assert!(<ConcreteAssetFromSystem<RelayLocation>>::contains(
&expected_asset,
@@ -182,12 +174,12 @@ mod tests {
#[test]
fn concrete_asset_from_sibling_system_para_fails_for_wrong_asset() {
let unexpected_assets: Vec<MultiAsset> = vec![
let unexpected_assets: Vec<Asset> = vec![
(Here, 1000000).into(),
((PalletInstance(50), GeneralIndex(1)), 1000000).into(),
((Parent, Parachain(1000), PalletInstance(50), GeneralIndex(1)), 1000000).into(),
];
let expected_origin: MultiLocation = (Parent, Parachain(1000)).into();
let expected_origin: Location = (Parent, Parachain(1000)).into();
unexpected_assets.iter().for_each(|asset| {
assert!(!<ConcreteAssetFromSystem<RelayLocation>>::contains(asset, &expected_origin));
@@ -206,10 +198,10 @@ mod tests {
(2001, false), // Not a System Parachain
];
let expected_asset: MultiAsset = (Parent, 1000000).into();
let expected_asset: Asset = (Parent, 1000000).into();
for (para_id, expected_result) in test_data {
let origin: MultiLocation = (Parent, Parachain(para_id)).into();
let origin: Location = (Parent, Parachain(para_id)).into();
assert_eq!(
expected_result,
<ConcreteAssetFromSystem<RelayLocation>>::contains(&expected_asset, &origin)
@@ -220,15 +212,15 @@ mod tests {
#[test]
fn all_sibling_system_parachains_works() {
// system parachain
assert!(AllSiblingSystemParachains::contains(&MultiLocation::new(1, X1(Parachain(1)))));
assert!(AllSiblingSystemParachains::contains(&Location::new(1, [Parachain(1)])));
// non-system parachain
assert!(!AllSiblingSystemParachains::contains(&MultiLocation::new(
assert!(!AllSiblingSystemParachains::contains(&Location::new(
1,
X1(Parachain(LOWEST_PUBLIC_ID.into()))
[Parachain(LOWEST_PUBLIC_ID.into())]
)));
// when used at relay chain
assert!(!AllSiblingSystemParachains::contains(&MultiLocation::new(0, X1(Parachain(1)))));
assert!(!AllSiblingSystemParachains::contains(&Location::new(0, [Parachain(1)])));
// when used with non-parachain
assert!(!AllSiblingSystemParachains::contains(&MultiLocation::new(1, X1(OnlyChild))));
assert!(!AllSiblingSystemParachains::contains(&Location::new(1, [OnlyChild])));
}
}