Replicate e2e integration test as emulated (#2958)

* Allow functions to work over both parachains and relay chains

* additional references

* import

* backup

* refactoring para and relay traits

* use runtime crates to build types

* decouple ProcessMessage

* decouple ProcessMessage 2

* dmp and xcmp handlers decouple

* backup

* refactor done

* common int values working

* added global ext with mutex

* works for two mutex

* single mutex and remove condvar

* global test ext done

* failing moving test_ext because relay block num

* relay_block_number issue fixed

* backup

* Test working with assertions

* assertions get Test as arg

* DispatchArgs as generic

* clean up

* backup

* teleports for asset-hub-kusama done

* improve assert_expected_events macro

* rename Test generics

* check assertions for tuples

* test assertions redone

* reserve_transfer_assets done

* send transact done

* hrmp test for paras

* hrmp channels test done

* hrmp channels test done 2

* before modifying test dispatch

* reserve tests done & Test dispatch fixed

* reserve transfer local asset

* force_create_and_mint_asset

* force create and mint done

* tests done

* fix imports in common

* common events refactored

* add option to events attributes

* asset-hub-polkadot tests done

* asset-hub-westend half done

* relay chain events move to common

* remove failing send tests for asset-hub-westend

* added events to bridge-hub-rococo

* added events to collectives-polkadot

* cargo clean up

* fix asset-hub-westend tests

* ".git/.scripts/commands/fmt/fmt.sh"

* fix clippy

* ".git/.scripts/commands/fmt/fmt.sh"

* Removed unnecessary deps

* Extracted some commonality for Kusama/Polkadot (which will be reused also for BridgeHubs) (#2971)

* Extracted some commonality for Kusama/Polkadot (which will be reused also for BridgeHubs)

* AssetHubRococo should better use AssetHubKusama runtime

* add fund_account

---------

Co-authored-by: NachoPal <ignacio.palacios.santos@gmail.com>

* address comments

* rename event assertion helpers

* clean comments

* address comments 2

* ".git/.scripts/commands/fmt/fmt.sh"

---------

Co-authored-by: Giles Cope <gilescope@gmail.com>
Co-authored-by: command-bot <>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
This commit is contained in:
Ignacio Palacios
2023-08-10 19:38:18 +02:00
committed by GitHub
parent e077bdd99f
commit eadfbca388
40 changed files with 5344 additions and 1300 deletions
+20 -18
View File
@@ -447,7 +447,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
name = "asset-hub-kusama-integration-tests"
version = "1.0.0"
dependencies = [
"asset-hub-kusama-runtime",
"cumulus-pallet-dmp-queue",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"frame-support",
"frame-system",
"integration-tests-common",
@@ -456,7 +458,6 @@ dependencies = [
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"penpal-runtime",
"polkadot-core-primitives",
"polkadot-parachain",
"polkadot-runtime",
@@ -544,7 +545,9 @@ dependencies = [
name = "asset-hub-polkadot-integration-tests"
version = "1.0.0"
dependencies = [
"asset-hub-polkadot-runtime",
"cumulus-pallet-dmp-queue",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"frame-support",
"frame-system",
"integration-tests-common",
@@ -553,7 +556,6 @@ dependencies = [
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"penpal-runtime",
"polkadot-core-primitives",
"polkadot-parachain",
"polkadot-runtime",
@@ -641,6 +643,9 @@ version = "1.0.0"
dependencies = [
"assert_matches",
"asset-hub-westend-runtime",
"cumulus-pallet-dmp-queue",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"frame-support",
"frame-system",
"integration-tests-common",
@@ -650,7 +655,6 @@ dependencies = [
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"penpal-runtime",
"polkadot-core-primitives",
"polkadot-parachain",
"polkadot-runtime",
@@ -658,7 +662,6 @@ dependencies = [
"sp-core",
"sp-runtime",
"sp-weights",
"westend-runtime",
"xcm",
"xcm-emulator",
"xcm-executor",
@@ -1445,7 +1448,7 @@ name = "bridge-hub-rococo-integration-tests"
version = "1.0.0"
dependencies = [
"bp-messages",
"bridge-hub-rococo-runtime",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"frame-support",
"frame-system",
@@ -1759,15 +1762,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "casey"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614586263949597dcc18675da12ef9b429135e13628d92eb8b8c6fa50ca5656b"
dependencies = [
"syn 1.0.109",
]
[[package]]
name = "cast"
version = "0.3.0"
@@ -1999,6 +1993,7 @@ version = "0.1.0"
dependencies = [
"asset-hub-polkadot-runtime",
"collectives-polkadot-runtime",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"frame-support",
"frame-system",
@@ -5263,20 +5258,26 @@ dependencies = [
"bridge-hub-rococo-runtime",
"bridge-runtime-common",
"collectives-polkadot-runtime",
"cumulus-pallet-dmp-queue",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"cumulus-primitives-core",
"frame-support",
"frame-system",
"kusama-runtime",
"kusama-runtime-constants",
"lazy_static",
"pallet-assets",
"pallet-balances",
"pallet-bridge-messages",
"pallet-im-online",
"pallet-message-queue",
"pallet-staking",
"pallet-xcm",
"parachain-info",
"parachains-common",
"parity-scale-codec",
"paste",
"penpal-runtime",
"polkadot-core-primitives",
"polkadot-parachain",
@@ -15908,7 +15909,6 @@ dependencies = [
name = "xcm-emulator"
version = "0.1.0"
dependencies = [
"casey",
"cumulus-pallet-dmp-queue",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
@@ -15917,6 +15917,8 @@ dependencies = [
"cumulus-test-relay-sproof-builder",
"frame-support",
"frame-system",
"impl-trait-for-tuples",
"lazy_static",
"log",
"pallet-balances",
"pallet-message-queue",
@@ -15926,7 +15928,6 @@ dependencies = [
"paste",
"polkadot-primitives",
"polkadot-runtime-parachains",
"quote",
"sp-arithmetic",
"sp-core",
"sp-io",
@@ -15934,6 +15935,7 @@ dependencies = [
"sp-std",
"sp-trie",
"xcm",
"xcm-executor",
]
[[package]]
@@ -28,8 +28,9 @@ pallet-xcm = { default-features = false, git = "https://github.com/paritytech/po
# Cumulus
parachains-common = { path = "../../../../common" }
penpal-runtime = { path = "../../../../runtimes/testing/penpal" }
asset-hub-kusama-runtime = { path = "../../../../runtimes/assets/asset-hub-kusama" }
cumulus-pallet-dmp-queue = { path = "../../../../../pallets/dmp-queue" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../pallets/xcmp-queue" }
cumulus-pallet-parachain-system = { path = "../../../../../pallets/parachain-system" }
# Local
xcm-emulator = { default-features = false, path = "../../../../../xcm/xcm-emulator" }
@@ -16,31 +16,89 @@
pub use codec::Encode;
pub use frame_support::{
assert_ok, instances::Instance1, pallet_prelude::Weight, traits::fungibles::Inspect,
assert_err, assert_ok,
instances::Instance1,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult, MultiAddress},
traits::{fungibles::Inspect, OriginTrait},
};
pub use integration_tests_common::{
constants::{
accounts::{ALICE, BOB},
asset_hub_kusama::ED as ASSET_HUB_KUSAMA_ED,
kusama::ED as KUSAMA_ED,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
},
AccountId, AssetHubKusama, AssetHubKusamaPallet, AssetHubKusamaReceiver, AssetHubKusamaSender,
BridgeHubKusama, BridgeHubKusamaPallet, BridgeHubKusamaReceiver, BridgeHubKusamaSender,
BridgeHubPolkadot, BridgeHubPolkadotPallet, BridgeHubPolkadotReceiver, BridgeHubPolkadotSender,
Collectives, CollectivesPallet, CollectivesReceiver, CollectivesSender, Kusama, KusamaMockNet,
KusamaPallet, KusamaReceiver, KusamaSender, PenpalKusama, PenpalKusamaReceiver,
PenpalKusamaSender, PenpalPolkadot, PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot,
lazy_static::lazy_static,
xcm_transact_paid_execution, xcm_transact_unpaid_execution, AssetHubKusama,
AssetHubKusamaPallet, AssetHubKusamaReceiver, AssetHubKusamaSender, BridgeHubKusama,
BridgeHubKusamaPallet, BridgeHubKusamaReceiver, BridgeHubKusamaSender, BridgeHubPolkadot,
BridgeHubPolkadotPallet, BridgeHubPolkadotReceiver, BridgeHubPolkadotSender, Collectives,
CollectivesPallet, CollectivesReceiver, CollectivesSender, Kusama, KusamaMockNet, KusamaPallet,
KusamaReceiver, KusamaSender, PenpalKusamaA, PenpalKusamaAPallet, PenpalKusamaAReceiver,
PenpalKusamaASender, PenpalKusamaB, PenpalKusamaBPallet, PenpalKusamaBReceiver,
PenpalKusamaBSender, PenpalPolkadotA, PenpalPolkadotAReceiver, PenpalPolkadotASender, Polkadot,
PolkadotMockNet, PolkadotPallet, PolkadotReceiver, PolkadotSender,
};
pub use parachains_common::{AccountId, Balance};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use polkadot_parachain::primitives::{HrmpChannelId, Id};
pub use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId};
pub use xcm::{
prelude::*,
v3::{Error, NetworkId::Kusama as KusamaId},
DoubleEncoded,
};
pub use xcm_emulator::{
assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold,
Parachain as Para, RelayChain as Relay, TestExt,
AccountId32Junction, Chain, ParaId, Parachain as Para, RelayChain as Relay, Test, TestArgs,
TestContext, TestExt, TestExternalities,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
// `Assets` pallet index
pub const ASSETS_PALLET_ID: u8 = 50;
pub type RelayToSystemParaTest = Test<Kusama, AssetHubKusama>;
pub type SystemParaToRelayTest = Test<AssetHubKusama, Kusama>;
pub type SystemParaToParaTest = Test<AssetHubKusama, PenpalKusamaA>;
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
pub fn relay_test_args(amount: Balance) -> TestArgs {
TestArgs {
dest: Kusama::child_location_of(AssetHubKusama::para_id()),
beneficiary: AccountId32Junction {
network: None,
id: AssetHubKusamaReceiver::get().into(),
}
.into(),
amount,
assets: (Here, amount).into(),
asset_id: None,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests
pub fn system_para_test_args(
dest: MultiLocation,
beneficiary_id: AccountId32,
amount: Balance,
assets: MultiAssets,
asset_id: Option<u32>,
) -> TestArgs {
TestArgs {
dest,
beneficiary: AccountId32Junction { network: None, id: beneficiary_id.into() }.into(),
amount,
assets,
asset_id,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
#[cfg(test)]
mod tests;
@@ -0,0 +1,201 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
const MAX_CAPACITY: u32 = 8;
const MAX_MESSAGE_SIZE: u32 = 8192;
/// Opening HRMP channels between Parachains should work
#[test]
fn open_hrmp_channel_between_paras_works() {
// Parchain A init values
let para_a_id = PenpalKusamaA::para_id();
let para_a_root_origin = <PenpalKusamaA as Chain>::RuntimeOrigin::root();
// Parachain B init values
let para_b_id = PenpalKusamaB::para_id();
let para_b_root_origin = <PenpalKusamaB as Chain>::RuntimeOrigin::root();
let fee_amount = KUSAMA_ED * 1000;
let fund_amount = KUSAMA_ED * 1000_000_000;
// Fund Parachain's Sovereign accounts to be able to reserve the deposit
let para_a_sovereign_account = Kusama::fund_para_sovereign(fund_amount, para_a_id);
let para_b_sovereign_account = Kusama::fund_para_sovereign(fund_amount, para_b_id);
let relay_destination: VersionedMultiLocation = PenpalKusamaA::parent_location().into();
// ---- Init Open channel from Parachain to System Parachain
let mut call = Kusama::init_open_channel_call(para_b_id, MAX_CAPACITY, MAX_MESSAGE_SIZE);
let origin_kind = OriginKind::Native;
let native_asset: MultiAsset = (Here, fee_amount).into();
let beneficiary = Kusama::sovereign_account_id_of_child_para(para_a_id);
let mut xcm = xcm_transact_paid_execution(call, origin_kind, native_asset.clone(), beneficiary);
PenpalKusamaA::execute_with(|| {
assert_ok!(<PenpalKusamaA as PenpalKusamaAPallet>::PolkadotXcm::send(
para_a_root_origin,
bx!(relay_destination.clone()),
bx!(xcm),
));
});
Kusama::execute_with(|| {
type RuntimeEvent = <Kusama as Chain>::RuntimeEvent;
Kusama::assert_ump_queue_processed(
true,
Some(para_a_id),
Some(Weight::from_parts(1_312_558_000, 200000)),
);
assert_expected_events!(
Kusama,
vec![
// Parachain's Sovereign account balance is withdrawn to pay XCM fees
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == para_a_sovereign_account.clone(),
amount: *amount == fee_amount,
},
// Sender deposit is reserved for Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == para_a_sovereign_account,
},
// Open channel requested from Para A to Para B
RuntimeEvent::Hrmp(
polkadot_runtime_parachains::hrmp::Event::OpenChannelRequested(
sender, recipient, max_capacity, max_message_size
)
) => {
sender: *sender == para_a_id.into(),
recipient: *recipient == para_b_id.into(),
max_capacity: *max_capacity == MAX_CAPACITY,
max_message_size: *max_message_size == MAX_MESSAGE_SIZE,
},
]
);
});
// ---- Accept Open channel from Parachain to System Parachain
call = Kusama::accept_open_channel_call(para_a_id);
let beneficiary = Kusama::sovereign_account_id_of_child_para(para_b_id);
xcm = xcm_transact_paid_execution(call, origin_kind, native_asset, beneficiary);
PenpalKusamaB::execute_with(|| {
assert_ok!(<PenpalKusamaB as PenpalKusamaBPallet>::PolkadotXcm::send(
para_b_root_origin,
bx!(relay_destination),
bx!(xcm),
));
});
Kusama::execute_with(|| {
type RuntimeEvent = <Kusama as Chain>::RuntimeEvent;
Kusama::assert_ump_queue_processed(
true,
Some(para_b_id),
Some(Weight::from_parts(1_312_558_000, 200_000)),
);
assert_expected_events!(
Kusama,
vec![
// Parachain's Sovereign account balance is withdrawn to pay XCM fees
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == para_b_sovereign_account.clone(),
amount: *amount == fee_amount,
},
// Sender deposit is reserved for Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == para_b_sovereign_account,
},
// Open channel accepted for Para A to Para B
RuntimeEvent::Hrmp(
polkadot_runtime_parachains::hrmp::Event::OpenChannelAccepted(
sender, recipient
)
) => {
sender: *sender == para_a_id.into(),
recipient: *recipient == para_b_id.into(),
},
]
);
});
Kusama::force_process_hrmp_open(para_a_id, para_b_id);
}
/// Opening HRMP channels between System Parachains and Parachains should work
#[test]
fn force_open_hrmp_channel_for_system_para_works() {
// Relay Chain init values
let relay_root_origin = <Kusama as Chain>::RuntimeOrigin::root();
// System Para init values
let system_para_id = AssetHubKusama::para_id();
// Parachain A init values
let para_a_id = PenpalKusamaA::para_id();
let fund_amount = KUSAMA_ED * 1000_000_000;
// Fund Parachain's Sovereign accounts to be able to reserve the deposit
let para_a_sovereign_account = Kusama::fund_para_sovereign(fund_amount, para_a_id);
let system_para_sovereign_account = Kusama::fund_para_sovereign(fund_amount, system_para_id);
Kusama::execute_with(|| {
assert_ok!(<Kusama as KusamaPallet>::Hrmp::force_open_hrmp_channel(
relay_root_origin,
system_para_id,
para_a_id,
MAX_CAPACITY,
MAX_MESSAGE_SIZE
));
type RuntimeEvent = <Kusama as Chain>::RuntimeEvent;
assert_expected_events!(
Kusama,
vec![
// Sender deposit is reserved for System Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == system_para_sovereign_account,
},
// Recipient deposit is reserved for Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == para_a_sovereign_account,
},
// HRMP channel forced opened
RuntimeEvent::Hrmp(
polkadot_runtime_parachains::hrmp::Event::HrmpChannelForceOpened(
sender, recipient, max_capacity, max_message_size
)
) => {
sender: *sender == system_para_id.into(),
recipient: *recipient == para_a_id.into(),
max_capacity: *max_capacity == MAX_CAPACITY,
max_message_size: *max_message_size == MAX_MESSAGE_SIZE,
},
]
);
});
Kusama::force_process_hrmp_open(system_para_id, para_a_id);
}
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
mod hrmp_channels;
mod reserve_transfer;
mod send;
mod set_xcm_versions;
mod teleport;
mod transact;
@@ -16,66 +16,395 @@
use crate::*;
#[test]
fn reserve_transfer_native_asset_from_relay_to_assets() {
// Init tests variables
let amount = KUSAMA_ED * 1000;
let relay_sender_balance_before = Kusama::account_data_of(KusamaSender::get()).free;
let para_receiver_balance_before =
AssetHubKusama::account_data_of(AssetHubKusamaReceiver::get()).free;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Kusama as Chain>::RuntimeEvent;
let origin = <Kusama as Relay>::RuntimeOrigin::signed(KusamaSender::get());
let assets_para_destination: VersionedMultiLocation =
Kusama::child_location_of(AssetHubKusama::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: AssetHubKusamaReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
Kusama::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(630_092_000, 6_196)));
// Send XCM message from Relay Chain
Kusama::execute_with(|| {
assert_ok!(<Kusama as KusamaPallet>::XcmPallet::limited_reserve_transfer_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Kusama as Relay>::RuntimeEvent;
assert_expected_events!(
Kusama,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(630_092_000, 6196), *weight),
},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Para>::RuntimeEvent;
assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward {
outcome: Outcome::Incomplete(_, Error::UntrustedReserveLocation),
..
}) => {},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Kusama::account_data_of(KusamaSender::get()).free;
let para_sender_balance_after =
AssetHubKusama::account_data_of(AssetHubKusamaReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert_eq!(para_sender_balance_after, para_receiver_balance_before);
assert_expected_events!(
Kusama,
vec![
// Amount to reserve transfer is transferred to System Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => {
from: *from == t.sender.account_id,
to: *to == Kusama::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_dest_assertions_incomplete(_t: RelayToSystemParaTest) {
AssetHubKusama::assert_dmp_queue_incomplete(
Some(Weight::from_parts(1_000_000_000, 0)),
Some(Error::UntrustedReserveLocation),
);
}
fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) {
AssetHubKusama::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier))
}
fn system_para_to_para_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
AssetHubKusama::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
630_092_000,
6_196,
)));
assert_expected_events!(
AssetHubKusama,
vec![
// Amount to reserve transfer is transferred to Parachain's Sovereing account
RuntimeEvent::Balances(
pallet_balances::Event::Transfer { from, to, amount }
) => {
from: *from == t.sender.account_id,
to: *to == AssetHubKusama::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
AssetHubKusama::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
676_119_000,
6196,
)));
assert_expected_events!(
AssetHubKusama,
vec![
// Amount to reserve transfer is transferred to Parachain's Sovereing account
RuntimeEvent::Assets(
pallet_assets::Event::Transferred { asset_id, from, to, amount }
) => {
asset_id: *asset_id == ASSET_ID,
from: *from == t.sender.account_id,
to: *to == AssetHubKusama::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Kusama as KusamaPallet>::XcmPallet::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Kusama as KusamaPallet>::XcmPallet::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubKusama as AssetHubKusamaPallet>::PolkadotXcm::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubKusama as AssetHubKusamaPallet>::PolkadotXcm::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubKusama as AssetHubKusamaPallet>::PolkadotXcm::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubKusama as AssetHubKusamaPallet>::PolkadotXcm::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
#[test]
fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = KUSAMA_ED * 1000;
let test_args = TestContext {
sender: KusamaSender::get(),
receiver: AssetHubKusamaReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Kusama>(relay_origin_assertions);
test.set_assertion::<AssetHubKusama>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Kusama>(relay_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shoudln't work
#[test]
fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() {
// Init values for System Parachain
let destination = AssetHubKusama::parent_location();
let beneficiary_id = KusamaReceiver::get();
let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: KusamaReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubKusama>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubKusama>(system_para_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
#[test]
fn reserve_transfer_native_asset_from_relay_to_system_para_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = KUSAMA_ED * 1000;
let test_args = TestContext {
sender: KusamaSender::get(),
receiver: AssetHubKusamaReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Kusama>(relay_origin_assertions);
test.set_assertion::<AssetHubKusama>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Kusama>(relay_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work
#[test]
fn reserve_transfer_native_asset_from_system_para_to_relay_fails() {
// Init values for System Parachain
let destination = AssetHubKusama::parent_location();
let beneficiary_id = KusamaReceiver::get();
let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: KusamaReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubKusama>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubKusama>(system_para_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Limited Reserve Transfers of native asset from System Parachain to Parachain should work
#[test]
fn limited_reserve_transfer_native_asset_from_system_para_to_para() {
// Init values for System Parachain
let destination = AssetHubKusama::sibling_location_of(PenpalKusamaA::para_id());
let beneficiary_id = PenpalKusamaAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: PenpalKusamaAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
test.set_assertion::<AssetHubKusama>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubKusama>(system_para_to_para_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve transfers
}
/// Reserve Transfers of native asset from System Parachain to Parachain should work
#[test]
fn reserve_transfer_native_asset_from_system_para_to_para() {
// Init values for System Parachain
let destination = AssetHubKusama::sibling_location_of(PenpalKusamaA::para_id());
let beneficiary_id = PenpalKusamaAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: PenpalKusamaAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
test.set_assertion::<AssetHubKusama>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubKusama>(system_para_to_para_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve transfers
}
/// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work
#[test]
fn limited_reserve_transfer_asset_from_system_para_to_para() {
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
AssetHubKusama::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubKusamaSender::get(),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubKusama::sibling_location_of(PenpalKusamaA::para_id());
let beneficiary_id = PenpalKusamaAReceiver::get();
let amount_to_send = ASSET_MIN_BALANCE * 1000;
let assets =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
.into();
let system_para_test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: PenpalKusamaAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
system_para_test.set_assertion::<AssetHubKusama>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubKusama>(system_para_to_para_limited_reserve_transfer_assets);
system_para_test.assert();
}
/// Reserve Transfers of a local asset from System Parachain to Parachain should work
#[test]
fn reserve_transfer_asset_from_system_para_to_para() {
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
AssetHubKusama::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubKusamaSender::get(),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubKusama::sibling_location_of(PenpalKusamaA::para_id());
let beneficiary_id = PenpalKusamaAReceiver::get();
let amount_to_send = ASSET_MIN_BALANCE * 1000;
let assets =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
.into();
let system_para_test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: PenpalKusamaAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
system_para_test.set_assertion::<AssetHubKusama>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubKusama>(system_para_to_para_reserve_transfer_assets);
system_para_test.assert();
}
@@ -0,0 +1,196 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser` and signer is `sudo`
#[test]
fn send_transact_sudo_from_relay_to_system_para_works() {
// Init tests variables
let root_origin = <Kusama as Chain>::RuntimeOrigin::root();
let system_para_destination = Kusama::child_location_of(AssetHubKusama::para_id()).into();
let asset_owner: AccountId = AssetHubKusamaSender::get().into();
let xcm = AssetHubKusama::force_create_asset_xcm(
OriginKind::Superuser,
ASSET_ID,
asset_owner.clone(),
true,
1000,
);
// Send XCM message from Relay Chain
Kusama::execute_with(|| {
assert_ok!(<Kusama as KusamaPallet>::XcmPallet::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
Kusama::assert_xcm_pallet_sent();
});
// Receive XCM message in Assets Parachain
AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
AssetHubKusama::assert_dmp_queue_complete(Some(Weight::from_parts(1_019_445_000, 200_000)));
assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::Assets(pallet_assets::Event::ForceCreated { asset_id, owner }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == asset_owner,
},
]
);
assert!(<AssetHubKusama as AssetHubKusamaPallet>::Assets::asset_exists(ASSET_ID));
});
}
/// Relay Chain shouldn't be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Native`
#[test]
fn send_transact_native_from_relay_to_system_para_fails() {
// Init tests variables
let signed_origin = <Kusama as Chain>::RuntimeOrigin::signed(KusamaSender::get().into());
let system_para_destination = Kusama::child_location_of(AssetHubKusama::para_id()).into();
let asset_owner = AssetHubKusamaSender::get().into();
let xcm = AssetHubKusama::force_create_asset_xcm(
OriginKind::Native,
ASSET_ID,
asset_owner,
true,
1000,
);
// Send XCM message from Relay Chain
Kusama::execute_with(|| {
assert_err!(
<Kusama as KusamaPallet>::XcmPallet::send(
signed_origin,
bx!(system_para_destination),
bx!(xcm)
),
DispatchError::BadOrigin
);
});
}
/// System Parachain shouldn't be able to execute `Transact` instructions in Relay Chain
/// when `OriginKind::Native`
#[test]
fn send_transact_native_from_system_para_to_relay_fails() {
// Init tests variables
let signed_origin =
<AssetHubKusama as Chain>::RuntimeOrigin::signed(AssetHubKusamaSender::get().into());
let relay_destination = AssetHubKusama::parent_location().into();
let call = <Kusama as Chain>::RuntimeCall::System(frame_system::Call::<
<Kusama as Chain>::Runtime,
>::remark_with_event {
remark: vec![0, 1, 2, 3],
})
.encode()
.into();
let origin_kind = OriginKind::Native;
let xcm = xcm_transact_unpaid_execution(call, origin_kind);
// Send XCM message from Relay Chain
AssetHubKusama::execute_with(|| {
assert_err!(
<AssetHubKusama as AssetHubKusamaPallet>::PolkadotXcm::send(
signed_origin,
bx!(relay_destination),
bx!(xcm)
),
DispatchError::BadOrigin
);
});
}
/// Parachain should be able to send XCM paying its fee with sufficient asset
/// in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
let para_sovereign_account = AssetHubKusama::sovereign_account_id_of(
AssetHubKusama::sibling_location_of(PenpalKusamaA::para_id()),
);
// Force create and mint assets for Parachain's sovereign account
AssetHubKusama::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
ASSET_MIN_BALANCE * 1000000000,
);
// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubKusama::force_create_asset_call(
ASSET_ID,
para_sovereign_account.clone(),
true,
ASSET_MIN_BALANCE,
);
let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), fee_amount).into();
let root_origin = <PenpalKusamaA as Chain>::RuntimeOrigin::root();
let system_para_destination =
PenpalKusamaA::sibling_location_of(AssetHubKusama::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);
PenpalKusamaA::execute_with(|| {
assert_ok!(<PenpalKusamaA as PenpalKusamaAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
AssetHubKusama::assert_xcm_pallet_sent();
});
AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
AssetHubKusama::assert_xcmp_queue_success(Some(Weight::from_parts(2_176_414_000, 203_593)));
assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account,
balance: *balance == fee_amount,
},
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == ASSET_ID,
},
]
);
});
}
@@ -0,0 +1,94 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
#[test]
fn relay_sets_system_para_xcm_supported_version() {
// Init tests variables
let sudo_origin = <Kusama as Chain>::RuntimeOrigin::root();
let system_para_destination: MultiLocation =
Kusama::child_location_of(AssetHubKusama::para_id());
// Relay Chain sets supported version for Asset Parachain
Kusama::execute_with(|| {
assert_ok!(<Kusama as KusamaPallet>::XcmPallet::force_xcm_version(
sudo_origin,
bx!(system_para_destination),
XCM_V3
));
type RuntimeEvent = <Kusama as Chain>::RuntimeEvent;
assert_expected_events!(
Kusama,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::SupportedVersionChanged {
location,
version: XCM_V3
}) => { location: *location == system_para_destination, },
]
);
});
}
#[test]
fn system_para_sets_relay_xcm_supported_version() {
// Init test variables
let sudo_origin = <Kusama as Chain>::RuntimeOrigin::root();
let parent_location = AssetHubKusama::parent_location();
let system_para_destination: VersionedMultiLocation =
Kusama::child_location_of(AssetHubKusama::para_id()).into();
let call = <AssetHubKusama as Chain>::RuntimeCall::PolkadotXcm(pallet_xcm::Call::<
<AssetHubKusama as Chain>::Runtime,
>::force_xcm_version {
location: bx!(parent_location),
version: XCM_V3,
})
.encode()
.into();
let origin_kind = OriginKind::Superuser;
let xcm = xcm_transact_unpaid_execution(call, origin_kind);
// System Parachain sets supported version for Relay Chain throught it
Kusama::execute_with(|| {
assert_ok!(<Kusama as KusamaPallet>::XcmPallet::send(
sudo_origin,
bx!(system_para_destination),
bx!(xcm),
));
Kusama::assert_xcm_pallet_sent();
});
// System Parachain receive the XCM message
AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
AssetHubKusama::assert_dmp_queue_complete(Some(Weight::from_parts(1_019_210_000, 200_000)));
assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::SupportedVersionChanged {
location,
version: XCM_V3
}) => { location: *location == parent_location, },
]
);
});
}
@@ -16,65 +16,347 @@
use crate::*;
#[test]
fn teleport_native_assets_from_relay_to_assets_para() {
// Init tests variables
let amount = KUSAMA_ED * 1000;
let relay_sender_balance_before = Kusama::account_data_of(KusamaSender::get()).free;
let para_receiver_balance_before =
AssetHubKusama::account_data_of(AssetHubKusamaReceiver::get()).free;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Kusama as Chain>::RuntimeEvent;
let origin = <Kusama as Relay>::RuntimeOrigin::signed(KusamaSender::get());
let assets_para_destination: VersionedMultiLocation =
Kusama::child_location_of(AssetHubKusama::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: AssetHubKusamaReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
Kusama::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(631_531_000, 7_186)));
// Send XCM message from Relay Chain
Kusama::execute_with(|| {
assert_ok!(<Kusama as KusamaPallet>::XcmPallet::limited_teleport_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Kusama as Relay>::RuntimeEvent;
assert_expected_events!(
Kusama,
vec![
RuntimeEvent::XcmPallet(
pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } }
) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Para>::RuntimeEvent;
assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == AssetHubKusamaReceiver::get().into(),
},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Kusama::account_data_of(KusamaSender::get()).free;
let para_sender_balance_after =
AssetHubKusama::account_data_of(AssetHubKusamaReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert!(para_sender_balance_after > para_receiver_balance_before);
assert_expected_events!(
Kusama,
vec![
// Amount to teleport is withdrawn from Sender
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
},
// Amount to teleport is deposited in Relay's `CheckAccount`
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, amount }) => {
who: *who == <Kusama as KusamaPallet>::XcmPallet::check_account(),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_dest_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <Kusama as Chain>::RuntimeEvent;
Kusama::assert_ump_queue_processed(
true,
Some(AssetHubKusama::para_id()),
Some(Weight::from_parts(307_225_000, 7_186)),
);
assert_expected_events!(
Kusama,
vec![
// Amount is witdrawn from Relay Chain's `CheckAccount`
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == <Kusama as KusamaPallet>::XcmPallet::check_account(),
amount: *amount == t.args.amount,
},
// Amount minus fees are deposited in Receiver's account
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == t.receiver.account_id,
},
]
);
}
fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
Kusama::assert_ump_queue_processed(
false,
Some(AssetHubKusama::para_id()),
Some(Weight::from_parts(148_433_000, 3_593)),
);
}
fn para_origin_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
AssetHubKusama::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
534_872_000,
7_133,
)));
AssetHubKusama::assert_parachain_system_ump_sent();
assert_expected_events!(
AssetHubKusama,
vec![
// Amount is withdrawn from Sender's account
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
},
]
);
}
fn para_dest_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
AssetHubKusama::assert_dmp_queue_complete(Some(Weight::from_parts(165_592_000, 0)));
assert_expected_events!(
AssetHubKusama,
vec![
// Amount minus fees are deposited in Receiver's account
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == t.receiver.account_id,
},
]
);
}
fn relay_limited_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Kusama as KusamaPallet>::XcmPallet::limited_teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn relay_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Kusama as KusamaPallet>::XcmPallet::teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubKusama as AssetHubKusamaPallet>::PolkadotXcm::limited_teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
// TODO: Uncomment when https://github.com/paritytech/polkadot/pull/7424 is merged
// fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
// <AssetHubKusama as AssetHubKusamaPallet>::PolkadotXcm::teleport_assets(
// t.signed_origin,
// bx!(t.args.dest),
// bx!(t.args.beneficiary),
// bx!(t.args.assets),
// t.args.fee_asset_item,
// )
// }
/// Limited Teleport of native asset from Relay Chain to the System Parachain should work
#[test]
fn limited_teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = KUSAMA_ED * 1000;
let test_args = TestContext {
sender: KusamaSender::get(),
receiver: AssetHubKusamaReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Kusama>(relay_origin_assertions);
test.set_assertion::<AssetHubKusama>(para_dest_assertions);
test.set_dispatchable::<Kusama>(relay_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
/// Limited Teleport of native asset from System Parachain to Relay Chain
/// should work when there is enough balance in Relay Chain's `CheckAccount`
#[test]
fn limited_teleport_native_assets_back_from_system_para_to_relay_works() {
// Dependency - Relay Chain's `CheckAccount` should have enough balance
limited_teleport_native_assets_from_relay_to_system_para_works();
// Init values for Relay Chain
let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
let destination = AssetHubKusama::parent_location();
let beneficiary_id = KusamaReceiver::get();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: KusamaReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubKusama>(para_origin_assertions);
test.set_assertion::<Kusama>(relay_dest_assertions);
test.set_dispatchable::<AssetHubKusama>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
/// Limited Teleport of native asset from System Parachain to Relay Chain
/// should't work when there is not enough balance in Relay Chain's `CheckAccount`
#[test]
fn limited_teleport_native_assets_from_system_para_to_relay_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
let destination = AssetHubKusama::parent_location().into();
let beneficiary_id = KusamaReceiver::get().into();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubKusamaSender::get(),
receiver: KusamaReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubKusama>(para_origin_assertions);
test.set_assertion::<Kusama>(relay_dest_assertions_fail);
test.set_dispatchable::<AssetHubKusama>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance does not change
assert_eq!(receiver_balance_after, receiver_balance_before);
}
/// Teleport of native asset from Relay Chain to the System Parachain should work
#[test]
fn teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = KUSAMA_ED * 1000;
let test_args = TestContext {
sender: KusamaSender::get(),
receiver: AssetHubKusamaReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Kusama>(relay_origin_assertions);
test.set_assertion::<AssetHubKusama>(para_dest_assertions);
test.set_dispatchable::<Kusama>(relay_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
// TODO: Uncomment when https://github.com/paritytech/polkadot/pull/7424 is merged
// Right now it is failing in the Relay Chain with a
// `messageQueue.ProcessingFailed` event `error: Unsupported`.
// The reason is the `Weigher` in `pallet_xcm` is not properly calculating the `remote_weight`
// and it cause an `Overweight` error in `AllowTopLevelPaidExecutionFrom` barrier
// /// Teleport of native asset from System Parachains to the Relay Chain
// /// should work when there is enough balance in Relay Chain's `CheckAccount`
// #[test]
// fn teleport_native_assets_back_from_system_para_to_relay_works() {
// // Dependency - Relay Chain's `CheckAccount` should have enough balance
// teleport_native_assets_from_relay_to_system_para_works();
// // Init values for Relay Chain
// let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
// let test_args = TestContext {
// sender: AssetHubKusamaSender::get(),
// receiver: KusamaReceiver::get(),
// args: get_para_dispatch_args(amount_to_send),
// };
// let mut test = SystemParaToRelayTest::new(test_args);
// let sender_balance_before = test.sender.balance;
// let receiver_balance_before = test.receiver.balance;
// test.set_assertion::<AssetHubKusama>(para_origin_assertions);
// test.set_assertion::<Kusama>(relay_dest_assertions);
// test.set_dispatchable::<AssetHubKusama>(system_para_teleport_assets);
// test.assert();
// let sender_balance_after = test.sender.balance;
// let receiver_balance_after = test.receiver.balance;
// // Sender's balance is reduced
// assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// // Receiver's balance is increased
// assert!(receiver_balance_after > receiver_balance_before);
// }
// /// Teleport of native asset from System Parachain to Relay Chain
// /// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount`
// #[test]
// fn teleport_native_assets_from_system_para_to_relay_fails() {
// // Init values for Relay Chain
// let amount_to_send: Balance = ASSET_HUB_KUSAMA_ED * 1000;
// let assets = (Parent, amount_to_send).into();
//
// let test_args = TestContext {
// sender: AssetHubKusamaSender::get(),
// receiver: KusamaReceiver::get(),
// args: system_para_test_args(amount_to_send),
// assets,
// None
// };
// let mut test = SystemParaToRelayTest::new(test_args);
// let sender_balance_before = test.sender.balance;
// let receiver_balance_before = test.receiver.balance;
// test.set_assertion::<AssetHubKusama>(para_origin_assertions);
// test.set_assertion::<Kusama>(relay_dest_assertions);
// test.set_dispatchable::<AssetHubKusama>(system_para_teleport_assets);
// test.assert();
// let sender_balance_after = test.sender.balance;
// let receiver_balance_after = test.receiver.balance;
// // Sender's balance is reduced
// assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// // Receiver's balance does not change
// assert_eq!(receiver_balance_after, receiver_balance_before);
// }
@@ -1,74 +0,0 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
#[test]
fn transact_sudo_from_relay_to_assets_para() {
// Init tests variables
// Call to be executed in Assets Parachain
const ASSET_ID: u32 = 1;
let call = <AssetHubKusama as Para>::RuntimeCall::Assets(pallet_assets::Call::<
<AssetHubKusama as Para>::Runtime,
Instance1,
>::force_create {
id: ASSET_ID.into(),
is_sufficient: true,
min_balance: 1000,
owner: AssetHubKusamaSender::get().into(),
})
.encode()
.into();
// XcmPallet send arguments
let sudo_origin = <Kusama as Relay>::RuntimeOrigin::root();
let assets_para_destination: VersionedMultiLocation =
Kusama::child_location_of(AssetHubKusama::para_id()).into();
let weight_limit = WeightLimit::Unlimited;
let require_weight_at_most = Weight::from_parts(1000000000, 200000);
let origin_kind = OriginKind::Superuser;
let check_origin = None;
let xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit, check_origin },
Transact { require_weight_at_most, origin_kind, call },
]));
// Send XCM message from Relay Chain
Kusama::execute_with(|| {
assert_ok!(<Kusama as KusamaPallet>::XcmPallet::send(
sudo_origin,
bx!(assets_para_destination),
bx!(xcm),
));
type RuntimeEvent = <Kusama as Relay>::RuntimeEvent;
assert_expected_events!(
Kusama,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubKusama::execute_with(|| {
assert!(<AssetHubKusama as AssetHubKusamaPallet>::Assets::asset_exists(ASSET_ID));
});
}
@@ -28,8 +28,9 @@ pallet-xcm = { default-features = false, git = "https://github.com/paritytech/po
# Cumulus
parachains-common = { path = "../../../../common" }
penpal-runtime = { path = "../../../../runtimes/testing/penpal" }
asset-hub-polkadot-runtime = { path = "../../../../runtimes/assets/asset-hub-polkadot" }
cumulus-pallet-dmp-queue = { path = "../../../../../pallets/dmp-queue" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../pallets/xcmp-queue" }
cumulus-pallet-parachain-system = { path = "../../../../../pallets/parachain-system" }
# Local
xcm-emulator = { default-features = false, path = "../../../../../xcm/xcm-emulator" }
@@ -16,35 +16,87 @@
pub use codec::Encode;
pub use frame_support::{
assert_ok, instances::Instance1, pallet_prelude::Weight, traits::fungibles::Inspect,
assert_err, assert_ok,
instances::Instance1,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult, MultiAddress},
traits::{fungibles::Inspect, OriginTrait},
};
pub use integration_tests_common::{
constants::{
accounts::{ALICE, BOB},
asset_hub_polkadot::ED as ASSET_HUB_POLKADOT_ED,
polkadot::ED as POLKADOT_ED,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
},
AccountId, AssetHubKusama, AssetHubKusamaPallet, AssetHubKusamaReceiver, AssetHubKusamaSender,
AssetHubPolkadot, AssetHubPolkadotPallet, AssetHubPolkadotReceiver, AssetHubPolkadotSender,
BridgeHubKusama, BridgeHubKusamaPallet, BridgeHubKusamaReceiver, BridgeHubKusamaSender,
BridgeHubPolkadot, BridgeHubPolkadotPallet, BridgeHubPolkadotReceiver, BridgeHubPolkadotSender,
Collectives, CollectivesPallet, CollectivesReceiver, CollectivesSender, Kusama, KusamaMockNet,
KusamaPallet, KusamaReceiver, KusamaSender, PenpalKusama, PenpalKusamaReceiver,
PenpalKusamaSender, PenpalPolkadot, PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot,
lazy_static::lazy_static,
xcm_transact_paid_execution, xcm_transact_unpaid_execution, AssetHubPolkadot,
AssetHubPolkadotPallet, AssetHubPolkadotReceiver, AssetHubPolkadotSender, BridgeHubPolkadot,
BridgeHubPolkadotPallet, BridgeHubPolkadotReceiver, BridgeHubPolkadotSender, Collectives,
CollectivesPallet, CollectivesReceiver, CollectivesSender, PenpalPolkadotA,
PenpalPolkadotAPallet, PenpalPolkadotAReceiver, PenpalPolkadotASender, PenpalPolkadotB,
PenpalPolkadotBPallet, PenpalPolkadotBReceiver, PenpalPolkadotBSender, Polkadot,
PolkadotMockNet, PolkadotPallet, PolkadotReceiver, PolkadotSender,
};
pub use parachains_common::{AccountId, Balance};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use polkadot_parachain::primitives::{HrmpChannelId, Id};
pub use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId};
pub use xcm::{
prelude::*,
v3::{
Error,
NetworkId::{Kusama as KusamaId, Polkadot as PolkadotId},
},
v3::{Error, NetworkId::Polkadot as PolkadotId},
DoubleEncoded,
};
pub use xcm_emulator::{
assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold,
Parachain as Para, RelayChain as Relay, TestExt,
AccountId32Junction, Chain, ParaId, Parachain as Para, RelayChain as Relay, Test, TestArgs,
TestContext, TestExt, TestExternalities,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
// `Assets` pallet index
pub const ASSETS_PALLET_ID: u8 = 50;
pub type RelayToSystemParaTest = Test<Polkadot, AssetHubPolkadot>;
pub type SystemParaToRelayTest = Test<AssetHubPolkadot, Polkadot>;
pub type SystemParaToParaTest = Test<AssetHubPolkadot, PenpalPolkadotA>;
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
pub fn relay_test_args(amount: Balance) -> TestArgs {
TestArgs {
dest: Polkadot::child_location_of(AssetHubPolkadot::para_id()),
beneficiary: AccountId32Junction {
network: None,
id: AssetHubPolkadotReceiver::get().into(),
}
.into(),
amount,
assets: (Here, amount).into(),
asset_id: None,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests
pub fn system_para_test_args(
dest: MultiLocation,
beneficiary_id: AccountId32,
amount: Balance,
assets: MultiAssets,
asset_id: Option<u32>,
) -> TestArgs {
TestArgs {
dest,
beneficiary: AccountId32Junction { network: None, id: beneficiary_id.into() }.into(),
amount,
assets,
asset_id,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
#[cfg(test)]
mod tests;
@@ -0,0 +1,201 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
const MAX_CAPACITY: u32 = 8;
const MAX_MESSAGE_SIZE: u32 = 8192;
/// Opening HRMP channels between Parachains should work
#[test]
fn open_hrmp_channel_between_paras_works() {
// Parchain A init values
let para_a_id = PenpalPolkadotA::para_id();
let para_a_root_origin = <PenpalPolkadotA as Chain>::RuntimeOrigin::root();
// Parachain B init values
let para_b_id = PenpalPolkadotB::para_id();
let para_b_root_origin = <PenpalPolkadotB as Chain>::RuntimeOrigin::root();
let fee_amount = POLKADOT_ED * 1000;
let fund_amount = POLKADOT_ED * 1000_000_000;
// Fund Parachain's Sovereign accounts to be able to reserve the deposit
let para_a_sovereign_account = Polkadot::fund_para_sovereign(fund_amount, para_a_id);
let para_b_sovereign_account = Polkadot::fund_para_sovereign(fund_amount, para_b_id);
let relay_destination: VersionedMultiLocation = PenpalPolkadotA::parent_location().into();
// ---- Init Open channel from Parachain to System Parachain
let mut call = Polkadot::init_open_channel_call(para_b_id, MAX_CAPACITY, MAX_MESSAGE_SIZE);
let origin_kind = OriginKind::Native;
let native_asset: MultiAsset = (Here, fee_amount).into();
let beneficiary = Polkadot::sovereign_account_id_of_child_para(para_a_id);
let mut xcm = xcm_transact_paid_execution(call, origin_kind, native_asset.clone(), beneficiary);
PenpalPolkadotA::execute_with(|| {
assert_ok!(<PenpalPolkadotA as PenpalPolkadotAPallet>::PolkadotXcm::send(
para_a_root_origin,
bx!(relay_destination.clone()),
bx!(xcm),
));
});
Polkadot::execute_with(|| {
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;
Polkadot::assert_ump_queue_processed(
true,
Some(para_a_id),
Some(Weight::from_parts(1_282_426_000, 207_186)),
);
assert_expected_events!(
Polkadot,
vec![
// Parachain's Sovereign account balance is withdrawn to pay XCM fees
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == para_a_sovereign_account.clone(),
amount: *amount == fee_amount,
},
// Sender deposit is reserved for Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == para_a_sovereign_account,
},
// Open channel requested from Para A to Para B
RuntimeEvent::Hrmp(
polkadot_runtime_parachains::hrmp::Event::OpenChannelRequested(
sender, recipient, max_capacity, max_message_size
)
) => {
sender: *sender == para_a_id.into(),
recipient: *recipient == para_b_id.into(),
max_capacity: *max_capacity == MAX_CAPACITY,
max_message_size: *max_message_size == MAX_MESSAGE_SIZE,
},
]
);
});
// ---- Accept Open channel from Parachain to System Parachain
call = Polkadot::accept_open_channel_call(para_a_id);
let beneficiary = Polkadot::sovereign_account_id_of_child_para(para_b_id);
xcm = xcm_transact_paid_execution(call, origin_kind, native_asset, beneficiary);
PenpalPolkadotB::execute_with(|| {
assert_ok!(<PenpalPolkadotB as PenpalPolkadotBPallet>::PolkadotXcm::send(
para_b_root_origin,
bx!(relay_destination),
bx!(xcm),
));
});
Polkadot::execute_with(|| {
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;
Polkadot::assert_ump_queue_processed(
true,
Some(para_b_id),
Some(Weight::from_parts(1_282_426_000, 207_186)),
);
assert_expected_events!(
Polkadot,
vec![
// Parachain's Sovereign account balance is withdrawn to pay XCM fees
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == para_b_sovereign_account.clone(),
amount: *amount == fee_amount,
},
// Sender deposit is reserved for Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == para_b_sovereign_account,
},
// Open channel accepted for Para A to Para B
RuntimeEvent::Hrmp(
polkadot_runtime_parachains::hrmp::Event::OpenChannelAccepted(
sender, recipient
)
) => {
sender: *sender == para_a_id.into(),
recipient: *recipient == para_b_id.into(),
},
]
);
});
Polkadot::force_process_hrmp_open(para_a_id, para_b_id);
}
/// Opening HRMP channels between System Parachains and Parachains should work
#[test]
fn force_open_hrmp_channel_for_system_para_works() {
// Relay Chain init values
let relay_root_origin = <Polkadot as Chain>::RuntimeOrigin::root();
// System Para init values
let system_para_id = AssetHubPolkadot::para_id();
// Parachain A init values
let para_a_id = PenpalPolkadotA::para_id();
let fund_amount = POLKADOT_ED * 1000_000_000;
// Fund Parachain's Sovereign accounts to be able to reserve the deposit
let system_para_sovereign_account = Polkadot::fund_para_sovereign(fund_amount, system_para_id);
let para_a_sovereign_account = Polkadot::fund_para_sovereign(fund_amount, para_a_id);
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::Hrmp::force_open_hrmp_channel(
relay_root_origin,
system_para_id,
para_a_id,
MAX_CAPACITY,
MAX_MESSAGE_SIZE
));
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
// Sender deposit is reserved for System Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == system_para_sovereign_account,
},
// Recipient deposit is reserved for Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Reserved { who, .. }) =>{
who: *who == para_a_sovereign_account,
},
// HRMP channel forced opened
RuntimeEvent::Hrmp(
polkadot_runtime_parachains::hrmp::Event::HrmpChannelForceOpened(
sender, recipient, max_capacity, max_message_size
)
) => {
sender: *sender == system_para_id.into(),
recipient: *recipient == para_a_id.into(),
max_capacity: *max_capacity == MAX_CAPACITY,
max_message_size: *max_message_size == MAX_MESSAGE_SIZE,
},
]
);
});
Polkadot::force_process_hrmp_open(system_para_id, para_a_id);
}
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
mod hrmp_channels;
mod reserve_transfer;
mod send;
mod set_xcm_versions;
mod teleport;
mod transact;
@@ -16,66 +16,395 @@
use crate::*;
#[test]
fn reserve_transfer_native_asset_from_relay_to_assets() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_receiver_balance_before =
AssetHubPolkadot::account_data_of(AssetHubPolkadotReceiver::get()).free;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;
let origin = <Polkadot as Relay>::RuntimeOrigin::signed(PolkadotSender::get());
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(AssetHubPolkadot::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: AssetHubPolkadotReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
Polkadot::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(629_384_000, 6_196)));
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::limited_reserve_transfer_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(686_043_000, 6196), *weight),
},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Para>::RuntimeEvent;
assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward {
outcome: Outcome::Incomplete(_, Error::UntrustedReserveLocation),
..
}) => {},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_sender_balance_after =
AssetHubPolkadot::account_data_of(AssetHubPolkadotReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert_eq!(para_sender_balance_after, para_receiver_balance_before);
assert_expected_events!(
Polkadot,
vec![
// Amount to reserve transfer is transferred to System Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => {
from: *from == t.sender.account_id,
to: *to == Polkadot::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_dest_assertions_incomplete(_t: RelayToSystemParaTest) {
AssetHubPolkadot::assert_dmp_queue_incomplete(
Some(Weight::from_parts(1_000_000_000, 0)),
Some(Error::UntrustedReserveLocation),
);
}
fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) {
AssetHubPolkadot::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier))
}
fn system_para_to_para_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
AssetHubPolkadot::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
676_119_000,
6196,
)));
assert_expected_events!(
AssetHubPolkadot,
vec![
// Amount to reserve transfer is transferred to Parachain's Sovereing account
RuntimeEvent::Balances(
pallet_balances::Event::Transfer { from, to, amount }
) => {
from: *from == t.sender.account_id,
to: *to == AssetHubPolkadot::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
AssetHubPolkadot::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
676_119_000,
6196,
)));
assert_expected_events!(
AssetHubPolkadot,
vec![
// Amount to reserve transfer is transferred to Parachain's Sovereing account
RuntimeEvent::Assets(
pallet_assets::Event::Transferred { asset_id, from, to, amount }
) => {
asset_id: *asset_id == ASSET_ID,
from: *from == t.sender.account_id,
to: *to == AssetHubPolkadot::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Polkadot as PolkadotPallet>::XcmPallet::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Polkadot as PolkadotPallet>::XcmPallet::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
#[test]
fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = POLKADOT_ED * 1000;
let test_args = TestContext {
sender: PolkadotSender::get(),
receiver: AssetHubPolkadotReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Polkadot>(relay_origin_assertions);
test.set_assertion::<AssetHubPolkadot>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Polkadot>(relay_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shoudln't work
#[test]
fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() {
// Init values for System Parachain
let destination = AssetHubPolkadot::parent_location();
let beneficiary_id = PolkadotReceiver::get();
let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PolkadotReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubPolkadot>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubPolkadot>(system_para_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
#[test]
fn reserve_transfer_native_asset_from_relay_to_system_para_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = POLKADOT_ED * 1000;
let test_args = TestContext {
sender: PolkadotSender::get(),
receiver: AssetHubPolkadotReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Polkadot>(relay_origin_assertions);
test.set_assertion::<AssetHubPolkadot>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Polkadot>(relay_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work
#[test]
fn reserve_transfer_native_asset_from_system_para_to_relay_fails() {
// Init values for System Parachain
let destination = AssetHubPolkadot::parent_location();
let beneficiary_id = PolkadotReceiver::get();
let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PolkadotReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubPolkadot>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubPolkadot>(system_para_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Limited Reserve Transfers of native asset from System Parachain to Parachain should work
#[test]
fn limited_reserve_transfer_native_asset_from_system_para_to_para() {
// Init values for System Parachain
let destination = AssetHubPolkadot::sibling_location_of(PenpalPolkadotA::para_id());
let beneficiary_id = PenpalPolkadotAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PenpalPolkadotAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
test.set_assertion::<AssetHubPolkadot>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubPolkadot>(system_para_to_para_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve transfers
}
/// Reserve Transfers of native asset from System Parachain to Parachain should work
#[test]
fn reserve_transfer_native_asset_from_system_para_to_para() {
// Init values for System Parachain
let destination = AssetHubPolkadot::sibling_location_of(PenpalPolkadotA::para_id());
let beneficiary_id = PenpalPolkadotAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PenpalPolkadotAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
test.set_assertion::<AssetHubPolkadot>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubPolkadot>(system_para_to_para_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve transfers
}
/// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work
#[test]
fn limited_reserve_transfer_asset_from_system_para_to_para() {
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
AssetHubPolkadot::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubPolkadotSender::get(),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubPolkadot::sibling_location_of(PenpalPolkadotA::para_id());
let beneficiary_id = PenpalPolkadotAReceiver::get();
let amount_to_send = ASSET_MIN_BALANCE * 1000;
let assets =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
.into();
let system_para_test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PenpalPolkadotAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
system_para_test.set_assertion::<AssetHubPolkadot>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubPolkadot>(system_para_to_para_limited_reserve_transfer_assets);
system_para_test.assert();
}
/// Reserve Transfers of a local asset from System Parachain to Parachain should work
#[test]
fn reserve_transfer_asset_from_system_para_to_para() {
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
AssetHubPolkadot::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubPolkadotSender::get(),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubPolkadot::sibling_location_of(PenpalPolkadotA::para_id());
let beneficiary_id = PenpalPolkadotAReceiver::get();
let amount_to_send = ASSET_MIN_BALANCE * 1000;
let assets =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
.into();
let system_para_test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PenpalPolkadotAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
system_para_test.set_assertion::<AssetHubPolkadot>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubPolkadot>(system_para_to_para_reserve_transfer_assets);
system_para_test.assert();
}
@@ -0,0 +1,202 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser` and signer is `sudo`
#[test]
fn send_transact_sudo_from_relay_to_system_para_works() {
// Init tests variables
let root_origin = <Polkadot as Chain>::RuntimeOrigin::root();
let system_para_destination = Polkadot::child_location_of(AssetHubPolkadot::para_id()).into();
let asset_owner: AccountId = AssetHubPolkadotSender::get().into();
let xcm = AssetHubPolkadot::force_create_asset_xcm(
OriginKind::Superuser,
ASSET_ID,
asset_owner.clone(),
true,
1000,
);
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
Polkadot::assert_xcm_pallet_sent();
});
// Receive XCM message in Assets Parachain
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
AssetHubPolkadot::assert_dmp_queue_complete(Some(Weight::from_parts(
1_019_445_000,
200_000,
)));
assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::Assets(pallet_assets::Event::ForceCreated { asset_id, owner }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == asset_owner,
},
]
);
assert!(<AssetHubPolkadot as AssetHubPolkadotPallet>::Assets::asset_exists(ASSET_ID));
});
}
/// Relay Chain shouldn't be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Native`
#[test]
fn send_transact_native_from_relay_to_system_para_fails() {
// Init tests variables
let signed_origin = <Polkadot as Chain>::RuntimeOrigin::signed(PolkadotSender::get().into());
let system_para_destination = Polkadot::child_location_of(AssetHubPolkadot::para_id()).into();
let asset_owner = AssetHubPolkadotSender::get().into();
let xcm = AssetHubPolkadot::force_create_asset_xcm(
OriginKind::Native,
ASSET_ID,
asset_owner,
true,
1000,
);
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_err!(
<Polkadot as PolkadotPallet>::XcmPallet::send(
signed_origin,
bx!(system_para_destination),
bx!(xcm)
),
DispatchError::BadOrigin
);
});
}
/// System Parachain shouldn't be able to execute `Transact` instructions in Relay Chain
/// when `OriginKind::Native`
#[test]
fn send_transact_native_from_system_para_to_relay_fails() {
// Init tests variables
let signed_origin =
<AssetHubPolkadot as Chain>::RuntimeOrigin::signed(AssetHubPolkadotSender::get().into());
let relay_destination = AssetHubPolkadot::parent_location().into();
let call = <Polkadot as Chain>::RuntimeCall::System(frame_system::Call::<
<Polkadot as Chain>::Runtime,
>::remark_with_event {
remark: vec![0, 1, 2, 3],
})
.encode()
.into();
let origin_kind = OriginKind::Native;
let xcm = xcm_transact_unpaid_execution(call, origin_kind);
// Send XCM message from Relay Chain
AssetHubPolkadot::execute_with(|| {
assert_err!(
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::send(
signed_origin,
bx!(relay_destination),
bx!(xcm)
),
DispatchError::BadOrigin
);
});
}
/// Parachain should be able to send XCM paying its fee with sufficient asset
/// in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
let para_sovereign_account = AssetHubPolkadot::sovereign_account_id_of(
AssetHubPolkadot::sibling_location_of(PenpalPolkadotA::para_id()),
);
// Force create and mint assets for Parachain's sovereign account
AssetHubPolkadot::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
ASSET_MIN_BALANCE * 1000000000,
);
// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubPolkadot::force_create_asset_call(
ASSET_ID,
para_sovereign_account.clone(),
true,
ASSET_MIN_BALANCE,
);
let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), fee_amount).into();
let root_origin = <PenpalPolkadotA as Chain>::RuntimeOrigin::root();
let system_para_destination =
PenpalPolkadotA::sibling_location_of(AssetHubPolkadot::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);
PenpalPolkadotA::execute_with(|| {
assert_ok!(<PenpalPolkadotA as PenpalPolkadotAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
AssetHubPolkadot::assert_xcm_pallet_sent();
});
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
AssetHubPolkadot::assert_xcmp_queue_success(Some(Weight::from_parts(
2_176_414_000,
203_593,
)));
assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account,
balance: *balance == fee_amount,
},
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == ASSET_ID,
},
]
);
});
}
@@ -0,0 +1,97 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
#[test]
fn relay_sets_system_para_xcm_supported_version() {
// Init tests variables
let sudo_origin = <Polkadot as Chain>::RuntimeOrigin::root();
let system_para_destination: MultiLocation =
Polkadot::child_location_of(AssetHubPolkadot::para_id());
// Relay Chain sets supported version for Asset Parachain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::force_xcm_version(
sudo_origin,
bx!(system_para_destination),
XCM_V3
));
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::SupportedVersionChanged {
location,
version: XCM_V3
}) => { location: *location == system_para_destination, },
]
);
});
}
#[test]
fn system_para_sets_relay_xcm_supported_version() {
// Init test variables
let sudo_origin = <Polkadot as Chain>::RuntimeOrigin::root();
let parent_location = AssetHubPolkadot::parent_location();
let system_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(AssetHubPolkadot::para_id()).into();
let call = <AssetHubPolkadot as Chain>::RuntimeCall::PolkadotXcm(pallet_xcm::Call::<
<AssetHubPolkadot as Chain>::Runtime,
>::force_xcm_version {
location: bx!(parent_location),
version: XCM_V3,
})
.encode()
.into();
let origin_kind = OriginKind::Superuser;
let xcm = xcm_transact_unpaid_execution(call, origin_kind);
// System Parachain sets supported version for Relay Chain throught it
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::send(
sudo_origin,
bx!(system_para_destination),
bx!(xcm),
));
Polkadot::assert_xcm_pallet_sent();
});
// System Parachain receive the XCM message
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
AssetHubPolkadot::assert_dmp_queue_complete(Some(Weight::from_parts(
1_019_210_000,
200_000,
)));
assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::SupportedVersionChanged {
location,
version: XCM_V3
}) => { location: *location == parent_location, },
]
);
});
}
@@ -16,63 +16,347 @@
use crate::*;
#[test]
fn teleport_native_assets_from_relay_to_assets_para() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_receiver_balance_before =
AssetHubPolkadot::account_data_of(AssetHubPolkadotReceiver::get()).free;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;
let origin = <Polkadot as Relay>::RuntimeOrigin::signed(PolkadotSender::get());
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(AssetHubPolkadot::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: AssetHubPolkadotReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
Polkadot::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(632_207_000, 7_186)));
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::limited_teleport_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } }) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Para>::RuntimeEvent;
assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == AssetHubPolkadotReceiver::get().into(),
},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_sender_balance_after =
AssetHubPolkadot::account_data_of(AssetHubPolkadotReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert!(para_sender_balance_after > para_receiver_balance_before);
assert_expected_events!(
Polkadot,
vec![
// Amount to teleport is withdrawn from Sender
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
},
// Amount to teleport is deposited in Relay's `CheckAccount`
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, amount }) => {
who: *who == <Polkadot as PolkadotPallet>::XcmPallet::check_account(),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_dest_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <Polkadot as Chain>::RuntimeEvent;
Polkadot::assert_ump_queue_processed(
true,
Some(AssetHubPolkadot::para_id()),
Some(Weight::from_parts(368_931_000, 7_186)),
);
assert_expected_events!(
Polkadot,
vec![
// Amount is witdrawn from Relay Chain's `CheckAccount`
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == <Polkadot as PolkadotPallet>::XcmPallet::check_account(),
amount: *amount == t.args.amount,
},
// Amount minus fees are deposited in Receiver's account
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == t.receiver.account_id,
},
]
);
}
fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
Polkadot::assert_ump_queue_processed(
false,
Some(AssetHubPolkadot::para_id()),
Some(Weight::from_parts(232_982_000, 3_593)),
);
}
fn para_origin_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
AssetHubPolkadot::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
632_207_000,
7_186,
)));
AssetHubPolkadot::assert_parachain_system_ump_sent();
assert_expected_events!(
AssetHubPolkadot,
vec![
// Amount is withdrawn from Sender's account
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
},
]
);
}
fn para_dest_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
AssetHubPolkadot::assert_dmp_queue_complete(Some(Weight::from_parts(161_196_000, 0)));
assert_expected_events!(
AssetHubPolkadot,
vec![
// Amount minus fees are deposited in Receiver's account
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == t.receiver.account_id,
},
]
);
}
fn relay_limited_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Polkadot as PolkadotPallet>::XcmPallet::limited_teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn relay_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Polkadot as PolkadotPallet>::XcmPallet::teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::limited_teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
// TODO: Uncomment when https://github.com/paritytech/polkadot/pull/7424 is merged
// fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
// <AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::teleport_assets(
// t.signed_origin,
// bx!(t.args.dest),
// bx!(t.args.beneficiary),
// bx!(t.args.assets),
// t.args.fee_asset_item,
// )
// }
/// Limited Teleport of native asset from Relay Chain to the System Parachain should work
#[test]
fn limited_teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = POLKADOT_ED * 1000;
let test_args = TestContext {
sender: PolkadotSender::get(),
receiver: AssetHubPolkadotReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Polkadot>(relay_origin_assertions);
test.set_assertion::<AssetHubPolkadot>(para_dest_assertions);
test.set_dispatchable::<Polkadot>(relay_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
/// Limited Teleport of native asset from System Parachain to Relay Chain
/// should work when there is enough balance in Relay Chain's `CheckAccount`
#[test]
fn limited_teleport_native_assets_back_from_system_para_to_relay_works() {
// Dependency - Relay Chain's `CheckAccount` should have enough balance
limited_teleport_native_assets_from_relay_to_system_para_works();
// Init values for Relay Chain
let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
let destination = AssetHubPolkadot::parent_location();
let beneficiary_id = PolkadotReceiver::get();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PolkadotReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubPolkadot>(para_origin_assertions);
test.set_assertion::<Polkadot>(relay_dest_assertions);
test.set_dispatchable::<AssetHubPolkadot>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
/// Limited Teleport of native asset from System Parachain to Relay Chain
/// should't work when there is not enough balance in Relay Chain's `CheckAccount`
#[test]
fn limited_teleport_native_assets_from_system_para_to_relay_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
let destination = AssetHubPolkadot::parent_location().into();
let beneficiary_id = PolkadotReceiver::get().into();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubPolkadotSender::get(),
receiver: PolkadotReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubPolkadot>(para_origin_assertions);
test.set_assertion::<Polkadot>(relay_dest_assertions_fail);
test.set_dispatchable::<AssetHubPolkadot>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance does not change
assert_eq!(receiver_balance_after, receiver_balance_before);
}
/// Teleport of native asset from Relay Chain to the System Parachain should work
#[test]
fn teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = POLKADOT_ED * 1000;
let test_args = TestContext {
sender: PolkadotSender::get(),
receiver: AssetHubPolkadotReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Polkadot>(relay_origin_assertions);
test.set_assertion::<AssetHubPolkadot>(para_dest_assertions);
test.set_dispatchable::<Polkadot>(relay_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
// TODO: Uncomment when https://github.com/paritytech/polkadot/pull/7424 is merged
// Right now it is failing in the Relay Chain with a
// `messageQueue.ProcessingFailed` event `error: Unsupported`.
// The reason is the `Weigher` in `pallet_xcm` is not properly calculating the `remote_weight`
// and it cause an `Overweight` error in `AllowTopLevelPaidExecutionFrom` barrier
// /// Teleport of native asset from System Parachains to the Relay Chain
// /// should work when there is enough balance in Relay Chain's `CheckAccount`
// #[test]
// fn teleport_native_assets_back_from_system_para_to_relay_works() {
// // Dependency - Relay Chain's `CheckAccount` should have enough balance
// teleport_native_assets_from_relay_to_system_para_works();
// // Init values for Relay Chain
// let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
// let test_args = TestContext {
// sender: AssetHubPolkadotSender::get(),
// receiver: PolkadotReceiver::get(),
// args: get_para_dispatch_args(amount_to_send),
// };
// let mut test = SystemParaToRelayTest::new(test_args);
// let sender_balance_before = test.sender.balance;
// let receiver_balance_before = test.receiver.balance;
// test.set_assertion::<AssetHubPolkadot>(para_origin_assertions);
// test.set_assertion::<Polkadot>(relay_dest_assertions);
// test.set_dispatchable::<AssetHubPolkadot>(system_para_teleport_assets);
// test.assert();
// let sender_balance_after = test.sender.balance;
// let receiver_balance_after = test.receiver.balance;
// // Sender's balance is reduced
// assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// // Receiver's balance is increased
// assert!(receiver_balance_after > receiver_balance_before);
// }
// /// Teleport of native asset from System Parachain to Relay Chain
// /// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount`
// #[test]
// fn teleport_native_assets_from_system_para_to_relay_fails() {
// // Init values for Relay Chain
// let amount_to_send: Balance = ASSET_HUB_POLKADOT_ED * 1000;
// let assets = (Parent, amount_to_send).into();
//
// let test_args = TestContext {
// sender: AssetHubPolkadotSender::get(),
// receiver: PolkadotReceiver::get(),
// args: system_para_test_args(amount_to_send),
// assets,
// None
// };
// let mut test = SystemParaToRelayTest::new(test_args);
// let sender_balance_before = test.sender.balance;
// let receiver_balance_before = test.receiver.balance;
// test.set_assertion::<AssetHubPolkadot>(para_origin_assertions);
// test.set_assertion::<Polkadot>(relay_dest_assertions);
// test.set_dispatchable::<AssetHubPolkadot>(system_para_teleport_assets);
// test.assert();
// let sender_balance_after = test.sender.balance;
// let receiver_balance_after = test.receiver.balance;
// // Sender's balance is reduced
// assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// // Receiver's balance does not change
// assert_eq!(receiver_balance_after, receiver_balance_before);
// }
@@ -1,74 +0,0 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
#[test]
fn transact_sudo_from_relay_to_assets_para() {
// Init tests variables
// Call to be executed in Assets Parachain
const ASSET_ID: u32 = 1;
let call = <AssetHubPolkadot as Para>::RuntimeCall::Assets(pallet_assets::Call::<
<AssetHubPolkadot as Para>::Runtime,
Instance1,
>::force_create {
id: ASSET_ID.into(),
is_sufficient: true,
min_balance: 1000,
owner: AssetHubPolkadotSender::get().into(),
})
.encode()
.into();
// XcmPallet send arguments
let sudo_origin = <Polkadot as Relay>::RuntimeOrigin::root();
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(AssetHubPolkadot::para_id()).into();
let weight_limit = WeightLimit::Unlimited;
let require_weight_at_most = Weight::from_parts(1000000000, 200000);
let origin_kind = OriginKind::Superuser;
let check_origin = None;
let xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit, check_origin },
Transact { require_weight_at_most, origin_kind, call },
]));
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::send(
sudo_origin,
bx!(assets_para_destination),
bx!(xcm),
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubPolkadot::execute_with(|| {
assert!(<AssetHubPolkadot as AssetHubPolkadotPallet>::Assets::asset_exists(ASSET_ID));
});
}
@@ -24,15 +24,16 @@ polkadot-core-primitives = { default-features = false, git = "https://github.com
polkadot-parachain = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" }
westend-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
pallet-xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
parachains-common = { path = "../../../../common" }
penpal-runtime = { path = "../../../../runtimes/testing/penpal" }
asset-hub-westend-runtime = { path = "../../../../runtimes/assets/asset-hub-westend" }
cumulus-pallet-dmp-queue = { path = "../../../../../pallets/dmp-queue" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../pallets/xcmp-queue" }
cumulus-pallet-parachain-system = { path = "../../../../../pallets/parachain-system" }
# Local
xcm-emulator = { default-features = false, path = "../../../../../xcm/xcm-emulator" }
@@ -16,31 +16,86 @@
pub use codec::Encode;
pub use frame_support::{
assert_ok, instances::Instance1, pallet_prelude::Weight, traits::fungibles::Inspect,
assert_err, assert_ok,
instances::{Instance1, Instance2},
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError, MultiAddress},
traits::{fungibles::Inspect, OriginTrait},
BoundedVec,
};
pub use integration_tests_common::{
constants::{
accounts::{ALICE, BOB},
polkadot::ED as POLKADOT_ED,
asset_hub_westend::ED as ASSET_HUB_WESTEND_ED,
westend::ED as WESTEND_ED,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
},
AccountId, AssetHubWestend, AssetHubWestendPallet, AssetHubWestendReceiver,
AssetHubWestendSender, Collectives, CollectivesPallet, CollectivesReceiver, CollectivesSender,
PenpalWestend, PenpalWestendPallet, PenpalWestendReceiver, PenpalWestendSender, Westend,
lazy_static::lazy_static,
xcm_transact_paid_execution, xcm_transact_unpaid_execution, AssetHubWestend,
AssetHubWestendPallet, AssetHubWestendReceiver, AssetHubWestendSender, Collectives,
CollectivesPallet, CollectivesReceiver, CollectivesSender, PenpalWestendA,
PenpalWestendAPallet, PenpalWestendAReceiver, PenpalWestendASender, Westend, WestendMockNet,
WestendPallet, WestendReceiver, WestendSender,
};
pub use parachains_common::{AccountId, Balance};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use polkadot_parachain::primitives::{HrmpChannelId, Id};
pub use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId};
pub use xcm::{
prelude::*,
v3::{
Error,
NetworkId::{Kusama as KusamaId, Polkadot as PolkadotId},
},
v3::{Error, NetworkId::Westend as WestendId},
DoubleEncoded,
};
pub use xcm_emulator::{
assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold,
Parachain as Para, RelayChain as Relay, TestExt,
AccountId32Junction, Chain, ParaId, Parachain as Para, RelayChain as Relay, Test, TestArgs,
TestContext, TestExt, TestExternalities,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
// `Assets` pallet index
pub const ASSETS_PALLET_ID: u8 = 50;
pub type RelayToSystemParaTest = Test<Westend, AssetHubWestend>;
pub type SystemParaToRelayTest = Test<AssetHubWestend, Westend>;
pub type SystemParaToParaTest = Test<AssetHubWestend, PenpalWestendA>;
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
pub fn relay_test_args(amount: Balance) -> TestArgs {
TestArgs {
dest: Westend::child_location_of(AssetHubWestend::para_id()),
beneficiary: AccountId32Junction {
network: None,
id: AssetHubWestendReceiver::get().into(),
}
.into(),
amount,
assets: (Here, amount).into(),
asset_id: None,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests
pub fn system_para_test_args(
dest: MultiLocation,
beneficiary_id: AccountId32,
amount: Balance,
assets: MultiAssets,
asset_id: Option<u32>,
) -> TestArgs {
TestArgs {
dest,
beneficiary: AccountId32Junction { network: None, id: beneficiary_id.into() }.into(),
amount,
assets,
asset_id,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
#[cfg(test)]
mod tests;
@@ -15,6 +15,7 @@
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
mod reserve_transfer;
mod send;
mod set_xcm_versions;
mod swap;
mod teleport;
mod transact;
@@ -16,66 +16,395 @@
use crate::*;
#[test]
fn reserve_transfer_native_asset_from_relay_to_assets() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Westend::account_data_of(WestendSender::get()).free;
let para_receiver_balance_before =
AssetHubWestend::account_data_of(AssetHubWestendReceiver::get()).free;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
let origin = <Westend as Relay>::RuntimeOrigin::signed(WestendSender::get());
let assets_para_destination: VersionedMultiLocation =
Westend::child_location_of(AssetHubWestend::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: AssetHubWestendReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(629_384_000, 6_196)));
// Send XCM message from Relay Chain
Westend::execute_with(|| {
assert_ok!(<Westend as WestendPallet>::XcmPallet::limited_reserve_transfer_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Westend as Relay>::RuntimeEvent;
assert_expected_events!(
Westend,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(629_384_000, 6196), *weight),
},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Para>::RuntimeEvent;
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward {
outcome: Outcome::Incomplete(_, Error::UntrustedReserveLocation),
..
}) => {},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Westend::account_data_of(WestendSender::get()).free;
let para_sender_balance_after =
AssetHubWestend::account_data_of(AssetHubWestendReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert_eq!(para_sender_balance_after, para_receiver_balance_before);
assert_expected_events!(
Westend,
vec![
// Amount to reserve transfer is transferred to System Parachain's Sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => {
from: *from == t.sender.account_id,
to: *to == Westend::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_dest_assertions_incomplete(_t: RelayToSystemParaTest) {
AssetHubWestend::assert_dmp_queue_incomplete(
Some(Weight::from_parts(1_000_000_000, 0)),
Some(Error::UntrustedReserveLocation),
);
}
fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) {
AssetHubWestend::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier))
}
fn system_para_to_para_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
676_119_000,
6196,
)));
assert_expected_events!(
AssetHubWestend,
vec![
// Amount to reserve transfer is transferred to Parachain's Sovereing account
RuntimeEvent::Balances(
pallet_balances::Event::Transfer { from, to, amount }
) => {
from: *from == t.sender.account_id,
to: *to == AssetHubWestend::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
676_119_000,
6196,
)));
assert_expected_events!(
AssetHubWestend,
vec![
// Amount to reserve transfer is transferred to Parachain's Sovereing account
RuntimeEvent::Assets(
pallet_assets::Event::Transferred { asset_id, from, to, amount }
) => {
asset_id: *asset_id == ASSET_ID,
from: *from == t.sender.account_id,
to: *to == AssetHubWestend::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Westend as WestendPallet>::XcmPallet::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Westend as WestendPallet>::XcmPallet::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::reserve_transfer_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
#[test]
fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000;
let test_args = TestContext {
sender: WestendSender::get(),
receiver: AssetHubWestendReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Westend>(relay_origin_assertions);
test.set_assertion::<AssetHubWestend>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Westend>(relay_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shoudln't work
#[test]
fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() {
// Init values for System Parachain
let destination = AssetHubWestend::parent_location();
let beneficiary_id = WestendReceiver::get();
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: WestendReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubWestend>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubWestend>(system_para_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
#[test]
fn reserve_transfer_native_asset_from_relay_to_system_para_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000;
let test_args = TestContext {
sender: WestendSender::get(),
receiver: AssetHubWestendReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Westend>(relay_origin_assertions);
test.set_assertion::<AssetHubWestend>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Westend>(relay_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work
#[test]
fn reserve_transfer_native_asset_from_system_para_to_relay_fails() {
// Init values for System Parachain
let destination = AssetHubWestend::parent_location();
let beneficiary_id = WestendReceiver::get();
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: WestendReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubWestend>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubWestend>(system_para_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before, sender_balance_after);
assert_eq!(receiver_balance_before, receiver_balance_after);
}
/// Limited Reserve Transfers of native asset from System Parachain to Parachain should work
#[test]
fn limited_reserve_transfer_native_asset_from_system_para_to_para() {
// Init values for System Parachain
let destination = AssetHubWestend::sibling_location_of(PenpalWestendA::para_id());
let beneficiary_id = PenpalWestendAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: PenpalWestendAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
test.set_assertion::<AssetHubWestend>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve transfers
}
/// Reserve Transfers of native asset from System Parachain to Parachain should work
#[test]
fn reserve_transfer_native_asset_from_system_para_to_para() {
// Init values for System Parachain
let destination = AssetHubWestend::sibling_location_of(PenpalWestendA::para_id());
let beneficiary_id = PenpalWestendAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: PenpalWestendAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
test.set_assertion::<AssetHubWestend>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubWestend>(system_para_to_para_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve transfers
}
/// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work
#[test]
fn limited_reserve_transfer_asset_from_system_para_to_para() {
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
AssetHubWestend::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubWestendSender::get(),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubWestend::sibling_location_of(PenpalWestendA::para_id());
let beneficiary_id = PenpalWestendAReceiver::get();
let amount_to_send = ASSET_MIN_BALANCE * 1000;
let assets =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
.into();
let system_para_test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: PenpalWestendAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
system_para_test.set_assertion::<AssetHubWestend>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
system_para_test.assert();
}
/// Reserve Transfers of a local asset from System Parachain to Parachain should work
#[test]
fn reserve_transfer_asset_from_system_para_to_para() {
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
AssetHubWestend::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubWestendSender::get(),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubWestend::sibling_location_of(PenpalWestendA::para_id());
let beneficiary_id = PenpalWestendAReceiver::get();
let amount_to_send = ASSET_MIN_BALANCE * 1000;
let assets =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
.into();
let system_para_test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: PenpalWestendAReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
system_para_test.set_assertion::<AssetHubWestend>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubWestend>(system_para_to_para_reserve_transfer_assets);
system_para_test.assert();
}
@@ -0,0 +1,141 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser` and signer is `sudo`
#[test]
fn send_transact_sudo_from_relay_to_system_para_works() {
// Init tests variables
let root_origin = <Westend as Chain>::RuntimeOrigin::root();
let system_para_destination = Westend::child_location_of(AssetHubWestend::para_id()).into();
let asset_owner: AccountId = AssetHubWestendSender::get().into();
let xcm = AssetHubWestend::force_create_asset_xcm(
OriginKind::Superuser,
ASSET_ID,
asset_owner.clone(),
true,
1000,
);
// Send XCM message from Relay Chain
Westend::execute_with(|| {
assert_ok!(<Westend as WestendPallet>::XcmPallet::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
Westend::assert_xcm_pallet_sent();
});
// Receive XCM message in Assets Parachain
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(
1_019_445_000,
200_000,
)));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::Assets(pallet_assets::Event::ForceCreated { asset_id, owner }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == asset_owner,
},
]
);
assert!(<AssetHubWestend as AssetHubWestendPallet>::Assets::asset_exists(ASSET_ID));
});
}
/// Parachain should be able to send XCM paying its fee with sufficient asset
/// in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
let para_sovereign_account = AssetHubWestend::sovereign_account_id_of(
AssetHubWestend::sibling_location_of(PenpalWestendA::para_id()),
);
// Force create and mint assets for Parachain's sovereign account
AssetHubWestend::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
ASSET_MIN_BALANCE * 1000000000,
);
// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubWestend::force_create_asset_call(
ASSET_ID,
para_sovereign_account.clone(),
true,
ASSET_MIN_BALANCE,
);
let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset =
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), fee_amount).into();
let root_origin = <PenpalWestendA as Chain>::RuntimeOrigin::root();
let system_para_destination =
PenpalWestendA::sibling_location_of(AssetHubWestend::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);
PenpalWestendA::execute_with(|| {
assert_ok!(<PenpalWestendA as PenpalWestendAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
AssetHubWestend::assert_xcm_pallet_sent();
});
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts(
2_176_414_000,
203_593,
)));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account,
balance: *balance == fee_amount,
},
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == ASSET_ID,
},
]
);
});
}
@@ -0,0 +1,97 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
#[test]
fn relay_sets_system_para_xcm_supported_version() {
// Init tests variables
let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
let system_para_destination: MultiLocation =
Westend::child_location_of(AssetHubWestend::para_id());
// Relay Chain sets supported version for Asset Parachain
Westend::execute_with(|| {
assert_ok!(<Westend as WestendPallet>::XcmPallet::force_xcm_version(
sudo_origin,
bx!(system_para_destination),
XCM_V3
));
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
assert_expected_events!(
Westend,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::SupportedVersionChanged {
location,
version: XCM_V3
}) => { location: *location == system_para_destination, },
]
);
});
}
#[test]
fn system_para_sets_relay_xcm_supported_version() {
// Init test variables
let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
let parent_location = AssetHubWestend::parent_location();
let system_para_destination: VersionedMultiLocation =
Westend::child_location_of(AssetHubWestend::para_id()).into();
let call = <AssetHubWestend as Chain>::RuntimeCall::PolkadotXcm(pallet_xcm::Call::<
<AssetHubWestend as Chain>::Runtime,
>::force_xcm_version {
location: bx!(parent_location),
version: XCM_V3,
})
.encode()
.into();
let origin_kind = OriginKind::Superuser;
let xcm = xcm_transact_unpaid_execution(call, origin_kind);
// System Parachain sets supported version for Relay Chain throught it
Westend::execute_with(|| {
assert_ok!(<Westend as WestendPallet>::XcmPallet::send(
sudo_origin,
bx!(system_para_destination),
bx!(xcm),
));
Westend::assert_xcm_pallet_sent();
});
// System Parachain receive the XCM message
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(
1_019_210_000,
200_000,
)));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::SupportedVersionChanged {
location,
version: XCM_V3
}) => { location: *location == parent_location, },
]
);
});
}
@@ -1,23 +1,18 @@
use crate::*;
use frame_support::{instances::Instance2, BoundedVec};
use sp_runtime::{DispatchError, ModuleError};
use xcm_emulator::Parachain;
#[test]
fn swap_locally_on_chain_using_local_assets() {
const ASSET_ID: u32 = 1;
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
let asset_one = Box::new(MultiLocation {
parents: 0,
interior: X2(PalletInstance(50), GeneralIndex(ASSET_ID.into())),
interior: X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())),
});
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Parachain>::RuntimeEvent;
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::create(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
1000,
@@ -25,14 +20,14 @@ fn swap_locally_on_chain_using_local_assets() {
assert!(<AssetHubWestend as AssetHubWestendPallet>::Assets::asset_exists(ASSET_ID));
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
3_000_000_000_000,
));
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
asset_one.clone(),
));
@@ -45,7 +40,7 @@ fn swap_locally_on_chain_using_local_assets() {
);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
asset_one.clone(),
1_000_000_000_000,
@@ -65,7 +60,7 @@ fn swap_locally_on_chain_using_local_assets() {
let path = BoundedVec::<_, _>::truncate_from(vec![asset_native.clone(), asset_one.clone()]);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100,
1,
@@ -84,7 +79,7 @@ fn swap_locally_on_chain_using_local_assets() {
);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native,
asset_one,
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
@@ -99,14 +94,13 @@ fn swap_locally_on_chain_using_local_assets() {
fn swap_locally_on_chain_using_foreign_assets() {
use frame_support::weights::WeightToFee;
const ASSET_ID: u32 = 1;
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
let foreign_asset1_at_asset_hub_westend = Box::new(MultiLocation {
parents: 1,
interior: X3(
Parachain(PenpalWestend::para_id().into()),
PalletInstance(50),
Parachain(PenpalWestendA::para_id().into()),
PalletInstance(ASSETS_PALLET_ID),
GeneralIndex(ASSET_ID.into()),
),
});
@@ -116,18 +110,18 @@ fn swap_locally_on_chain_using_foreign_assets() {
.into();
let penpal_location =
MultiLocation { parents: 1, interior: X1(Parachain(PenpalWestend::para_id().into())) };
MultiLocation { parents: 1, interior: X1(Parachain(PenpalWestendA::para_id().into())) };
// 1. Create asset on penpal:
PenpalWestend::execute_with(|| {
assert_ok!(<PenpalWestend as PenpalWestendPallet>::Assets::create(
<PenpalWestend as Parachain>::RuntimeOrigin::signed(PenpalWestendSender::get()),
PenpalWestendA::execute_with(|| {
assert_ok!(<PenpalWestendA as PenpalWestendAPallet>::Assets::create(
<PenpalWestendA as Chain>::RuntimeOrigin::signed(PenpalWestendASender::get()),
ASSET_ID.into(),
PenpalWestendSender::get().into(),
PenpalWestendASender::get().into(),
1000,
));
assert!(<PenpalWestend as PenpalWestendPallet>::Assets::asset_exists(ASSET_ID));
assert!(<PenpalWestendA as PenpalWestendAPallet>::Assets::asset_exists(ASSET_ID));
});
// 2. Create foreign asset on asset_hub_westend:
@@ -137,21 +131,21 @@ fn swap_locally_on_chain_using_foreign_assets() {
let sov_penpal_on_asset_hub_westend = AssetHubWestend::sovereign_account_id_of(penpal_location);
AssetHubWestend::fund_accounts(vec![
(AssetHubWestendSender::get(), 5_000_000), // An account to swap dot for something else.
(sov_penpal_on_asset_hub_westend.clone(), 1000_000_000_000_000_000),
(AssetHubWestendSender::get().into(), 5_000_000 * WESTEND_ED),
(sov_penpal_on_asset_hub_westend.clone().into(), 1000_000_000_000_000_000 * WESTEND_ED),
]);
let sov_penpal_on_asset_hub_westend_as_location: MultiLocation = MultiLocation {
parents: 0,
interior: X1(AccountId32 {
interior: X1(AccountId32Junction {
network: None,
id: sov_penpal_on_asset_hub_westend.clone().into(),
}),
};
let call_foreign_assets_create =
<AssetHubWestend as Para>::RuntimeCall::ForeignAssets(pallet_assets::Call::<
<AssetHubWestend as Para>::Runtime,
<AssetHubWestend as Chain>::RuntimeCall::ForeignAssets(pallet_assets::Call::<
<AssetHubWestend as Chain>::Runtime,
Instance2,
>::create {
id: *foreign_asset1_at_asset_hub_westend,
@@ -183,18 +177,18 @@ fn swap_locally_on_chain_using_foreign_assets() {
]));
// Send XCM message from penpal => asset_hub_westend
let sudo_penpal_origin = <PenpalWestend as Parachain>::RuntimeOrigin::root();
PenpalWestend::execute_with(|| {
assert_ok!(<PenpalWestend as PenpalWestendPallet>::PolkadotXcm::send(
let sudo_penpal_origin = <PenpalWestendA as Chain>::RuntimeOrigin::root();
PenpalWestendA::execute_with(|| {
assert_ok!(<PenpalWestendA as PenpalWestendAPallet>::PolkadotXcm::send(
sudo_penpal_origin.clone(),
bx!(assets_para_destination.clone()),
bx!(xcm),
));
type RuntimeEvent = <PenpalWestend as Parachain>::RuntimeEvent;
type RuntimeEvent = <PenpalWestendA as Chain>::RuntimeEvent;
assert_expected_events!(
PenpalWestend,
PenpalWestendA,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
]
@@ -212,10 +206,10 @@ fn swap_locally_on_chain_using_foreign_assets() {
// (While it might be nice to use batch,
// currently that's disabled due to safe call filters.)
type RuntimeEvent = <AssetHubWestend as Parachain>::RuntimeEvent;
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
// 3. Mint foreign asset (in reality this should be a teleport or some such)
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone().into()
),
*foreign_asset1_at_asset_hub_westend,
@@ -232,7 +226,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
// 4. Create pool:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
foreign_asset1_at_asset_hub_westend.clone(),
));
@@ -246,7 +240,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
// 5. Add liquidity:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone()
),
asset_native.clone(),
@@ -274,7 +268,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
]);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100000,
1000,
@@ -294,7 +288,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
// 7. Remove liquidity
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
<AssetHubWestend as Chain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone()
),
asset_native,
@@ -309,8 +303,6 @@ fn swap_locally_on_chain_using_foreign_assets() {
#[test]
fn cannot_create_pool_from_pool_assets() {
const ASSET_ID: u32 = 1;
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
let mut asset_one = asset_hub_westend_runtime::xcm_config::PoolAssetsPalletLocation::get();
asset_one.append_with(GeneralIndex(ASSET_ID.into())).expect("pool assets");
@@ -319,7 +311,7 @@ fn cannot_create_pool_from_pool_assets() {
let pool_owner_account_id = asset_hub_westend_runtime::AssetConversionOrigin::get();
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::create(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(pool_owner_account_id.clone()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(pool_owner_account_id.clone()),
ASSET_ID.into(),
pool_owner_account_id.clone().into(),
1000,
@@ -327,7 +319,7 @@ fn cannot_create_pool_from_pool_assets() {
assert!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::asset_exists(ASSET_ID));
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(pool_owner_account_id),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(pool_owner_account_id),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
3_000_000_000_000,
@@ -335,7 +327,7 @@ fn cannot_create_pool_from_pool_assets() {
assert_matches::assert_matches!(
<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
Box::new(asset_one),
),
@@ -16,63 +16,347 @@
use crate::*;
#[test]
fn teleport_native_assets_from_relay_to_assets_para() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Westend::account_data_of(WestendSender::get()).free;
let para_receiver_balance_before =
AssetHubWestend::account_data_of(AssetHubWestendReceiver::get()).free;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
let origin = <Westend as Relay>::RuntimeOrigin::signed(WestendSender::get());
let assets_para_destination: VersionedMultiLocation =
Westend::child_location_of(AssetHubWestend::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: AssetHubWestendReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(632_207_000, 7_186)));
// Send XCM message from Relay Chain
Westend::execute_with(|| {
assert_ok!(<Westend as WestendPallet>::XcmPallet::limited_teleport_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Westend as Relay>::RuntimeEvent;
assert_expected_events!(
Westend,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted { outcome: Outcome::Complete { .. } }) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Para>::RuntimeEvent;
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == AssetHubWestendReceiver::get().into(),
},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Westend::account_data_of(WestendSender::get()).free;
let para_sender_balance_after =
AssetHubWestend::account_data_of(AssetHubWestendReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert!(para_sender_balance_after > para_receiver_balance_before);
assert_expected_events!(
Westend,
vec![
// Amount to teleport is withdrawn from Sender
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
},
// Amount to teleport is deposited in Relay's `CheckAccount`
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, amount }) => {
who: *who == <Westend as WestendPallet>::XcmPallet::check_account(),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_dest_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
Westend::assert_ump_queue_processed(
true,
Some(AssetHubWestend::para_id()),
Some(Weight::from_parts(308_222_000, 7_186)),
);
assert_expected_events!(
Westend,
vec![
// Amount is witdrawn from Relay Chain's `CheckAccount`
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == <Westend as WestendPallet>::XcmPallet::check_account(),
amount: *amount == t.args.amount,
},
// Amount minus fees are deposited in Receiver's account
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == t.receiver.account_id,
},
]
);
}
fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
Westend::assert_ump_queue_processed(
false,
Some(AssetHubWestend::para_id()),
Some(Weight::from_parts(148_705_000, 3_593)),
);
}
fn para_origin_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
533_910_000,
7167,
)));
AssetHubWestend::assert_parachain_system_ump_sent();
assert_expected_events!(
AssetHubWestend,
vec![
// Amount is withdrawn from Sender's account
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == t.sender.account_id,
amount: *amount == t.args.amount,
},
]
);
}
fn para_dest_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(164_733_000, 0)));
assert_expected_events!(
AssetHubWestend,
vec![
// Amount minus fees are deposited in Receiver's account
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == t.receiver.account_id,
},
]
);
}
fn relay_limited_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Westend as WestendPallet>::XcmPallet::limited_teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
fn relay_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Westend as WestendPallet>::XcmPallet::teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
)
}
fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_teleport_assets(
t.signed_origin,
bx!(t.args.dest.into()),
bx!(t.args.beneficiary.into()),
bx!(t.args.assets.into()),
t.args.fee_asset_item,
t.args.weight_limit,
)
}
// TODO: Uncomment when https://github.com/paritytech/polkadot/pull/7424 is merged
// fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
// <AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::teleport_assets(
// t.signed_origin,
// bx!(t.args.dest),
// bx!(t.args.beneficiary),
// bx!(t.args.assets),
// t.args.fee_asset_item,
// )
// }
/// Limited Teleport of native asset from Relay Chain to the System Parachain should work
#[test]
fn limited_teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000;
let test_args = TestContext {
sender: WestendSender::get(),
receiver: AssetHubWestendReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Westend>(relay_origin_assertions);
test.set_assertion::<AssetHubWestend>(para_dest_assertions);
test.set_dispatchable::<Westend>(relay_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
/// Limited Teleport of native asset from System Parachain to Relay Chain
/// should work when there is enough balance in Relay Chain's `CheckAccount`
#[test]
fn limited_teleport_native_assets_back_from_system_para_to_relay_works() {
// Dependency - Relay Chain's `CheckAccount` should have enough balance
limited_teleport_native_assets_from_relay_to_system_para_works();
// Init values for Relay Chain
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
let destination = AssetHubWestend::parent_location();
let beneficiary_id = WestendReceiver::get();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: WestendReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubWestend>(para_origin_assertions);
test.set_assertion::<Westend>(relay_dest_assertions);
test.set_dispatchable::<AssetHubWestend>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
/// Limited Teleport of native asset from System Parachain to Relay Chain
/// should't work when there is not enough balance in Relay Chain's `CheckAccount`
#[test]
fn limited_teleport_native_assets_from_system_para_to_relay_fails() {
// Init values for Relay Chain
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
let destination = AssetHubWestend::parent_location().into();
let beneficiary_id = WestendReceiver::get().into();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubWestendSender::get(),
receiver: WestendReceiver::get(),
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
};
let mut test = SystemParaToRelayTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<AssetHubWestend>(para_origin_assertions);
test.set_assertion::<Westend>(relay_dest_assertions_fail);
test.set_dispatchable::<AssetHubWestend>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance does not change
assert_eq!(receiver_balance_after, receiver_balance_before);
}
/// Teleport of native asset from Relay Chain to the System Parachain should work
#[test]
fn teleport_native_assets_from_relay_to_system_para_works() {
// Init values for Relay Chain
let amount_to_send: Balance = WESTEND_ED * 1000;
let test_args = TestContext {
sender: WestendSender::get(),
receiver: AssetHubWestendReceiver::get(),
args: relay_test_args(amount_to_send),
};
let mut test = RelayToSystemParaTest::new(test_args);
let sender_balance_before = test.sender.balance;
let receiver_balance_before = test.receiver.balance;
test.set_assertion::<Westend>(relay_origin_assertions);
test.set_assertion::<AssetHubWestend>(para_dest_assertions);
test.set_dispatchable::<Westend>(relay_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
// TODO: Uncomment when https://github.com/paritytech/polkadot/pull/7424 is merged
// Right now it is failing in the Relay Chain with a
// `messageQueue.ProcessingFailed` event `error: Unsupported`.
// The reason is the `Weigher` in `pallet_xcm` is not properly calculating the `remote_weight`
// and it cause an `Overweight` error in `AllowTopLevelPaidExecutionFrom` barrier
// /// Teleport of native asset from System Parachains to the Relay Chain
// /// should work when there is enough balance in Relay Chain's `CheckAccount`
// #[test]
// fn teleport_native_assets_back_from_system_para_to_relay_works() {
// // Dependency - Relay Chain's `CheckAccount` should have enough balance
// teleport_native_assets_from_relay_to_system_para_works();
// // Init values for Relay Chain
// let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
// let test_args = TestContext {
// sender: AssetHubWestendSender::get(),
// receiver: WestendReceiver::get(),
// args: get_para_dispatch_args(amount_to_send),
// };
// let mut test = SystemParaToRelayTest::new(test_args);
// let sender_balance_before = test.sender.balance;
// let receiver_balance_before = test.receiver.balance;
// test.set_assertion::<AssetHubWestend>(para_origin_assertions);
// test.set_assertion::<Westend>(relay_dest_assertions);
// test.set_dispatchable::<AssetHubWestend>(system_para_teleport_assets);
// test.assert();
// let sender_balance_after = test.sender.balance;
// let receiver_balance_after = test.receiver.balance;
// // Sender's balance is reduced
// assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// // Receiver's balance is increased
// assert!(receiver_balance_after > receiver_balance_before);
// }
// /// Teleport of native asset from System Parachain to Relay Chain
// /// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount`
// #[test]
// fn teleport_native_assets_from_system_para_to_relay_fails() {
// // Init values for Relay Chain
// let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
// let assets = (Parent, amount_to_send).into();
//
// let test_args = TestContext {
// sender: AssetHubWestendSender::get(),
// receiver: WestendReceiver::get(),
// args: system_para_test_args(amount_to_send),
// assets,
// None
// };
// let mut test = SystemParaToRelayTest::new(test_args);
// let sender_balance_before = test.sender.balance;
// let receiver_balance_before = test.receiver.balance;
// test.set_assertion::<AssetHubWestend>(para_origin_assertions);
// test.set_assertion::<Westend>(relay_dest_assertions);
// test.set_dispatchable::<AssetHubWestend>(system_para_teleport_assets);
// test.assert();
// let sender_balance_after = test.sender.balance;
// let receiver_balance_after = test.receiver.balance;
// // Sender's balance is reduced
// assert_eq!(sender_balance_before - amount_to_send, sender_balance_after);
// // Receiver's balance does not change
// assert_eq!(receiver_balance_after, receiver_balance_before);
// }
@@ -1,74 +0,0 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus 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.
// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::*;
#[test]
fn transact_sudo_from_relay_to_assets_para() {
// Init tests variables
// Call to be executed in Assets Parachain
const ASSET_ID: u32 = 1;
let call = <AssetHubWestend as Para>::RuntimeCall::Assets(pallet_assets::Call::<
<AssetHubWestend as Para>::Runtime,
Instance1,
>::force_create {
id: ASSET_ID.into(),
is_sufficient: true,
min_balance: 1000,
owner: AssetHubWestendSender::get().into(),
})
.encode()
.into();
// XcmPallet send arguments
let sudo_origin = <Westend as Relay>::RuntimeOrigin::root();
let assets_para_destination: VersionedMultiLocation =
Westend::child_location_of(AssetHubWestend::para_id()).into();
let weight_limit = WeightLimit::Unlimited;
let require_weight_at_most = Weight::from_parts(1000000000, 200000);
let origin_kind = OriginKind::Superuser;
let check_origin = None;
let xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit, check_origin },
Transact { require_weight_at_most, origin_kind, call },
]));
// Send XCM message from Relay Chain
Westend::execute_with(|| {
assert_ok!(<Westend as WestendPallet>::XcmPallet::send(
sudo_origin,
bx!(assets_para_destination),
bx!(xcm),
));
type RuntimeEvent = <Westend as Relay>::RuntimeEvent;
assert_expected_events!(
Westend,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubWestend::execute_with(|| {
assert!(<AssetHubWestend as AssetHubWestendPallet>::Assets::asset_exists(ASSET_ID));
});
}
@@ -29,7 +29,7 @@ pallet-xcm = { default-features = false, git = "https://github.com/paritytech/po
# Cumulus
parachains-common = { path = "../../../../common" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../pallets/xcmp-queue" }
bridge-hub-rococo-runtime = { path = "../../../../runtimes/bridge-hubs/bridge-hub-rococo" }
cumulus-pallet-parachain-system = { path = "../../../../../pallets/parachain-system" }
pallet-bridge-messages = { default-features = false, path = "../../../../../bridges/modules/messages" }
bp-messages = { default-features = false, path = "../../../../../bridges/primitives/messages" }
@@ -16,33 +16,73 @@
pub use bp_messages::LaneId;
pub use codec::Encode;
pub use frame_support::{assert_ok, pallet_prelude::Weight};
pub use frame_support::{
assert_err, assert_ok,
instances::Instance1,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult, MultiAddress},
traits::{fungibles::Inspect, OriginTrait},
};
pub use integration_tests_common::{
constants::{
accounts::{ALICE, BOB},
rococo::{ED as ROCOCO_ED, ED as WOCOCO_ED},
asset_hub_kusama::ED as ASSET_HUB_ROCOCO_ED,
kusama::ED as ROCOCO_ED,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
},
AccountId, AssetHubWococo, BridgeHubPolkadot, BridgeHubPolkadotPallet,
BridgeHubPolkadotReceiver, BridgeHubPolkadotSender, BridgeHubRococo, BridgeHubRococoPallet,
BridgeHubRococoReceiver, BridgeHubRococoSender, BridgeHubWococo, Collectives,
CollectivesPallet, CollectivesReceiver, CollectivesSender, Kusama, KusamaPallet,
PenpalPolkadot, PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot, PolkadotMockNet,
PolkadotPallet, PolkadotReceiver, PolkadotSender, Rococo, RococoMockNet, RococoPallet,
RococoReceiver, RococoSender,
lazy_static::lazy_static,
xcm_transact_paid_execution, xcm_transact_unpaid_execution, AssetHubRococo,
AssetHubRococoPallet, AssetHubRococoReceiver, AssetHubRococoSender, AssetHubWococo,
AssetHubWococoPallet, AssetHubWococoReceiver, AssetHubWococoSender, BridgeHubRococo,
BridgeHubRococoPallet, BridgeHubRococoReceiver, BridgeHubRococoSender, BridgeHubWococo,
BridgeHubWococoPallet, BridgeHubWococoReceiver, BridgeHubWococoSender, Collectives,
CollectivesPallet, CollectivesReceiver, CollectivesSender, PenpalRococoA, PenpalRococoAPallet,
PenpalRococoAReceiver, PenpalRococoASender, Rococo, RococoMockNet, RococoPallet,
RococoReceiver, RococoSender, Wococo, WococoMockNet, WococoPallet, WococoReceiver,
WococoSender,
};
// pub use polkadot_core_primitives::InboundDownwardMessage;
pub use parachains_common::{AccountId, Balance};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use polkadot_parachain::primitives::{HrmpChannelId, Id};
pub use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId};
pub use xcm::{
prelude::*,
v3::{
Error,
NetworkId::{Rococo as RococoId, Wococo as WococoId},
},
DoubleEncoded,
};
pub use xcm_emulator::{
assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold,
Parachain as Para, RelayChain as Relay, TestExt,
AccountId32Junction, Chain, ParaId, Parachain as Para, RelayChain as Relay, Test, TestArgs,
TestContext, TestExt, TestExternalities,
};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
pub const ASSETS_PALLET_ID: u8 = 50;
pub type RelayToSystemParaTest = Test<Rococo, AssetHubRococo>;
pub type SystemParaToRelayTest = Test<AssetHubRococo, Rococo>;
pub type SystemParaToParaTest = Test<AssetHubRococo, PenpalRococoA>;
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
pub fn relay_test_args(amount: Balance) -> TestArgs {
TestArgs {
dest: Rococo::child_location_of(AssetHubRococo::para_id()),
beneficiary: AccountId32Junction {
network: None,
id: AssetHubRococoReceiver::get().into(),
}
.into(),
amount,
assets: (Here, amount).into(),
asset_id: None,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
#[cfg(test)]
mod tests;
@@ -20,7 +20,7 @@ use crate::*;
fn example() {
// Init tests variables
// XcmPallet send arguments
let sudo_origin = <Rococo as Relay>::RuntimeOrigin::root();
let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into();
let weight_limit = WeightLimit::Unlimited;
let check_origin = None;
@@ -45,7 +45,7 @@ fn example() {
bx!(xcm),
));
type RuntimeEvent = <Rococo as Relay>::RuntimeEvent;
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
assert_expected_events!(
Rococo,
@@ -56,7 +56,7 @@ fn example() {
});
// Receive XCM message in Bridge Hub source Parachain
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Para>::RuntimeEvent;
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubRococo,
@@ -76,7 +76,7 @@ fn example() {
// Wococo GLobal Consensus
// Receive XCM message in Bridge Hub target Parachain
BridgeHubWococo::execute_with(|| {
type RuntimeEvent = <BridgeHubWococo as Para>::RuntimeEvent;
type RuntimeEvent = <BridgeHubWococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubWococo,
@@ -87,7 +87,7 @@ fn example() {
});
// Receive embeded XCM message within `ExportMessage` in Parachain destination
AssetHubWococo::execute_with(|| {
type RuntimeEvent = <AssetHubWococo as Para>::RuntimeEvent;
type RuntimeEvent = <AssetHubWococo as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubWococo,
@@ -5,7 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
description = "Polkadot Collectives parachain runtime integration tests based on xcm-emulator"
[dev-dependencies]
[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
# Substrate
@@ -31,6 +31,7 @@ pallet-xcm = { default-features = false, git = "https://github.com/paritytech/po
# Cumulus
parachains-common = { path = "../../../../common" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../pallets/xcmp-queue" }
cumulus-pallet-parachain-system = { path = "../../../../../pallets/parachain-system" }
collectives-polkadot-runtime = { path = "../../../../runtimes/collectives/collectives-polkadot" }
asset-hub-polkadot-runtime = { path = "../../../../runtimes/assets/asset-hub-polkadot" }
@@ -14,17 +14,88 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
//! Collectives Parachain integration tests based on xcm-emulator.
#![cfg(test)]
pub use frame_support::assert_ok;
pub use integration_tests_common::{
constants::accounts::ALICE, AccountId, AssetHubPolkadot as AssetHub,
AssetHubPolkadotPallet as AssetHubPallet, Collectives, CollectivesPallet, Polkadot,
PolkadotMockNet,
pub use codec::Encode;
pub use frame_support::{
assert_err, assert_ok,
instances::Instance1,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult, MultiAddress},
traits::{fungibles::Inspect, OriginTrait},
};
pub use integration_tests_common::{
constants::{
accounts::{ALICE, BOB},
asset_hub_polkadot::ED as ASSET_HUB_POLKADOT_ED,
polkadot::ED as POLKADOT_ED,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
},
lazy_static::lazy_static,
xcm_transact_paid_execution, xcm_transact_unpaid_execution, AssetHubPolkadot,
AssetHubPolkadotPallet, AssetHubPolkadotReceiver, AssetHubPolkadotSender, BridgeHubPolkadot,
BridgeHubPolkadotPallet, BridgeHubPolkadotReceiver, BridgeHubPolkadotSender, Collectives,
CollectivesPallet, CollectivesReceiver, CollectivesSender, PenpalPolkadotA,
PenpalPolkadotAPallet, PenpalPolkadotAReceiver, PenpalPolkadotASender, PenpalPolkadotB,
PenpalPolkadotBPallet, PenpalPolkadotBReceiver, PenpalPolkadotBSender, Polkadot,
PolkadotMockNet, PolkadotPallet, PolkadotReceiver, PolkadotSender,
};
pub use parachains_common::{AccountId, Balance};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use polkadot_parachain::primitives::{HrmpChannelId, Id};
pub use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId};
pub use xcm::{
prelude::*,
v3::{Error, NetworkId::Polkadot as PolkadotId},
DoubleEncoded,
};
pub use xcm_emulator::{
assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold,
AccountId32Junction, Chain, ParaId, Parachain as Para, RelayChain as Relay, Test, TestArgs,
TestContext, TestExt, TestExternalities,
};
pub use xcm::prelude::*;
pub use xcm_emulator::{assert_expected_events, Parachain};
pub const ASSET_ID: u32 = 1;
pub const ASSET_MIN_BALANCE: u128 = 1000;
pub const ASSETS_PALLET_ID: u8 = 50;
pub type RelayToSystemParaTest = Test<Polkadot, AssetHubPolkadot>;
pub type SystemParaToRelayTest = Test<AssetHubPolkadot, Polkadot>;
pub type SystemParaToParaTest = Test<AssetHubPolkadot, PenpalPolkadotA>;
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
pub fn relay_test_args(amount: Balance) -> TestArgs {
TestArgs {
dest: Polkadot::child_location_of(AssetHubPolkadot::para_id()),
beneficiary: AccountId32Junction {
network: None,
id: AssetHubPolkadotReceiver::get().into(),
}
.into(),
amount,
assets: (Here, amount).into(),
asset_id: None,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests
pub fn system_para_test_args(
dest: MultiLocation,
beneficiary_id: AccountId32,
amount: Balance,
assets: MultiAssets,
asset_id: Option<u32>,
) -> TestArgs {
TestArgs {
dest,
beneficiary: AccountId32Junction { network: None, id: beneficiary_id.into() }.into(),
amount,
assets,
asset_id,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
#[cfg(test)]
mod tests;
@@ -34,8 +34,8 @@ fn pay_salary() {
let pay_to = Polkadot::account_id_of(ALICE);
let pay_amount = 9000;
AssetHub::execute_with(|| {
type AssetHubAssets = <AssetHub as AssetHubPallet>::Assets;
AssetHubPolkadot::execute_with(|| {
type AssetHubAssets = <AssetHubPolkadot as AssetHubPolkadotPallet>::Assets;
assert_ok!(<AssetHubAssets as Create<_>>::create(
asset_id,
@@ -47,7 +47,7 @@ fn pay_salary() {
});
Collectives::execute_with(|| {
type RuntimeEvent = <Collectives as Parachain>::RuntimeEvent;
type RuntimeEvent = <Collectives as Chain>::RuntimeEvent;
assert_ok!(FellowshipSalaryPaymaster::pay(&pay_to, (), pay_amount));
assert_expected_events!(
@@ -58,11 +58,11 @@ fn pay_salary() {
);
});
AssetHub::execute_with(|| {
type RuntimeEvent = <AssetHub as Parachain>::RuntimeEvent;
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHub,
AssetHubPolkadot,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => {
asset_id: id == &asset_id,
@@ -7,6 +7,8 @@ description = "Common resources for integration testing with xcm-emulator"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
lazy_static = "1.4.0"
paste = "1.0.14"
# Substrate
grandpa = { package = "sc-consensus-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -20,6 +22,7 @@ sp-consensus-babe = { default-features = false, git = "https://github.com/parity
pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-staking = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-message-queue = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-im-online = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-primitives = { package = "sp-consensus-beefy", git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -54,6 +57,9 @@ bridge-hub-kusama-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-k
bridge-hub-polkadot-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-polkadot" }
bridge-hub-rococo-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-rococo" }
xcm-emulator = { default-features = false, path = "../../../../xcm/xcm-emulator" }
cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue" }
cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../pallets/xcmp-queue" }
cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system" }
bp-messages = { path = "../../../../bridges/primitives/messages"}
bp-runtime = { path = "../../../../bridges/primitives/runtime"}
pallet-bridge-messages = { path = "../../../../bridges/modules/messages" }
@@ -2,8 +2,12 @@ use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId;
use grandpa::AuthorityId as GrandpaId;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use parachains_common::{AccountId, AssetHubPolkadotAuraId, AuraId, Balance, BlockNumber};
use polkadot_parachain::primitives::{HeadData, ValidationCode};
use polkadot_primitives::{AssignmentId, ValidatorId};
use polkadot_runtime_parachains::configuration::HostConfiguration;
use polkadot_runtime_parachains::{
configuration::HostConfiguration,
paras::{ParaGenesisArgs, ParaKind},
};
use polkadot_service::chain_spec::get_authority_keys_from_seed_no_beefy;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId;
@@ -129,6 +133,13 @@ pub mod polkadot {
max_upward_message_size: 51200,
max_upward_message_num_per_candidate: 10,
max_downward_message_size: 51200,
hrmp_sender_deposit: 100_000_000_000,
hrmp_recipient_deposit: 100_000_000_000,
hrmp_channel_max_capacity: 1000,
hrmp_channel_max_message_size: 102400,
hrmp_channel_max_total_size: 102400,
hrmp_max_parachain_outbound_channels: 30,
hrmp_max_parachain_inbound_channels: 30,
..Default::default()
}
}
@@ -206,6 +217,41 @@ pub mod polkadot {
..Default::default()
},
configuration: polkadot_runtime::ConfigurationConfig { config: get_host_config() },
paras: polkadot_runtime::ParasConfig {
paras: vec![
(
asset_hub_polkadot::PARA_ID.into(),
ParaGenesisArgs {
genesis_head: HeadData::default(),
validation_code: ValidationCode(
asset_hub_polkadot_runtime::WASM_BINARY.unwrap().to_vec(),
),
para_kind: ParaKind::Parachain,
},
),
(
penpal::PARA_ID_A.into(),
ParaGenesisArgs {
genesis_head: HeadData::default(),
validation_code: ValidationCode(
penpal_runtime::WASM_BINARY.unwrap().to_vec(),
),
para_kind: ParaKind::Parachain,
},
),
(
penpal::PARA_ID_B.into(),
ParaGenesisArgs {
genesis_head: HeadData::default(),
validation_code: ValidationCode(
penpal_runtime::WASM_BINARY.unwrap().to_vec(),
),
para_kind: ParaKind::Parachain,
},
),
],
..Default::default()
},
..Default::default()
};
@@ -228,6 +274,13 @@ pub mod westend {
max_upward_message_size: 51200,
max_upward_message_num_per_candidate: 10,
max_downward_message_size: 51200,
hrmp_sender_deposit: 100_000_000_000,
hrmp_recipient_deposit: 100_000_000_000,
hrmp_channel_max_capacity: 1000,
hrmp_channel_max_message_size: 102400,
hrmp_channel_max_total_size: 102400,
hrmp_max_parachain_outbound_channels: 30,
hrmp_max_parachain_inbound_channels: 30,
..Default::default()
}
}
@@ -327,6 +380,13 @@ pub mod kusama {
max_upward_message_size: 51200,
max_upward_message_num_per_candidate: 10,
max_downward_message_size: 51200,
hrmp_sender_deposit: 5_000_000_000_000,
hrmp_recipient_deposit: 5_000_000_000_000,
hrmp_channel_max_capacity: 1000,
hrmp_channel_max_message_size: 102400,
hrmp_channel_max_total_size: 102400,
hrmp_max_parachain_outbound_channels: 30,
hrmp_max_parachain_inbound_channels: 30,
..Default::default()
}
}
@@ -403,6 +463,41 @@ pub mod kusama {
..Default::default()
},
configuration: kusama_runtime::ConfigurationConfig { config: get_host_config() },
paras: kusama_runtime::ParasConfig {
paras: vec![
(
asset_hub_kusama::PARA_ID.into(),
ParaGenesisArgs {
genesis_head: HeadData::default(),
validation_code: ValidationCode(
asset_hub_kusama_runtime::WASM_BINARY.unwrap().to_vec(),
),
para_kind: ParaKind::Parachain,
},
),
(
penpal::PARA_ID_A.into(),
ParaGenesisArgs {
genesis_head: HeadData::default(),
validation_code: ValidationCode(
penpal_runtime::WASM_BINARY.unwrap().to_vec(),
),
para_kind: ParaKind::Parachain,
},
),
(
penpal::PARA_ID_B.into(),
ParaGenesisArgs {
genesis_head: HeadData::default(),
validation_code: ValidationCode(
penpal_runtime::WASM_BINARY.unwrap().to_vec(),
),
para_kind: ParaKind::Parachain,
},
),
],
..Default::default()
},
..Default::default()
};
@@ -419,10 +514,18 @@ pub mod rococo {
pub fn get_host_config() -> HostConfiguration<BlockNumber> {
HostConfiguration {
max_upward_queue_count: 10,
max_upward_queue_size: 51200,
max_upward_message_size: 51200,
max_upward_message_num_per_candidate: 10,
max_downward_message_size: 51200,
hrmp_sender_deposit: 0,
hrmp_recipient_deposit: 0,
hrmp_channel_max_capacity: 1000,
hrmp_channel_max_message_size: 102400,
hrmp_channel_max_total_size: 102400,
hrmp_max_parachain_outbound_channels: 30,
hrmp_max_parachain_inbound_channels: 30,
..Default::default()
}
}
@@ -674,7 +777,8 @@ pub mod asset_hub_kusama {
// Penpal
pub mod penpal {
use super::*;
pub const PARA_ID: u32 = 2000;
pub const PARA_ID_A: u32 = 2000;
pub const PARA_ID_B: u32 = 2001;
pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT;
pub fn genesis(para_id: u32) -> Storage {
@@ -1,4 +1,5 @@
use super::{BridgeHubRococo, BridgeHubWococo};
// pub use paste;
use bp_messages::{
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
LaneId, MessageKey, OutboundLaneData,
@@ -8,7 +9,7 @@ use codec::Decode;
pub use cumulus_primitives_core::{DmpMessageHandler, XcmpMessageHandler};
use pallet_bridge_messages::{Config, Instance1, Instance2, OutboundLanes, Pallet};
use sp_core::Get;
use xcm_emulator::{BridgeMessage, BridgeMessageDispatchError, BridgeMessageHandler, Parachain};
use xcm_emulator::{BridgeMessage, BridgeMessageDispatchError, BridgeMessageHandler, Chain};
pub struct BridgeHubMessageHandler<S, T, I> {
_marker: std::marker::PhantomData<(S, T, I)>,
@@ -28,12 +29,12 @@ impl From<u32> for LaneIdWrapper {
}
}
type BridgeHubRococoRuntime = <BridgeHubRococo as Parachain>::Runtime;
type BridgeHubWococoRuntime = <BridgeHubWococo as Parachain>::Runtime;
type BridgeHubRococoRuntime = <BridgeHubRococo as Chain>::Runtime;
type BridgeHubWococoRuntime = <BridgeHubWococo as Chain>::Runtime;
// TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged
// type BridgeHubPolkadotRuntime = <BridgeHubPolkadot as Parachain>::Runtime;
// type BridgeHubKusamaRuntime = <BridgeHubKusama as Parachain>::Runtime;
// type BridgeHubPolkadotRuntime = <BridgeHubPolkadot as Chain>::Runtime;
// type BridgeHubKusamaRuntime = <BridgeHubKusama as Chain>::Runtime;
pub type RococoWococoMessageHandler =
BridgeHubMessageHandler<BridgeHubRococoRuntime, BridgeHubWococoRuntime, Instance2>;
@@ -124,3 +125,473 @@ where
OutboundLanes::<S, Instance1>::insert(LaneIdWrapper::from(lane_id).0, new_data);
}
}
#[macro_export]
macro_rules! impl_accounts_helpers_for_relay_chain {
( $chain:ident ) => {
$crate::paste::paste! {
impl $chain {
/// Fund a set of accounts with a balance
pub fn fund_accounts(accounts: Vec<(AccountId, Balance)>) {
Self::execute_with(|| {
for account in accounts {
assert_ok!(<Self as [<$chain Pallet>]>::Balances::force_set_balance(
<Self as Chain>::RuntimeOrigin::root(),
account.0.into(),
account.1,
));
}
});
}
/// Fund a sovereign account based on its Parachain Id
pub fn fund_para_sovereign(amount: Balance, para_id: ParaId) -> sp_runtime::AccountId32 {
let sovereign_account = Self::sovereign_account_id_of_child_para(para_id);
Self::fund_accounts(vec![(sovereign_account.clone(), amount)]);
sovereign_account
}
}
}
};
}
#[macro_export]
macro_rules! impl_assert_events_helpers_for_relay_chain {
( $chain:ident ) => {
$crate::paste::paste! {
type [<$chain RuntimeEvent>] = <$chain as Chain>::RuntimeEvent;
impl $chain {
/// Asserts a dispatchable is completely executed and XCM sent
pub fn assert_xcm_pallet_attempted_complete(expected_weight: Option<Weight>) {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::XcmPallet(
pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }
) => {
weight: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight),
*weight
),
},
]
);
}
/// Asserts a dispatchable is incompletely executed and XCM sent
pub fn assert_xcm_pallet_attempted_incomplete(
expected_weight: Option<Weight>,
expected_error: Option<Error>,
) {
assert_expected_events!(
Self,
vec![
// Dispatchable is properly executed and XCM message sent
[<$chain RuntimeEvent>]::XcmPallet(
pallet_xcm::Event::Attempted { outcome: Outcome::Incomplete(weight, error) }
) => {
weight: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight),
*weight
),
error: *error == expected_error.unwrap_or(*error),
},
]
);
}
/// Asserts a XCM message is sent
pub fn assert_xcm_pallet_sent() {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
}
/// Asserts a XCM from System Parachain is succesfully received and proccessed
pub fn assert_ump_queue_processed(
expected_success: bool,
expected_id: Option<ParaId>,
expected_weight: Option<Weight>,
) {
assert_expected_events!(
Self,
vec![
// XCM is succesfully received and proccessed
[<$chain RuntimeEvent>]::MessageQueue(pallet_message_queue::Event::Processed {
origin: AggregateMessageOrigin::Ump(UmpQueueId::Para(id)),
weight_used,
success,
..
}) => {
id: *id == expected_id.unwrap_or(*id),
weight_used: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight_used),
*weight_used
),
success: *success == expected_success,
},
]
);
}
}
}
};
}
#[macro_export]
macro_rules! impl_hrmp_channels_helpers_for_relay_chain {
( $chain:ident ) => {
$crate::paste::paste! {
impl $chain {
/// Init open channel request with another Parachain
pub fn init_open_channel_call(
recipient_para_id: ParaId,
max_capacity: u32,
max_message_size: u32,
) -> DoubleEncoded<()> {
<Self as Chain>::RuntimeCall::Hrmp(polkadot_runtime_parachains::hrmp::Call::<
<Self as Chain>::Runtime,
>::hrmp_init_open_channel {
recipient: recipient_para_id,
proposed_max_capacity: max_capacity,
proposed_max_message_size: max_message_size,
})
.encode()
.into()
}
/// Recipient Parachain accept the open request from another Parachain
pub fn accept_open_channel_call(sender_para_id: ParaId) -> DoubleEncoded<()> {
<Self as Chain>::RuntimeCall::Hrmp(polkadot_runtime_parachains::hrmp::Call::<
<Self as Chain>::Runtime,
>::hrmp_accept_open_channel {
sender: sender_para_id,
})
.encode()
.into()
}
/// A root origin force to open a channel between two Parachains
pub fn force_process_hrmp_open(sender: ParaId, recipient: ParaId) {
Self::execute_with(|| {
let relay_root_origin = <Self as Chain>::RuntimeOrigin::root();
// Force process HRMP open channel requests without waiting for the next session
assert_ok!(<Self as [<$chain Pallet>]>::Hrmp::force_process_hrmp_open(
relay_root_origin,
0
));
let channel_id = HrmpChannelId { sender, recipient };
let hrmp_channel_exist = polkadot_runtime_parachains::hrmp::HrmpChannels::<
<Self as Chain>::Runtime,
>::contains_key(&channel_id);
// Check the HRMP channel has been successfully registrered
assert!(hrmp_channel_exist)
});
}
}
}
};
}
#[macro_export]
macro_rules! impl_accounts_helpers_for_parachain {
( $chain:ident ) => {
$crate::paste::paste! {
impl $chain {
/// Fund a set of accounts with a balance
pub fn fund_accounts(accounts: Vec<(AccountId, Balance)>) {
Self::execute_with(|| {
for account in accounts {
assert_ok!(<Self as [<$chain Pallet>]>::Balances::force_set_balance(
<Self as Chain>::RuntimeOrigin::root(),
account.0.into(),
account.1,
));
}
});
}
}
}
};
}
#[macro_export]
macro_rules! impl_assert_events_helpers_for_parachain {
( $chain:ident ) => {
$crate::paste::paste! {
type [<$chain RuntimeEvent>] = <$chain as Chain>::RuntimeEvent;
impl $chain {
/// Asserts a dispatchable is completely executed and XCM sent
pub fn assert_xcm_pallet_attempted_complete(expected_weight: Option<Weight>) {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::PolkadotXcm(
pallet_xcm::Event::Attempted { outcome: Outcome::Complete(weight) }
) => {
weight: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight),
*weight
),
},
]
);
}
/// Asserts a dispatchable is incompletely executed and XCM sent
pub fn assert_xcm_pallet_attempted_incomplete(
expected_weight: Option<Weight>,
expected_error: Option<Error>,
) {
assert_expected_events!(
Self,
vec![
// Dispatchable is properly executed and XCM message sent
[<$chain RuntimeEvent>]::PolkadotXcm(
pallet_xcm::Event::Attempted { outcome: Outcome::Incomplete(weight, error) }
) => {
weight: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight),
*weight
),
error: *error == expected_error.unwrap_or(*error),
},
]
);
}
/// Asserts a dispatchable throws and error when trying to be sent
pub fn assert_xcm_pallet_attempted_error(expected_error: Option<Error>) {
assert_expected_events!(
Self,
vec![
// Execution fails in the origin with `Barrier`
[<$chain RuntimeEvent>]::PolkadotXcm(
pallet_xcm::Event::Attempted { outcome: Outcome::Error(error) }
) => {
error: *error == expected_error.unwrap_or(*error),
},
]
);
}
/// Asserts a XCM message is sent
pub fn assert_xcm_pallet_sent() {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
]
);
}
/// Asserts a XCM message is sent to Relay Chain
pub fn assert_parachain_system_ump_sent() {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::ParachainSystem(
cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }
) => {},
]
);
}
/// Asserts a XCM from Relay Chain is completely executed
pub fn assert_dmp_queue_complete(expected_weight: Option<Weight>) {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward {
outcome: Outcome::Complete(weight), ..
}) => {
weight: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight),
*weight
),
},
]
);
}
/// Asserts a XCM from Relay Chain is incompletely executed
pub fn assert_dmp_queue_incomplete(
expected_weight: Option<Weight>,
expected_error: Option<Error>,
) {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward {
outcome: Outcome::Incomplete(weight, error), ..
}) => {
weight: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight),
*weight
),
error: *error == expected_error.unwrap_or(*error),
},
]
);
}
/// Asserts a XCM from another Parachain is completely executed
pub fn assert_xcmp_queue_success(expected_weight: Option<Weight>) {
assert_expected_events!(
Self,
vec![
[<$chain RuntimeEvent>]::XcmpQueue(
cumulus_pallet_xcmp_queue::Event::Success { weight, .. }
) => {
weight: weight_within_threshold(
(REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD),
expected_weight.unwrap_or(*weight),
*weight
),
},
]
);
}
}
}
};
}
#[macro_export]
macro_rules! impl_assets_helpers_for_parachain {
( $chain:ident, $relay_chain:ident ) => {
$crate::paste::paste! {
impl $chain {
/// Returns the encoded call for `force_create` from the assets pallet
pub fn force_create_asset_call(
asset_id: u32,
owner: AccountId,
is_sufficient: bool,
min_balance: Balance,
) -> DoubleEncoded<()> {
<Self as Chain>::RuntimeCall::Assets(pallet_assets::Call::<
<Self as Chain>::Runtime,
Instance1,
>::force_create {
id: asset_id.into(),
owner: owner.into(),
is_sufficient,
min_balance,
})
.encode()
.into()
}
/// Returns a `VersionedXcm` for `force_create` from the assets pallet
pub fn force_create_asset_xcm(
origin_kind: OriginKind,
asset_id: u32,
owner: AccountId,
is_sufficient: bool,
min_balance: Balance,
) -> VersionedXcm<()> {
let call = Self::force_create_asset_call(asset_id, owner, is_sufficient, min_balance);
xcm_transact_unpaid_execution(call, origin_kind)
}
/// Mint assets making use of the assets pallet
pub fn mint_asset(
signed_origin: <Self as Chain>::RuntimeOrigin,
id: u32,
beneficiary: AccountId,
amount_to_mint: u128,
) {
Self::execute_with(|| {
assert_ok!(<Self as [<$chain Pallet>]>::Assets::mint(
signed_origin,
id.into(),
beneficiary.clone().into(),
amount_to_mint
));
type RuntimeEvent = <$chain as Chain>::RuntimeEvent;
assert_expected_events!(
Self,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, owner, amount }) => {
asset_id: *asset_id == id,
owner: *owner == beneficiary.clone().into(),
amount: *amount == amount_to_mint,
},
]
);
});
}
/// Force create and mint assets making use of the assets pallet
pub fn force_create_and_mint_asset(
id: u32,
min_balance: u128,
is_sufficient: bool,
asset_owner: AccountId,
amount_to_mint: u128,
) {
// Init values for Relay Chain
let root_origin = <$relay_chain as Chain>::RuntimeOrigin::root();
let destination = <$relay_chain>::child_location_of(<$chain>::para_id());
let xcm = Self::force_create_asset_xcm(
OriginKind::Superuser,
id,
asset_owner.clone(),
is_sufficient,
min_balance,
);
<$relay_chain>::execute_with(|| {
assert_ok!(<$relay_chain as [<$relay_chain Pallet>]>::XcmPallet::send(
root_origin,
bx!(destination.into()),
bx!(xcm),
));
<$relay_chain>::assert_xcm_pallet_sent();
});
Self::execute_with(|| {
Self::assert_dmp_queue_complete(Some(Weight::from_parts(1_019_445_000, 200_000)));
type RuntimeEvent = <$chain as Chain>::RuntimeEvent;
assert_expected_events!(
Self,
vec![
// Asset has been created
RuntimeEvent::Assets(pallet_assets::Event::ForceCreated { asset_id, owner }) => {
asset_id: *asset_id == id,
owner: *owner == asset_owner.clone(),
},
]
);
assert!(<Self as [<$chain Pallet>]>::Assets::asset_exists(id.into()));
});
let signed_origin = <Self as Chain>::RuntimeOrigin::signed(asset_owner.clone());
// Mint asset for System Parachain's sender
Self::mint_asset(signed_origin, id, asset_owner, amount_to_mint);
}
}
}
};
}
@@ -1,121 +1,114 @@
pub use lazy_static;
pub mod constants;
pub mod impls;
pub use codec::Encode;
pub use constants::{
accounts::{ALICE, BOB},
asset_hub_kusama, asset_hub_polkadot, asset_hub_westend, bridge_hub_kusama,
bridge_hub_polkadot, bridge_hub_rococo, collectives, kusama, penpal, polkadot, rococo, westend,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD,
};
use frame_support::{
assert_ok, instances::Instance1, parameter_types, sp_tracing, traits::fungibles::Inspect,
};
pub use impls::{RococoWococoMessageHandler, WococoRococoMessageHandler};
use frame_support::{parameter_types, sp_io, sp_tracing};
pub use parachains_common::{AccountId, AssetHubPolkadotAuraId, AuraId, Balance, BlockNumber};
pub use parachains_common::{AccountId, Balance};
pub use paste;
use polkadot_parachain::primitives::HrmpChannelId;
pub use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId};
pub use sp_core::{sr25519, storage::Storage, Get};
use xcm::prelude::*;
use xcm_emulator::{
decl_test_bridges, decl_test_networks, decl_test_parachains, decl_test_relay_chains,
decl_test_sender_receiver_accounts_parameter_types, BridgeMessageHandler, Parachain,
RelayChain, TestExt,
assert_expected_events, bx, decl_test_bridges, decl_test_networks, decl_test_parachains,
decl_test_relay_chains, decl_test_sender_receiver_accounts_parameter_types,
helpers::weight_within_threshold, BridgeMessageHandler, Chain, DefaultMessageProcessor, ParaId,
Parachain, RelayChain, TestExt,
};
pub use xcm::{
prelude::{
AccountId32, All, BuyExecution, DepositAsset, MultiAsset, MultiAssets, MultiLocation,
OriginKind, Outcome, RefundSurplus, Transact, UnpaidExecution, VersionedXcm, Weight,
WeightLimit, WithdrawAsset, Xcm, X1,
},
v3::Error,
DoubleEncoded,
};
use xcm_executor::traits::ConvertLocation;
decl_test_relay_chains! {
#[api_version(5)]
pub struct Polkadot {
genesis = polkadot::genesis(),
on_init = (),
runtime = {
Runtime: polkadot_runtime::Runtime,
RuntimeOrigin: polkadot_runtime::RuntimeOrigin,
RuntimeCall: polkadot_runtime::RuntimeCall,
RuntimeEvent: polkadot_runtime::RuntimeEvent,
MessageQueue: polkadot_runtime::MessageQueue,
XcmConfig: polkadot_runtime::xcm_config::XcmConfig,
runtime = polkadot_runtime,
core = {
MessageProcessor: DefaultMessageProcessor<Polkadot>,
SovereignAccountOf: polkadot_runtime::xcm_config::SovereignAccountOf,
System: polkadot_runtime::System,
Balances: polkadot_runtime::Balances,
},
pallets_extra = {
pallets = {
XcmPallet: polkadot_runtime::XcmPallet,
Balances: polkadot_runtime::Balances,
Hrmp: polkadot_runtime::Hrmp,
}
},
#[api_version(5)]
pub struct Kusama {
genesis = kusama::genesis(),
on_init = (),
runtime = {
Runtime: kusama_runtime::Runtime,
RuntimeOrigin: kusama_runtime::RuntimeOrigin,
RuntimeCall: kusama_runtime::RuntimeCall,
RuntimeEvent: kusama_runtime::RuntimeEvent,
MessageQueue: kusama_runtime::MessageQueue,
XcmConfig: kusama_runtime::xcm_config::XcmConfig,
runtime = kusama_runtime,
core = {
MessageProcessor: DefaultMessageProcessor<Kusama>,
SovereignAccountOf: kusama_runtime::xcm_config::SovereignAccountOf,
System: kusama_runtime::System,
Balances: kusama_runtime::Balances,
},
pallets_extra = {
pallets = {
XcmPallet: kusama_runtime::XcmPallet,
Balances: kusama_runtime::Balances,
Hrmp: kusama_runtime::Hrmp,
}
},
#[api_version(5)]
pub struct Westend {
genesis = westend::genesis(),
on_init = (),
runtime = {
Runtime: westend_runtime::Runtime,
RuntimeOrigin: westend_runtime::RuntimeOrigin,
RuntimeCall: westend_runtime::RuntimeCall,
RuntimeEvent: westend_runtime::RuntimeEvent,
MessageQueue: westend_runtime::MessageQueue,
XcmConfig: westend_runtime::xcm_config::XcmConfig,
runtime = westend_runtime,
core = {
MessageProcessor: DefaultMessageProcessor<Westend>,
SovereignAccountOf: westend_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf,
System: westend_runtime::System,
Balances: westend_runtime::Balances,
},
pallets_extra = {
pallets = {
XcmPallet: westend_runtime::XcmPallet,
Sudo: westend_runtime::Sudo,
Balances: westend_runtime::Balances,
}
},
#[api_version(5)]
pub struct Rococo {
genesis = rococo::genesis(),
on_init = (),
runtime = {
Runtime: rococo_runtime::Runtime,
RuntimeOrigin: rococo_runtime::RuntimeOrigin,
RuntimeCall: rococo_runtime::RuntimeCall,
RuntimeEvent: rococo_runtime::RuntimeEvent,
MessageQueue: rococo_runtime::MessageQueue,
XcmConfig: rococo_runtime::xcm_config::XcmConfig,
runtime = rococo_runtime,
core = {
MessageProcessor: DefaultMessageProcessor<Rococo>,
SovereignAccountOf: rococo_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf,
System: rococo_runtime::System,
Balances: rococo_runtime::Balances,
},
pallets_extra = {
pallets = {
XcmPallet: rococo_runtime::XcmPallet,
Sudo: rococo_runtime::Sudo,
Balances: rococo_runtime::Balances,
}
},
#[api_version(5)]
pub struct Wococo {
genesis = rococo::genesis(),
on_init = (),
runtime = {
Runtime: rococo_runtime::Runtime,
RuntimeOrigin: rococo_runtime::RuntimeOrigin,
RuntimeCall: rococo_runtime::RuntimeCall,
RuntimeEvent: rococo_runtime::RuntimeEvent,
MessageQueue: rococo_runtime::MessageQueue,
XcmConfig: rococo_runtime::xcm_config::XcmConfig,
runtime = rococo_runtime,
core = {
MessageProcessor: DefaultMessageProcessor<Wococo>,
SovereignAccountOf: rococo_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf,
System: rococo_runtime::System,
Balances: rococo_runtime::Balances,
},
pallets_extra = {
pallets = {
XcmPallet: rococo_runtime::XcmPallet,
Sudo: rococo_runtime::Sudo,
Balances: rococo_runtime::Balances,
}
}
}
@@ -125,81 +118,74 @@ decl_test_parachains! {
pub struct AssetHubPolkadot {
genesis = asset_hub_polkadot::genesis(),
on_init = (),
runtime = {
Runtime: asset_hub_polkadot_runtime::Runtime,
RuntimeOrigin: asset_hub_polkadot_runtime::RuntimeOrigin,
RuntimeCall: asset_hub_polkadot_runtime::RuntimeCall,
RuntimeEvent: asset_hub_polkadot_runtime::RuntimeEvent,
runtime = asset_hub_polkadot_runtime,
core = {
XcmpMessageHandler: asset_hub_polkadot_runtime::XcmpQueue,
DmpMessageHandler: asset_hub_polkadot_runtime::DmpQueue,
LocationToAccountId: asset_hub_polkadot_runtime::xcm_config::LocationToAccountId,
System: asset_hub_polkadot_runtime::System,
Balances: asset_hub_polkadot_runtime::Balances,
ParachainSystem: asset_hub_polkadot_runtime::ParachainSystem,
ParachainInfo: asset_hub_polkadot_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: asset_hub_polkadot_runtime::PolkadotXcm,
Assets: asset_hub_polkadot_runtime::Assets,
Balances: asset_hub_polkadot_runtime::Balances,
}
},
pub struct Collectives {
genesis = collectives::genesis(),
on_init = (),
runtime = {
Runtime: collectives_polkadot_runtime::Runtime,
RuntimeOrigin: collectives_polkadot_runtime::RuntimeOrigin,
RuntimeCall: collectives_polkadot_runtime::RuntimeCall,
RuntimeEvent: collectives_polkadot_runtime::RuntimeEvent,
runtime = collectives_polkadot_runtime,
core = {
XcmpMessageHandler: collectives_polkadot_runtime::XcmpQueue,
DmpMessageHandler: collectives_polkadot_runtime::DmpQueue,
LocationToAccountId: collectives_polkadot_runtime::xcm_config::LocationToAccountId,
System: collectives_polkadot_runtime::System,
Balances: collectives_polkadot_runtime::Balances,
ParachainSystem: collectives_polkadot_runtime::ParachainSystem,
ParachainInfo: collectives_polkadot_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: collectives_polkadot_runtime::PolkadotXcm,
Balances: collectives_polkadot_runtime::Balances,
}
},
pub struct BridgeHubPolkadot {
genesis = bridge_hub_polkadot::genesis(),
on_init = (),
runtime = {
Runtime: bridge_hub_polkadot_runtime::Runtime,
RuntimeOrigin: bridge_hub_polkadot_runtime::RuntimeOrigin,
RuntimeCall: bridge_hub_polkadot_runtime::RuntimeCall,
RuntimeEvent: bridge_hub_polkadot_runtime::RuntimeEvent,
runtime = bridge_hub_polkadot_runtime,
core = {
XcmpMessageHandler: bridge_hub_polkadot_runtime::XcmpQueue,
DmpMessageHandler: bridge_hub_polkadot_runtime::DmpQueue,
LocationToAccountId: bridge_hub_polkadot_runtime::xcm_config::LocationToAccountId,
System: bridge_hub_polkadot_runtime::System,
Balances: bridge_hub_polkadot_runtime::Balances,
ParachainSystem: bridge_hub_polkadot_runtime::ParachainSystem,
ParachainInfo: bridge_hub_polkadot_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: bridge_hub_polkadot_runtime::PolkadotXcm,
}
},
pub struct PenpalPolkadot {
genesis = penpal::genesis(penpal::PARA_ID),
pub struct PenpalPolkadotA {
genesis = penpal::genesis(penpal::PARA_ID_A),
on_init = (),
runtime = {
Runtime: penpal_runtime::Runtime,
RuntimeOrigin: penpal_runtime::RuntimeOrigin,
RuntimeCall: penpal_runtime::RuntimeCall,
RuntimeEvent: penpal_runtime::RuntimeEvent,
runtime = penpal_runtime,
core = {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
System: penpal_runtime::System,
Balances: penpal_runtime::Balances,
ParachainSystem: penpal_runtime::ParachainSystem,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
},
pub struct PenpalPolkadotB {
genesis = penpal::genesis(penpal::PARA_ID_B),
on_init = (),
runtime = penpal_runtime,
core = {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
@@ -208,62 +194,60 @@ decl_test_parachains! {
pub struct AssetHubKusama {
genesis = asset_hub_kusama::genesis(),
on_init = (),
runtime = {
Runtime: asset_hub_kusama_runtime::Runtime,
RuntimeOrigin: asset_hub_kusama_runtime::RuntimeOrigin,
RuntimeCall: asset_hub_kusama_runtime::RuntimeCall,
RuntimeEvent: asset_hub_kusama_runtime::RuntimeEvent,
runtime = asset_hub_kusama_runtime,
core = {
XcmpMessageHandler: asset_hub_kusama_runtime::XcmpQueue,
DmpMessageHandler: asset_hub_kusama_runtime::DmpQueue,
LocationToAccountId: asset_hub_kusama_runtime::xcm_config::LocationToAccountId,
System: asset_hub_kusama_runtime::System,
Balances: asset_hub_kusama_runtime::Balances,
ParachainSystem: asset_hub_kusama_runtime::ParachainSystem,
ParachainInfo: asset_hub_kusama_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: asset_hub_kusama_runtime::PolkadotXcm,
Assets: asset_hub_kusama_runtime::Assets,
ForeignAssets: asset_hub_kusama_runtime::Assets,
Balances: asset_hub_kusama_runtime::Balances,
}
},
pub struct BridgeHubKusama {
genesis = bridge_hub_kusama::genesis(),
on_init = (),
runtime = {
Runtime: bridge_hub_kusama_runtime::Runtime,
RuntimeOrigin: bridge_hub_kusama_runtime::RuntimeOrigin,
RuntimeCall: bridge_hub_kusama_runtime::RuntimeCall,
RuntimeEvent: bridge_hub_kusama_runtime::RuntimeEvent,
runtime = bridge_hub_kusama_runtime,
core = {
XcmpMessageHandler: bridge_hub_kusama_runtime::XcmpQueue,
DmpMessageHandler: bridge_hub_kusama_runtime::DmpQueue,
LocationToAccountId: bridge_hub_kusama_runtime::xcm_config::LocationToAccountId,
System: bridge_hub_kusama_runtime::System,
Balances: bridge_hub_kusama_runtime::Balances,
ParachainSystem: bridge_hub_kusama_runtime::ParachainSystem,
ParachainInfo: bridge_hub_kusama_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: bridge_hub_kusama_runtime::PolkadotXcm,
}
},
pub struct PenpalKusama {
genesis = penpal::genesis(penpal::PARA_ID),
pub struct PenpalKusamaA {
genesis = penpal::genesis(penpal::PARA_ID_A),
on_init = (),
runtime = {
Runtime: penpal_runtime::Runtime,
RuntimeOrigin: penpal_runtime::RuntimeOrigin,
RuntimeCall: penpal_runtime::RuntimeCall,
RuntimeEvent: penpal_runtime::RuntimeEvent,
runtime = penpal_runtime,
core = {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
System: penpal_runtime::System,
Balances: penpal_runtime::Balances,
ParachainSystem: penpal_runtime::ParachainSystem,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
},
pub struct PenpalKusamaB {
genesis = penpal::genesis(penpal::PARA_ID_B),
on_init = (),
runtime = penpal_runtime,
core = {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
@@ -272,44 +256,33 @@ decl_test_parachains! {
pub struct AssetHubWestend {
genesis = asset_hub_westend::genesis(),
on_init = (),
runtime = {
Runtime: asset_hub_westend_runtime::Runtime,
RuntimeOrigin: asset_hub_westend_runtime::RuntimeOrigin,
RuntimeCall: asset_hub_westend_runtime::RuntimeCall,
RuntimeEvent: asset_hub_westend_runtime::RuntimeEvent,
runtime = asset_hub_westend_runtime,
core = {
XcmpMessageHandler: asset_hub_westend_runtime::XcmpQueue,
DmpMessageHandler: asset_hub_westend_runtime::DmpQueue,
LocationToAccountId: asset_hub_westend_runtime::xcm_config::LocationToAccountId,
System: asset_hub_westend_runtime::System,
Balances: asset_hub_westend_runtime::Balances,
ParachainSystem: asset_hub_westend_runtime::ParachainSystem,
ParachainInfo: asset_hub_westend_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm,
Balances: asset_hub_westend_runtime::Balances,
Assets: asset_hub_westend_runtime::Assets,
ForeignAssets: asset_hub_westend_runtime::ForeignAssets,
PoolAssets: asset_hub_westend_runtime::PoolAssets,
AssetConversion: asset_hub_westend_runtime::AssetConversion,
}
},
pub struct PenpalWestend {
genesis = penpal::genesis(penpal::PARA_ID),
pub struct PenpalWestendA {
genesis = penpal::genesis(penpal::PARA_ID_A),
on_init = (),
runtime = {
Runtime: penpal_runtime::Runtime,
RuntimeOrigin: penpal_runtime::RuntimeOrigin,
RuntimeCall: penpal_runtime::RuntimeCall,
RuntimeEvent: penpal_runtime::RuntimeEvent,
runtime = penpal_runtime,
core = {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
System: penpal_runtime::System,
Balances: penpal_runtime::Balances,
ParachainSystem: penpal_runtime::ParachainSystem,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
@@ -318,85 +291,78 @@ decl_test_parachains! {
pub struct BridgeHubRococo {
genesis = bridge_hub_rococo::genesis(),
on_init = (),
runtime = {
Runtime: bridge_hub_rococo_runtime::Runtime,
RuntimeOrigin: bridge_hub_rococo_runtime::RuntimeOrigin,
RuntimeCall: bridge_hub_rococo_runtime::RuntimeCall,
RuntimeEvent: bridge_hub_rococo_runtime::RuntimeEvent,
runtime = bridge_hub_rococo_runtime,
core = {
XcmpMessageHandler: bridge_hub_rococo_runtime::XcmpQueue,
DmpMessageHandler: bridge_hub_rococo_runtime::DmpQueue,
LocationToAccountId: bridge_hub_rococo_runtime::xcm_config::LocationToAccountId,
System: bridge_hub_rococo_runtime::System,
Balances: bridge_hub_rococo_runtime::Balances,
ParachainSystem: bridge_hub_rococo_runtime::ParachainSystem,
ParachainInfo: bridge_hub_rococo_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm,
Balances: bridge_hub_rococo_runtime::Balances,
}
},
// AssetHubRococo (aka Rockmine/Rockmine2) mirrors AssetHubKusama
pub struct AssetHubRococo {
genesis = asset_hub_polkadot::genesis(),
genesis = asset_hub_kusama::genesis(),
on_init = (),
runtime = {
Runtime: asset_hub_polkadot_runtime::Runtime,
RuntimeOrigin: asset_hub_polkadot_runtime::RuntimeOrigin,
RuntimeCall: asset_hub_polkadot_runtime::RuntimeCall,
RuntimeEvent: asset_hub_polkadot_runtime::RuntimeEvent,
XcmpMessageHandler: asset_hub_polkadot_runtime::XcmpQueue,
DmpMessageHandler: asset_hub_polkadot_runtime::DmpQueue,
LocationToAccountId: asset_hub_polkadot_runtime::xcm_config::LocationToAccountId,
System: asset_hub_polkadot_runtime::System,
Balances: asset_hub_polkadot_runtime::Balances,
ParachainSystem: asset_hub_polkadot_runtime::ParachainSystem,
ParachainInfo: asset_hub_polkadot_runtime::ParachainInfo,
runtime = asset_hub_kusama_runtime,
core = {
XcmpMessageHandler: asset_hub_kusama_runtime::XcmpQueue,
DmpMessageHandler: asset_hub_kusama_runtime::DmpQueue,
LocationToAccountId: asset_hub_kusama_runtime::xcm_config::LocationToAccountId,
ParachainInfo: asset_hub_kusama_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: asset_hub_polkadot_runtime::PolkadotXcm,
Assets: asset_hub_polkadot_runtime::Assets,
pallets = {
PolkadotXcm: asset_hub_kusama_runtime::PolkadotXcm,
Assets: asset_hub_kusama_runtime::Assets,
}
},
// Wococo Parachains
pub struct BridgeHubWococo {
genesis = bridge_hub_rococo::genesis(),
on_init = (),
runtime = {
Runtime: bridge_hub_rococo_runtime::Runtime,
RuntimeOrigin: bridge_hub_rococo_runtime::RuntimeOrigin,
RuntimeCall: bridge_hub_rococo_runtime::RuntimeCall,
RuntimeEvent: bridge_hub_rococo_runtime::RuntimeEvent,
runtime = bridge_hub_rococo_runtime,
core = {
XcmpMessageHandler: bridge_hub_rococo_runtime::XcmpQueue,
DmpMessageHandler: bridge_hub_rococo_runtime::DmpQueue,
LocationToAccountId: bridge_hub_rococo_runtime::xcm_config::LocationToAccountId,
System: bridge_hub_rococo_runtime::System,
Balances: bridge_hub_rococo_runtime::Balances,
ParachainSystem: bridge_hub_rococo_runtime::ParachainSystem,
ParachainInfo: bridge_hub_rococo_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm,
}
},
pub struct AssetHubWococo {
genesis = asset_hub_polkadot::genesis(),
on_init = (),
runtime = {
Runtime: asset_hub_polkadot_runtime::Runtime,
RuntimeOrigin: asset_hub_polkadot_runtime::RuntimeOrigin,
RuntimeCall: asset_hub_polkadot_runtime::RuntimeCall,
RuntimeEvent: asset_hub_polkadot_runtime::RuntimeEvent,
runtime = asset_hub_polkadot_runtime,
core = {
XcmpMessageHandler: asset_hub_polkadot_runtime::XcmpQueue,
DmpMessageHandler: asset_hub_polkadot_runtime::DmpQueue,
LocationToAccountId: asset_hub_polkadot_runtime::xcm_config::LocationToAccountId,
System: asset_hub_polkadot_runtime::System,
Balances: asset_hub_polkadot_runtime::Balances,
ParachainSystem: asset_hub_polkadot_runtime::ParachainSystem,
ParachainInfo: asset_hub_polkadot_runtime::ParachainInfo,
},
pallets_extra = {
pallets = {
PolkadotXcm: asset_hub_polkadot_runtime::PolkadotXcm,
Assets: asset_hub_polkadot_runtime::Assets,
}
},
pub struct PenpalRococoA {
genesis = penpal::genesis(penpal::PARA_ID_A),
on_init = (),
runtime = penpal_runtime,
core = {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
}
}
@@ -405,9 +371,10 @@ decl_test_networks! {
relay_chain = Polkadot,
parachains = vec![
AssetHubPolkadot,
PenpalPolkadot,
Collectives,
BridgeHubPolkadot,
PenpalPolkadotA,
PenpalPolkadotB,
],
// TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged
// bridge = PolkadotKusamaMockBridge
@@ -417,8 +384,9 @@ decl_test_networks! {
relay_chain = Kusama,
parachains = vec![
AssetHubKusama,
PenpalKusama,
PenpalKusamaA,
BridgeHubKusama,
PenpalKusamaB,
],
// TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged
// bridge = KusamaPolkadotMockBridge
@@ -428,7 +396,7 @@ decl_test_networks! {
relay_chain = Westend,
parachains = vec![
AssetHubWestend,
PenpalWestend,
PenpalWestendA,
],
bridge = ()
},
@@ -437,6 +405,7 @@ decl_test_networks! {
parachains = vec![
AssetHubRococo,
BridgeHubRococo,
PenpalRococoA,
],
bridge = RococoWococoMockBridge
},
@@ -474,6 +443,51 @@ decl_test_bridges! {
// }
}
// Polkadot implementation
impl_accounts_helpers_for_relay_chain!(Polkadot);
impl_assert_events_helpers_for_relay_chain!(Polkadot);
impl_hrmp_channels_helpers_for_relay_chain!(Polkadot);
// Kusama implementation
impl_accounts_helpers_for_relay_chain!(Kusama);
impl_assert_events_helpers_for_relay_chain!(Kusama);
impl_hrmp_channels_helpers_for_relay_chain!(Kusama);
// Westend implementation
impl_accounts_helpers_for_relay_chain!(Westend);
impl_assert_events_helpers_for_relay_chain!(Westend);
// Rococo implementation
impl_accounts_helpers_for_relay_chain!(Rococo);
impl_assert_events_helpers_for_relay_chain!(Rococo);
// Wococo implementation
impl_accounts_helpers_for_relay_chain!(Wococo);
impl_assert_events_helpers_for_relay_chain!(Wococo);
// AssetHubPolkadot implementation
impl_accounts_helpers_for_parachain!(AssetHubPolkadot);
impl_assets_helpers_for_parachain!(AssetHubPolkadot, Polkadot);
impl_assert_events_helpers_for_parachain!(AssetHubPolkadot);
// AssetHubKusama implementation
impl_accounts_helpers_for_parachain!(AssetHubKusama);
impl_assets_helpers_for_parachain!(AssetHubKusama, Kusama);
impl_assert_events_helpers_for_parachain!(AssetHubKusama);
// AssetHubWestend implementation
impl_accounts_helpers_for_parachain!(AssetHubWestend);
impl_assets_helpers_for_parachain!(AssetHubWestend, Westend);
impl_assert_events_helpers_for_parachain!(AssetHubWestend);
// Collectives implementation
impl_accounts_helpers_for_parachain!(Collectives);
impl_assert_events_helpers_for_parachain!(Collectives);
// BridgeHubRococo implementation
impl_accounts_helpers_for_parachain!(BridgeHubRococo);
impl_assert_events_helpers_for_parachain!(BridgeHubRococo);
decl_test_sender_receiver_accounts_parameter_types! {
// Relays
Polkadot { sender: ALICE, receiver: BOB },
@@ -495,7 +509,51 @@ decl_test_sender_receiver_accounts_parameter_types! {
BridgeHubRococo { sender: ALICE, receiver: BOB },
BridgeHubWococo { sender: ALICE, receiver: BOB },
// Penpals
PenpalPolkadot { sender: ALICE, receiver: BOB },
PenpalKusama { sender: ALICE, receiver: BOB },
PenpalWestend { sender: ALICE, receiver: BOB }
PenpalPolkadotA { sender: ALICE, receiver: BOB },
PenpalPolkadotB { sender: ALICE, receiver: BOB },
PenpalKusamaA { sender: ALICE, receiver: BOB },
PenpalKusamaB { sender: ALICE, receiver: BOB },
PenpalWestendA { sender: ALICE, receiver: BOB },
PenpalRococoA { sender: ALICE, receiver: BOB }
}
/// Helper method to build a XCM with a `Transact` instruction and paying for its execution
pub fn xcm_transact_paid_execution(
call: DoubleEncoded<()>,
origin_kind: OriginKind,
native_asset: MultiAsset,
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();
VersionedXcm::from(Xcm(vec![
WithdrawAsset(native_assets),
BuyExecution { fees: native_asset, weight_limit },
Transact { require_weight_at_most, origin_kind, call },
RefundSurplus,
DepositAsset {
assets: All.into(),
beneficiary: MultiLocation {
parents: 0,
interior: X1(AccountId32 { network: None, id: beneficiary.into() }),
},
},
]))
}
/// Helper method to build a XCM with a `Transact` instruction without paying for its execution
pub fn xcm_transact_unpaid_execution(
call: DoubleEncoded<()>,
origin_kind: OriginKind,
) -> VersionedXcm<()> {
let weight_limit = WeightLimit::Unlimited;
let require_weight_at_most = Weight::from_parts(1000000000, 200000);
let check_origin = None;
VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit, check_origin },
Transact { require_weight_at_most, origin_kind, call },
]))
}
+4 -3
View File
@@ -8,9 +8,9 @@ edition = "2021"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0" }
paste = "1.0.14"
quote = "1.0.32"
casey = "0.4.0"
log = { version = "0.4.19", default-features = false }
lazy_static = "1.4.0"
impl-trait-for-tuples = "0.2.2"
# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -18,9 +18,9 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -36,5 +36,6 @@ parachains-common = { path = "../../parachains/common" }
# Polkadot
xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
File diff suppressed because it is too large Load Diff