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
@@ -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));
});
}