mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 16:51:02 +00:00
XCMv4 (#1230)
# 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:
committed by
GitHub
parent
ec7bfae00a
commit
8428f678fe
@@ -38,8 +38,9 @@ pub use polkadot_runtime_parachains::{
|
||||
inclusion::{AggregateMessageOrigin, UmpQueueId},
|
||||
};
|
||||
pub use xcm::{
|
||||
prelude::{MultiLocation, OriginKind, Outcome, VersionedXcm, XcmVersion},
|
||||
v3::Error,
|
||||
prelude::{Location, OriginKind, Outcome, VersionedXcm, XcmVersion},
|
||||
v3,
|
||||
v4::Error as XcmError,
|
||||
DoubleEncoded,
|
||||
};
|
||||
|
||||
@@ -209,7 +210,7 @@ macro_rules! impl_assert_events_helpers_for_relay_chain {
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::XcmPallet(
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete(weight) }
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete { used: weight } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
@@ -224,21 +225,21 @@ macro_rules! impl_assert_events_helpers_for_relay_chain {
|
||||
/// Asserts a dispatchable is incompletely executed and XCM sent
|
||||
pub fn assert_xcm_pallet_attempted_incomplete(
|
||||
expected_weight: Option<$crate::impls::Weight>,
|
||||
expected_error: Option<$crate::impls::Error>,
|
||||
expected_error: Option<$crate::impls::XcmError>,
|
||||
) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
// Dispatchable is properly executed and XCM message sent
|
||||
[<$chain RuntimeEvent>]::<N>::XcmPallet(
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete(weight, error) }
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
error: *error == expected_error.unwrap_or(*error),
|
||||
error: *error == expected_error.unwrap_or((*error).into()).into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
@@ -365,7 +366,7 @@ macro_rules! impl_send_transact_helpers_for_relay_chain {
|
||||
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
let root_origin = <Self as Chain>::RuntimeOrigin::root();
|
||||
let destination: $crate::impls::MultiLocation = <Self as RelayChain>::child_location_of(recipient);
|
||||
let destination: $crate::impls::Location = <Self as RelayChain>::child_location_of(recipient);
|
||||
let xcm = $crate::impls::xcm_transact_unpaid_execution(call, $crate::impls::OriginKind::Superuser);
|
||||
|
||||
// Send XCM `Transact`
|
||||
@@ -416,13 +417,13 @@ macro_rules! impl_accounts_helpers_for_parachain {
|
||||
network_id: $crate::impls::NetworkId,
|
||||
para_id: $crate::impls::ParaId,
|
||||
) -> $crate::impls::AccountId {
|
||||
let remote_location = $crate::impls::MultiLocation {
|
||||
parents: 2,
|
||||
interior: $crate::impls::Junctions::X2(
|
||||
let remote_location = $crate::impls::Location::new(
|
||||
2,
|
||||
[
|
||||
$crate::impls::Junction::GlobalConsensus(network_id),
|
||||
$crate::impls::Junction::Parachain(para_id.into()),
|
||||
),
|
||||
};
|
||||
],
|
||||
);
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
Self::sovereign_account_id_of(remote_location)
|
||||
})
|
||||
@@ -445,7 +446,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
Self,
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::PolkadotXcm(
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete(weight) }
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete { used: weight } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
@@ -460,36 +461,36 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
/// Asserts a dispatchable is incompletely executed and XCM sent
|
||||
pub fn assert_xcm_pallet_attempted_incomplete(
|
||||
expected_weight: Option<$crate::impls::Weight>,
|
||||
expected_error: Option<$crate::impls::Error>,
|
||||
expected_error: Option<$crate::impls::XcmError>,
|
||||
) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
// Dispatchable is properly executed and XCM message sent
|
||||
[<$chain RuntimeEvent>]::<N>::PolkadotXcm(
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete(weight, error) }
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete { used: weight, error } }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
),
|
||||
error: *error == expected_error.unwrap_or(*error),
|
||||
error: *error == expected_error.unwrap_or((*error).into()).into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts a dispatchable throws and error when trying to be sent
|
||||
pub fn assert_xcm_pallet_attempted_error(expected_error: Option<$crate::impls::Error>) {
|
||||
pub fn assert_xcm_pallet_attempted_error(expected_error: Option<$crate::impls::XcmError>) {
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
vec![
|
||||
// Execution fails in the origin with `Barrier`
|
||||
[<$chain RuntimeEvent>]::<N>::PolkadotXcm(
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Error(error) }
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Error { error } }
|
||||
) => {
|
||||
error: *error == expected_error.unwrap_or(*error),
|
||||
error: *error == expected_error.unwrap_or((*error).into()).into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
@@ -639,7 +640,7 @@ macro_rules! impl_assets_helpers_for_parachain {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::Assets::mint(
|
||||
signed_origin,
|
||||
id.into(),
|
||||
id.clone().into(),
|
||||
beneficiary.clone().into(),
|
||||
amount_to_mint
|
||||
));
|
||||
@@ -717,7 +718,7 @@ macro_rules! impl_assets_helpers_for_parachain {
|
||||
]
|
||||
);
|
||||
|
||||
assert!(<Self as [<$chain ParaPallet>]>::Assets::asset_exists(id.into()));
|
||||
assert!(<Self as [<$chain ParaPallet>]>::Assets::asset_exists(id.clone().into()));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -732,7 +733,7 @@ macro_rules! impl_foreign_assets_helpers_for_parachain {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Create foreign assets using sudo `ForeignAssets::force_create()`
|
||||
pub fn force_create_foreign_asset(
|
||||
id: $crate::impls::MultiLocation,
|
||||
id: $crate::impls::v3::Location,
|
||||
owner: $crate::impls::AccountId,
|
||||
is_sufficient: bool,
|
||||
min_balance: u128,
|
||||
@@ -744,13 +745,13 @@ macro_rules! impl_foreign_assets_helpers_for_parachain {
|
||||
$crate::impls::assert_ok!(
|
||||
<Self as [<$chain ParaPallet>]>::ForeignAssets::force_create(
|
||||
sudo_origin,
|
||||
id,
|
||||
id.clone(),
|
||||
owner.clone().into(),
|
||||
is_sufficient,
|
||||
min_balance,
|
||||
)
|
||||
);
|
||||
assert!(<Self as [<$chain ParaPallet>]>::ForeignAssets::asset_exists(id));
|
||||
assert!(<Self as [<$chain ParaPallet>]>::ForeignAssets::asset_exists(id.clone()));
|
||||
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
|
||||
$crate::impls::assert_expected_events!(
|
||||
Self,
|
||||
@@ -767,21 +768,21 @@ macro_rules! impl_foreign_assets_helpers_for_parachain {
|
||||
for (beneficiary, amount) in prefund_accounts.into_iter() {
|
||||
let signed_origin =
|
||||
<$chain<N> as $crate::impls::Chain>::RuntimeOrigin::signed(owner.clone());
|
||||
Self::mint_foreign_asset(signed_origin, id, beneficiary, amount);
|
||||
Self::mint_foreign_asset(signed_origin, id.clone(), beneficiary, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/// Mint assets making use of the ForeignAssets pallet-assets instance
|
||||
pub fn mint_foreign_asset(
|
||||
signed_origin: <Self as $crate::impls::Chain>::RuntimeOrigin,
|
||||
id: $crate::impls::MultiLocation,
|
||||
id: $crate::impls::v3::Location,
|
||||
beneficiary: $crate::impls::AccountId,
|
||||
amount_to_mint: u128,
|
||||
) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::ForeignAssets::mint(
|
||||
signed_origin,
|
||||
id.into(),
|
||||
id.clone().into(),
|
||||
beneficiary.clone().into(),
|
||||
amount_to_mint
|
||||
));
|
||||
@@ -813,7 +814,7 @@ macro_rules! impl_xcm_helpers_for_parachain {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
/// Set XCM version for destination.
|
||||
pub fn force_xcm_version(dest: $crate::impls::MultiLocation, version: $crate::impls::XcmVersion) {
|
||||
pub fn force_xcm_version(dest: $crate::impls::Location, version: $crate::impls::XcmVersion) {
|
||||
<Self as $crate::impls::TestExt>::execute_with(|| {
|
||||
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::PolkadotXcm::force_xcm_version(
|
||||
<Self as $crate::impls::Chain>::RuntimeOrigin::root(),
|
||||
|
||||
@@ -40,6 +40,7 @@ use polkadot_service::chain_spec::get_authority_keys_from_seed_no_beefy;
|
||||
|
||||
pub const XCM_V2: u32 = 2;
|
||||
pub const XCM_V3: u32 = 3;
|
||||
pub const XCM_V4: u32 = 4;
|
||||
pub const REF_TIME_THRESHOLD: u64 = 33;
|
||||
pub const PROOF_SIZE_THRESHOLD: u64 = 33;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ macro_rules! test_parachain_is_trusted_teleporter {
|
||||
<$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free;
|
||||
let para_destination =
|
||||
<$sender_para>::sibling_location_of(<$receiver_para>::para_id());
|
||||
let beneficiary: MultiLocation =
|
||||
let beneficiary: Location =
|
||||
$crate::macros::AccountId32 { network: None, id: receiver.clone().into() }.into();
|
||||
|
||||
// Send XCM message from Origin Parachain
|
||||
@@ -57,8 +57,8 @@ macro_rules! test_parachain_is_trusted_teleporter {
|
||||
<$sender_para>::execute_with(|| {
|
||||
assert_ok!(<$sender_para as [<$sender_para Pallet>]>::PolkadotXcm::limited_teleport_assets(
|
||||
origin.clone(),
|
||||
bx!(para_destination.into()),
|
||||
bx!(beneficiary.into()),
|
||||
bx!(para_destination.clone().into()),
|
||||
bx!(beneficiary.clone().into()),
|
||||
bx!($assets.clone().into()),
|
||||
fee_asset_item,
|
||||
weight_limit.clone(),
|
||||
@@ -127,8 +127,8 @@ macro_rules! include_penpal_create_foreign_asset_on_asset_hub {
|
||||
$crate::impls::paste::paste! {
|
||||
pub fn penpal_create_foreign_asset_on_asset_hub(
|
||||
asset_id_on_penpal: u32,
|
||||
foreign_asset_at_asset_hub: MultiLocation,
|
||||
ah_as_seen_by_penpal: MultiLocation,
|
||||
foreign_asset_at_asset_hub: v3::Location,
|
||||
ah_as_seen_by_penpal: Location,
|
||||
is_sufficient: bool,
|
||||
asset_owner: AccountId,
|
||||
prefund_amount: u128,
|
||||
@@ -144,14 +144,14 @@ macro_rules! include_penpal_create_foreign_asset_on_asset_hub {
|
||||
// prefund SA of Penpal on AssetHub with enough native tokens to pay for creating
|
||||
// new foreign asset, also prefund CheckingAccount with ED, because teleported asset
|
||||
// itself might not be sufficient and CheckingAccount cannot be created otherwise
|
||||
let sov_penpal_on_ah = $asset_hub::sovereign_account_id_of(penpal_as_seen_by_ah);
|
||||
let sov_penpal_on_ah = $asset_hub::sovereign_account_id_of(penpal_as_seen_by_ah.clone());
|
||||
$asset_hub::fund_accounts(vec![
|
||||
(sov_penpal_on_ah.clone().into(), $relay_ed * 100_000_000_000),
|
||||
(ah_check_account.clone().into(), $relay_ed * 1000),
|
||||
]);
|
||||
|
||||
// prefund SA of AssetHub on Penpal with native asset
|
||||
let sov_ah_on_penpal = $penpal::sovereign_account_id_of(ah_as_seen_by_penpal);
|
||||
let sov_ah_on_penpal = $penpal::sovereign_account_id_of(ah_as_seen_by_penpal.clone());
|
||||
$penpal::fund_accounts(vec![
|
||||
(sov_ah_on_penpal.into(), $relay_ed * 1_000_000_000),
|
||||
(penpal_check_account.clone().into(), $relay_ed * 1000),
|
||||
@@ -183,8 +183,8 @@ macro_rules! include_penpal_create_foreign_asset_on_asset_hub {
|
||||
let buy_execution_fee_amount = $weight_to_fee::weight_to_fee(
|
||||
&Weight::from_parts(10_100_000_000_000, 300_000),
|
||||
);
|
||||
let buy_execution_fee = MultiAsset {
|
||||
id: Concrete(MultiLocation { parents: 1, interior: Here }),
|
||||
let buy_execution_fee = Asset {
|
||||
id: AssetId(Location { parents: 1, interior: Here }),
|
||||
fun: Fungible(buy_execution_fee_amount),
|
||||
};
|
||||
let xcm = VersionedXcm::from(Xcm(vec![
|
||||
|
||||
@@ -23,12 +23,12 @@ use xcm::{prelude::*, DoubleEncoded};
|
||||
pub fn xcm_transact_paid_execution(
|
||||
call: DoubleEncoded<()>,
|
||||
origin_kind: OriginKind,
|
||||
native_asset: MultiAsset,
|
||||
native_asset: Asset,
|
||||
beneficiary: AccountId,
|
||||
) -> VersionedXcm<()> {
|
||||
let weight_limit = WeightLimit::Unlimited;
|
||||
let require_weight_at_most = Weight::from_parts(1000000000, 200000);
|
||||
let native_assets: MultiAssets = native_asset.clone().into();
|
||||
let native_assets: Assets = native_asset.clone().into();
|
||||
|
||||
VersionedXcm::from(Xcm(vec![
|
||||
WithdrawAsset(native_assets),
|
||||
@@ -37,9 +37,9 @@ pub fn xcm_transact_paid_execution(
|
||||
RefundSurplus,
|
||||
DepositAsset {
|
||||
assets: All.into(),
|
||||
beneficiary: MultiLocation {
|
||||
beneficiary: Location {
|
||||
parents: 0,
|
||||
interior: X1(AccountId32 { network: None, id: beneficiary.into() }),
|
||||
interior: [AccountId32 { network: None, id: beneficiary.into() }].into(),
|
||||
},
|
||||
},
|
||||
]))
|
||||
@@ -61,15 +61,11 @@ pub fn xcm_transact_unpaid_execution(
|
||||
}
|
||||
|
||||
/// Helper method to get the non-fee asset used in multiple assets transfer
|
||||
pub fn non_fee_asset(assets: &MultiAssets, fee_idx: usize) -> Option<(MultiLocation, u128)> {
|
||||
pub fn non_fee_asset(assets: &Assets, fee_idx: usize) -> Option<(Location, u128)> {
|
||||
let asset = assets.inner().into_iter().enumerate().find(|a| a.0 != fee_idx)?.1.clone();
|
||||
let asset_id = match asset.id {
|
||||
Concrete(id) => id,
|
||||
_ => return None,
|
||||
};
|
||||
let asset_amount = match asset.fun {
|
||||
Fungible(amount) => amount,
|
||||
_ => return None,
|
||||
};
|
||||
Some((asset_id, asset_amount))
|
||||
Some((asset.id.0, asset_amount))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user