# 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
@@ -21,12 +21,16 @@ use asset_hub_westend_runtime::{
xcm_config,
xcm_config::{
bridging, ForeignCreatorsSovereignAccountOf, LocationToAccountId, WestendLocation,
WestendLocationV3,
},
AllPalletsWithoutSystem, MetadataDepositBase, MetadataDepositPerByte, PolkadotXcm, RuntimeCall,
RuntimeEvent, RuntimeOrigin, ToRococoXcmRouterInstance, XcmpQueue,
};
pub use asset_hub_westend_runtime::{
xcm_config::{CheckingAccount, TrustBackedAssetsPalletLocation, XcmConfig},
xcm_config::{
CheckingAccount, TrustBackedAssetsPalletLocation, TrustBackedAssetsPalletLocationV3,
XcmConfig,
},
AssetConversion, AssetDeposit, Assets, Balances, CollatorSelection, ExistentialDeposit,
ForeignAssets, ForeignAssetsInstance, ParachainSystem, Runtime, SessionKeys, System,
TrustBackedAssetsInstance,
@@ -51,14 +55,18 @@ use parachains_common::{
};
use sp_runtime::traits::MaybeEquivalence;
use std::convert::Into;
use xcm::latest::prelude::*;
use xcm_executor::traits::{Identity, JustTry, WeightTrader};
use xcm::latest::prelude::{Assets as XcmAssets, *};
use xcm_builder::V4V3LocationConverter;
use xcm_executor::traits::{JustTry, WeightTrader};
const ALICE: [u8; 32] = [1u8; 32];
const SOME_ASSET_ADMIN: [u8; 32] = [5u8; 32];
type AssetIdForTrustBackedAssetsConvert =
assets_common::AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation>;
assets_common::AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocationV3>;
type AssetIdForTrustBackedAssetsConvertLatest =
assets_common::AssetIdForTrustBackedAssetsConvertLatest<TrustBackedAssetsPalletLocation>;
type RuntimeHelper = asset_test_utils::RuntimeHelper<Runtime, AllPalletsWithoutSystem>;
@@ -101,7 +109,7 @@ fn test_buy_and_refund_weight_in_native() {
let fee = WeightToFee::weight_to_fee(&weight);
let extra_amount = 100;
let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None };
let payment: MultiAsset = (native_location, fee + extra_amount).into();
let payment: Asset = (native_location.clone(), fee + extra_amount).into();
// init trader and buy weight.
let mut trader = <XcmConfig as xcm_executor::Config>::Trader::new();
@@ -110,7 +118,7 @@ fn test_buy_and_refund_weight_in_native() {
// assert.
let unused_amount =
unused_asset.fungible.get(&native_location.into()).map_or(0, |a| *a);
unused_asset.fungible.get(&native_location.clone().into()).map_or(0, |a| *a);
assert_eq!(unused_amount, extra_amount);
assert_eq!(Balances::total_issuance(), total_issuance);
@@ -146,7 +154,7 @@ fn test_buy_and_refund_weight_with_swap_local_asset_xcm_trader() {
let bob: AccountId = SOME_ASSET_ADMIN.into();
let staking_pot = CollatorSelection::account_id();
let asset_1: u32 = 1;
let native_location = WestendLocation::get();
let native_location = WestendLocationV3::get();
let asset_1_location =
AssetIdForTrustBackedAssetsConvert::convert_back(&asset_1).unwrap();
// bob's initial balance for native and `asset1` assets.
@@ -182,6 +190,8 @@ fn test_buy_and_refund_weight_with_swap_local_asset_xcm_trader() {
let asset_total_issuance = Assets::total_issuance(asset_1);
let native_total_issuance = Balances::total_issuance();
let asset_1_location_latest: Location = asset_1_location.try_into().unwrap();
// prepare input to buy weight.
let weight = Weight::from_parts(4_000_000_000, 0);
let fee = WeightToFee::weight_to_fee(&weight);
@@ -189,7 +199,7 @@ fn test_buy_and_refund_weight_with_swap_local_asset_xcm_trader() {
AssetConversion::get_amount_in(&fee, &pool_liquidity, &pool_liquidity).unwrap();
let extra_amount = 100;
let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None };
let payment: MultiAsset = (asset_1_location, asset_fee + extra_amount).into();
let payment: Asset = (asset_1_location_latest.clone(), asset_fee + extra_amount).into();
// init trader and buy weight.
let mut trader = <XcmConfig as xcm_executor::Config>::Trader::new();
@@ -197,8 +207,10 @@ fn test_buy_and_refund_weight_with_swap_local_asset_xcm_trader() {
trader.buy_weight(weight, payment.into(), &ctx).expect("Expected Ok");
// assert.
let unused_amount =
unused_asset.fungible.get(&asset_1_location.into()).map_or(0, |a| *a);
let unused_amount = unused_asset
.fungible
.get(&asset_1_location_latest.clone().into())
.map_or(0, |a| *a);
assert_eq!(unused_amount, extra_amount);
assert_eq!(Assets::total_issuance(asset_1), asset_total_issuance + asset_fee);
@@ -212,7 +224,7 @@ fn test_buy_and_refund_weight_with_swap_local_asset_xcm_trader() {
// refund.
let actual_refund = trader.refund_weight(refund_weight, &ctx).unwrap();
assert_eq!(actual_refund, (asset_1_location, asset_refund).into());
assert_eq!(actual_refund, (asset_1_location_latest, asset_refund).into());
// assert.
assert_eq!(Balances::balance(&staking_pot), initial_balance);
@@ -241,9 +253,15 @@ fn test_buy_and_refund_weight_with_swap_foreign_asset_xcm_trader() {
.execute_with(|| {
let bob: AccountId = SOME_ASSET_ADMIN.into();
let staking_pot = CollatorSelection::account_id();
let native_location = WestendLocation::get();
let foreign_location =
MultiLocation { parents: 1, interior: X2(Parachain(1234), GeneralIndex(12345)) };
let native_location = WestendLocationV3::get();
let foreign_location = xcm::v3::Location {
parents: 1,
interior: (
xcm::v3::Junction::Parachain(1234),
xcm::v3::Junction::GeneralIndex(12345),
)
.into(),
};
// bob's initial balance for native and `asset1` assets.
let initial_balance = 200 * UNITS;
// liquidity for both arms of (native, asset1) pool.
@@ -282,6 +300,8 @@ fn test_buy_and_refund_weight_with_swap_foreign_asset_xcm_trader() {
let asset_total_issuance = ForeignAssets::total_issuance(foreign_location);
let native_total_issuance = Balances::total_issuance();
let foreign_location_latest: Location = foreign_location.try_into().unwrap();
// prepare input to buy weight.
let weight = Weight::from_parts(4_000_000_000, 0);
let fee = WeightToFee::weight_to_fee(&weight);
@@ -289,7 +309,7 @@ fn test_buy_and_refund_weight_with_swap_foreign_asset_xcm_trader() {
AssetConversion::get_amount_in(&fee, &pool_liquidity, &pool_liquidity).unwrap();
let extra_amount = 100;
let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None };
let payment: MultiAsset = (foreign_location, asset_fee + extra_amount).into();
let payment: Asset = (foreign_location_latest.clone(), asset_fee + extra_amount).into();
// init trader and buy weight.
let mut trader = <XcmConfig as xcm_executor::Config>::Trader::new();
@@ -297,8 +317,10 @@ fn test_buy_and_refund_weight_with_swap_foreign_asset_xcm_trader() {
trader.buy_weight(weight, payment.into(), &ctx).expect("Expected Ok");
// assert.
let unused_amount =
unused_asset.fungible.get(&foreign_location.into()).map_or(0, |a| *a);
let unused_amount = unused_asset
.fungible
.get(&foreign_location_latest.clone().into())
.map_or(0, |a| *a);
assert_eq!(unused_amount, extra_amount);
assert_eq!(
ForeignAssets::total_issuance(foreign_location),
@@ -315,7 +337,7 @@ fn test_buy_and_refund_weight_with_swap_foreign_asset_xcm_trader() {
// refund.
let actual_refund = trader.refund_weight(refund_weight, &ctx).unwrap();
assert_eq!(actual_refund, (foreign_location, asset_refund).into());
assert_eq!(actual_refund, (foreign_location_latest, asset_refund).into());
// assert.
assert_eq!(Balances::balance(&staking_pot), initial_balance);
@@ -345,19 +367,25 @@ fn test_assets_balances_api_works() {
.build()
.execute_with(|| {
let local_asset_id = 1;
let foreign_asset_id_multilocation =
MultiLocation { parents: 1, interior: X2(Parachain(1234), GeneralIndex(12345)) };
let foreign_asset_id_location = xcm::v3::Location {
parents: 1,
interior: [
xcm::v3::Junction::Parachain(1234),
xcm::v3::Junction::GeneralIndex(12345),
]
.into(),
};
// check before
assert_eq!(Assets::balance(local_asset_id, AccountId::from(ALICE)), 0);
assert_eq!(
ForeignAssets::balance(foreign_asset_id_multilocation, AccountId::from(ALICE)),
ForeignAssets::balance(foreign_asset_id_location, AccountId::from(ALICE)),
0
);
assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 0);
assert!(Runtime::query_account_balances(AccountId::from(ALICE))
.unwrap()
.try_as::<MultiAssets>()
.try_as::<XcmAssets>()
.unwrap()
.is_none());
@@ -388,7 +416,7 @@ fn test_assets_balances_api_works() {
let foreign_asset_minimum_asset_balance = 3333333_u128;
assert_ok!(ForeignAssets::force_create(
RuntimeHelper::root_origin(),
foreign_asset_id_multilocation,
foreign_asset_id_location,
AccountId::from(SOME_ASSET_ADMIN).into(),
false,
foreign_asset_minimum_asset_balance
@@ -397,7 +425,7 @@ fn test_assets_balances_api_works() {
// We first mint enough asset for the account to exist for assets
assert_ok!(ForeignAssets::mint(
RuntimeHelper::origin_of(AccountId::from(SOME_ASSET_ADMIN)),
foreign_asset_id_multilocation,
foreign_asset_id_location,
AccountId::from(ALICE).into(),
6 * foreign_asset_minimum_asset_balance
));
@@ -408,12 +436,12 @@ fn test_assets_balances_api_works() {
minimum_asset_balance
);
assert_eq!(
ForeignAssets::balance(foreign_asset_id_multilocation, AccountId::from(ALICE)),
ForeignAssets::balance(foreign_asset_id_location, AccountId::from(ALICE)),
6 * minimum_asset_balance
);
assert_eq!(Balances::free_balance(AccountId::from(ALICE)), some_currency);
let result: MultiAssets = Runtime::query_account_balances(AccountId::from(ALICE))
let result: XcmAssets = Runtime::query_account_balances(AccountId::from(ALICE))
.unwrap()
.try_into()
.unwrap();
@@ -428,13 +456,13 @@ fn test_assets_balances_api_works() {
)));
// check trusted asset
assert!(result.inner().iter().any(|asset| asset.eq(&(
AssetIdForTrustBackedAssetsConvert::convert_back(&local_asset_id).unwrap(),
AssetIdForTrustBackedAssetsConvertLatest::convert_back(&local_asset_id).unwrap(),
minimum_asset_balance
)
.into())));
// check foreign asset
assert!(result.inner().iter().any(|asset| asset.eq(&(
Identity::convert_back(&foreign_asset_id_multilocation).unwrap(),
V4V3LocationConverter::convert_back(&foreign_asset_id_location).unwrap(),
6 * foreign_asset_minimum_asset_balance
)
.into())));
@@ -505,7 +533,7 @@ asset_test_utils::include_asset_transactor_transfer_with_pallet_assets_instance_
XcmConfig,
TrustBackedAssetsInstance,
AssetIdForTrustBackedAssets,
AssetIdForTrustBackedAssetsConvert,
AssetIdForTrustBackedAssetsConvertLatest,
collator_session_keys(),
ExistentialDeposit::get(),
12345,
@@ -522,11 +550,15 @@ asset_test_utils::include_asset_transactor_transfer_with_pallet_assets_instance_
Runtime,
XcmConfig,
ForeignAssetsInstance,
MultiLocation,
xcm::v3::Location,
JustTry,
collator_session_keys(),
ExistentialDeposit::get(),
MultiLocation { parents: 1, interior: X2(Parachain(1313), GeneralIndex(12345)) },
xcm::v3::Location {
parents: 1,
interior: [xcm::v3::Junction::Parachain(1313), xcm::v3::Junction::GeneralIndex(12345)]
.into()
},
Box::new(|| {
assert!(Assets::asset_ids().collect::<Vec<_>>().is_empty());
}),
@@ -541,8 +573,8 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p
WeightToFee,
ForeignCreatorsSovereignAccountOf,
ForeignAssetsInstance,
MultiLocation,
JustTry,
xcm::v3::Location,
V4V3LocationConverter,
collator_session_keys(),
ExistentialDeposit::get(),
AssetDeposit::get(),
@@ -626,12 +658,12 @@ fn receive_reserve_asset_deposited_roc_from_asset_hub_rococo_works() {
AccountId::from([73; 32]),
AccountId::from(BLOCK_AUTHOR_ACCOUNT),
// receiving ROCs
(MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }, 1000000000000, 1_000_000_000),
(xcm::v3::Location::new(2, [xcm::v3::Junction::GlobalConsensus(xcm::v3::NetworkId::Rococo)]), 1000000000000, 1_000_000_000),
bridging_to_asset_hub_rococo,
(
X1(PalletInstance(bp_bridge_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX)),
[PalletInstance(bp_bridge_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX)].into(),
GlobalConsensus(Rococo),
X1(Parachain(1000))
[Parachain(1000)].into()
)
)
}