[xcm-emulator] Chains generic over Network & Integration tests restructure (#2092)

Closes:
- #1383 
- Declared chains can be now be imported and reused in a different
crate.
- Chain declaration are now generic over a generic type `N` (the
Network)
- #1389
- Solved #1383, chains and networks declarations can be restructure to
avoid having to compile all chains when running integrations tests where
are not needed.
- Chains are now declared on its own crate (removed from
`integration-tests-common`)
- Networks are now declared on its own crate (removed from
`integration-tests-common`)
    - Integration tests will import only the relevant Network crate
- `integration-tests-common` is renamed to
`emulated-integration-tests-common`

All this is necessary to be able to implement what is described here:
https://github.com/paritytech/roadmap/issues/56#issuecomment-1777010553

---------

Co-authored-by: command-bot <>
This commit is contained in:
Ignacio Palacios
2023-11-08 16:02:03 +01:00
committed by GitHub
parent 50390950d8
commit ffa0e30e58
79 changed files with 2674 additions and 2750 deletions
@@ -0,0 +1,32 @@
[package]
name = "asset-hub-rococo-integration-tests"
version = "1.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Asset Hub Rococo runtime integration tests with xcm-emulator"
publish = false
[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
assert_matches = "1.5.0"
# Substrate
sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false}
frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false}
pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false}
pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false}
pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false}
# Polkadot
xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false}
pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false}
xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false}
rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" }
# Cumulus
asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
parachains-common = { path = "../../../../../../parachains/common" }
asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" }
emulated-integration-tests-common = { path = "../../../common", default-features = false}
rococo-system-emulated-network ={ path = "../../../networks/rococo-system" }
@@ -0,0 +1,104 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub use codec::Encode;
// Substrate
pub use frame_support::{
assert_err, assert_ok,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult},
traits::fungibles::Inspect,
};
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{Error, NetworkId::Rococo as RococoId},
};
// Cumulus
pub use asset_test_utils::xcm_helpers;
pub use emulated_integration_tests_common::{
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
},
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet,
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
RococoRelay as Rococo, RococoRelayReceiver as RococoReceiver,
RococoRelaySender as RococoSender,
};
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<Rococo, AssetHubRococo>;
pub type SystemParaToRelayTest = Test<AssetHubRococo, Rococo>;
pub type SystemParaToParaTest = Test<AssetHubRococo, PenpalA>;
/// 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,
}
}
/// 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,20 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
mod reserve_transfer;
mod send;
mod set_xcm_versions;
mod swap;
mod teleport;
@@ -0,0 +1,439 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig;
use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
Rococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(630_092_000, 6_196)));
assert_expected_events!(
Rococo,
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 == Rococo::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_dest_assertions_incomplete(_t: RelayToSystemParaTest) {
AssetHubRococo::assert_dmp_queue_incomplete(Some(Weight::from_parts(57_185_000, 3504)));
}
fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) {
AssetHubRococo::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier))
}
fn system_para_to_para_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
864_610_000,
8_799,
)));
assert_expected_events!(
AssetHubRococo,
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 == AssetHubRococo::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
864_610_000,
8799,
)));
assert_expected_events!(
AssetHubRococo,
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 == AssetHubRococo::sovereign_account_id_of(
t.args.dest
),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
<Rococo as RococoPallet>::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 {
<Rococo as RococoPallet>::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 {
<AssetHubRococo as AssetHubRococoPallet>::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 {
<AssetHubRococo as AssetHubRococoPallet>::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 {
<AssetHubRococo as AssetHubRococoPallet>::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 {
<AssetHubRococo as AssetHubRococoPallet>::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 = ROCOCO_ED * 1000;
let test_args = TestContext {
sender: RococoSender::get(),
receiver: AssetHubRococoReceiver::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::<Rococo>(relay_origin_assertions);
test.set_assertion::<AssetHubRococo>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Rococo>(relay_limited_reserve_transfer_assets);
test.assert();
let delivery_fees = Rococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<RococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, 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 = AssetHubRococo::parent_location();
let beneficiary_id = RococoReceiver::get();
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: RococoReceiver::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::<AssetHubRococo>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubRococo>(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 = ROCOCO_ED * 1000;
let test_args = TestContext {
sender: RococoSender::get(),
receiver: AssetHubRococoReceiver::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::<Rococo>(relay_origin_assertions);
test.set_assertion::<AssetHubRococo>(system_para_dest_assertions_incomplete);
test.set_dispatchable::<Rococo>(relay_reserve_transfer_assets);
test.assert();
let delivery_fees = Rococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<RococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, 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 = AssetHubRococo::parent_location();
let beneficiary_id = RococoReceiver::get();
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: RococoReceiver::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::<AssetHubRococo>(system_para_to_relay_assertions);
test.set_dispatchable::<AssetHubRococo>(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 = AssetHubRococo::sibling_location_of(PenpalA::para_id());
let beneficiary_id = PenpalAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: PenpalAReceiver::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::<AssetHubRococo>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with
// `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubRococo>(system_para_to_para_limited_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let delivery_fees = AssetHubRococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubRococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, 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 = AssetHubRococo::sibling_location_of(PenpalA::para_id());
let beneficiary_id = PenpalAReceiver::get();
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: PenpalAReceiver::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::<AssetHubRococo>(system_para_to_para_assertions);
// TODO: Add assertion for Penpal runtime. Right now message is failing with
// `UntrustedReserveLocation`
test.set_dispatchable::<AssetHubRococo>(system_para_to_para_reserve_transfer_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let delivery_fees = AssetHubRococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubRococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, 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
AssetHubRococo::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubRococoSender::get(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubRococo::sibling_location_of(PenpalA::para_id());
let beneficiary_id = PenpalAReceiver::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: AssetHubRococoSender::get(),
receiver: PenpalAReceiver::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::<AssetHubRococo>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubRococo>(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
AssetHubRococo::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubRococoSender::get(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
ASSET_MIN_BALANCE * 1000000,
);
// Init values for System Parachain
let destination = AssetHubRococo::sibling_location_of(PenpalA::para_id());
let beneficiary_id = PenpalAReceiver::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: AssetHubRococoSender::get(),
receiver: PenpalAReceiver::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::<AssetHubRococo>(system_para_to_para_assets_assertions);
// TODO: Add assertions when Penpal is able to manage assets
system_para_test
.set_dispatchable::<AssetHubRococo>(system_para_to_para_reserve_transfer_assets);
system_para_test.assert();
}
@@ -0,0 +1,104 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
/// Relay Chain should be able to execute `Transact` instructions in System Parachain
/// when `OriginKind::Superuser`.
#[test]
fn send_transact_as_superuser_from_relay_to_system_para_works() {
AssetHubRococo::force_create_asset_from_relay_as_root(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
AssetHubRococoSender::get().into(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
)
}
/// 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 = AssetHubRococo::sovereign_account_id_of(
AssetHubRococo::sibling_location_of(PenpalA::para_id()),
);
// Force create and mint assets for Parachain's sovereign account
AssetHubRococo::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
ASSET_MIN_BALANCE * 1000000000,
);
// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubRococo::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 = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
PenpalA::assert_xcm_pallet_sent();
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_xcmp_queue_success(Some(Weight::from_parts(
15_594_564_000,
562_893,
)));
assert_expected_events!(
AssetHubRococo,
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,83 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
#[test]
fn relay_sets_system_para_xcm_supported_version() {
// Init tests variables
let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
let system_para_destination: MultiLocation =
Rococo::child_location_of(AssetHubRococo::para_id());
// Relay Chain sets supported version for Asset Parachain
Rococo::execute_with(|| {
assert_ok!(<Rococo as RococoPallet>::XcmPallet::force_xcm_version(
sudo_origin,
bx!(system_para_destination),
XCM_V3
));
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
assert_expected_events!(
Rococo,
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 parent_location = AssetHubRococo::parent_location();
let force_xcm_version_call =
<AssetHubRococo as Chain>::RuntimeCall::PolkadotXcm(pallet_xcm::Call::<
<AssetHubRococo as Chain>::Runtime,
>::force_xcm_version {
location: bx!(parent_location),
version: XCM_V3,
})
.encode()
.into();
// System Parachain sets supported version for Relay Chain through it
Rococo::send_unpaid_transact_to_parachain_as_root(
AssetHubRococo::para_id(),
force_xcm_version_call,
);
// System Parachain receive the XCM message
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_dmp_queue_complete(Some(Weight::from_parts(1_019_210_000, 200_000)));
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::SupportedVersionChanged {
location,
version: XCM_V3
}) => { location: *location == parent_location, },
]
);
});
}
@@ -0,0 +1,364 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use frame_support::{instances::Instance2, BoundedVec};
use parachains_common::rococo::currency::EXISTENTIAL_DEPOSIT;
use sp_runtime::{DispatchError, ModuleError};
#[test]
fn swap_locally_on_chain_using_local_assets() {
let asset_native = Box::new(asset_hub_rococo_runtime::xcm_config::TokenLocation::get());
let asset_one = Box::new(MultiLocation {
parents: 0,
interior: X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())),
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::Assets::create(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
ASSET_ID.into(),
AssetHubRococoSender::get().into(),
1000,
));
assert!(<AssetHubRococo as AssetHubRococoPallet>::Assets::asset_exists(ASSET_ID));
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::Assets::mint(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
ASSET_ID.into(),
AssetHubRococoSender::get().into(),
100_000_000_000_000,
));
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::Balances::force_set_balance(
<AssetHubRococo as Chain>::RuntimeOrigin::root(),
AssetHubRococoSender::get().into(),
100_000_000_000_000,
));
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::create_pool(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
asset_native.clone(),
asset_one.clone(),
));
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::add_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
asset_native.clone(),
asset_one.clone(),
1_000_000_000_000,
2_000_000_000_000,
0,
0,
AssetHubRococoSender::get().into()
));
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { lp_token_minted: *lp_token_minted == 1414213562273, },
]
);
let path = BoundedVec::<_, _>::truncate_from(vec![asset_native.clone(), asset_one.clone()]);
assert_ok!(
<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
path,
100,
1,
AssetHubRococoSender::get().into(),
true
)
);
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. }) => {
amount_in: *amount_in == 100,
amount_out: *amount_out == 199,
},
]
);
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::remove_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
asset_native,
asset_one,
1414213562273 - EXISTENTIAL_DEPOSIT * 2, // all but the 2 EDs can't be retrieved.
0,
0,
AssetHubRococoSender::get().into(),
));
});
}
#[test]
fn swap_locally_on_chain_using_foreign_assets() {
use frame_support::weights::WeightToFee;
let asset_native = Box::new(asset_hub_rococo_runtime::xcm_config::TokenLocation::get());
let foreign_asset1_at_asset_hub_rococo = Box::new(MultiLocation {
parents: 1,
interior: X3(
Parachain(PenpalA::para_id().into()),
PalletInstance(ASSETS_PALLET_ID),
GeneralIndex(ASSET_ID.into()),
),
});
let assets_para_destination: VersionedMultiLocation =
MultiLocation { parents: 1, interior: X1(Parachain(AssetHubRococo::para_id().into())) }
.into();
let penpal_location =
MultiLocation { parents: 1, interior: X1(Parachain(PenpalA::para_id().into())) };
// 1. Create asset on penpal:
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::Assets::create(
<PenpalA as Chain>::RuntimeOrigin::signed(PenpalASender::get()),
ASSET_ID.into(),
PenpalASender::get().into(),
1000,
));
assert!(<PenpalA as PenpalAPallet>::Assets::asset_exists(ASSET_ID));
});
// 2. Create foreign asset on asset_hub_rococo:
let require_weight_at_most = Weight::from_parts(1_100_000_000_000, 30_000);
let origin_kind = OriginKind::Xcm;
let sov_penpal_on_asset_hub_rococo = AssetHubRococo::sovereign_account_id_of(penpal_location);
AssetHubRococo::fund_accounts(vec![
(AssetHubRococoSender::get().into(), 5_000_000 * ROCOCO_ED), /* An account to swap dot
* for something else. */
(sov_penpal_on_asset_hub_rococo.clone().into(), 1000_000_000_000_000_000 * ROCOCO_ED),
]);
let sov_penpal_on_asset_hub_rococo_as_location: MultiLocation = MultiLocation {
parents: 0,
interior: X1(AccountId32Junction {
network: None,
id: sov_penpal_on_asset_hub_rococo.clone().into(),
}),
};
let call_foreign_assets_create =
<AssetHubRococo as Chain>::RuntimeCall::ForeignAssets(pallet_assets::Call::<
<AssetHubRococo as Chain>::Runtime,
Instance2,
>::create {
id: *foreign_asset1_at_asset_hub_rococo,
min_balance: 1000,
admin: sov_penpal_on_asset_hub_rococo.clone().into(),
})
.encode()
.into();
let buy_execution_fee_amount = parachains_common::rococo::fee::WeightToFee::weight_to_fee(
&Weight::from_parts(10_100_000_000_000, 300_000),
);
let buy_execution_fee = MultiAsset {
id: Concrete(MultiLocation { parents: 1, interior: Here }),
fun: Fungible(buy_execution_fee_amount),
};
let xcm = VersionedXcm::from(Xcm(vec![
WithdrawAsset { 0: vec![buy_execution_fee.clone()].into() },
BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited },
Transact { require_weight_at_most, origin_kind, call: call_foreign_assets_create },
RefundSurplus,
DepositAsset {
assets: All.into(),
beneficiary: sov_penpal_on_asset_hub_rococo_as_location,
},
]));
// Send XCM message from penpal => asset_hub_rococo
let sudo_penpal_origin = <PenpalA as Chain>::RuntimeOrigin::root();
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
sudo_penpal_origin.clone(),
bx!(assets_para_destination.clone()),
bx!(xcm),
));
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
assert_expected_events!(
PenpalA,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubRococo::execute_with(|| {
assert!(<AssetHubRococo as AssetHubRococoPallet>::ForeignAssets::asset_exists(
*foreign_asset1_at_asset_hub_rococo
));
// 3: Mint foreign asset on asset_hub_rococo:
//
// (While it might be nice to use batch,
// currently that's disabled due to safe call filters.)
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
// 3. Mint foreign asset (in reality this should be a teleport or some such)
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::ForeignAssets::mint(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_rococo.clone().into()
),
*foreign_asset1_at_asset_hub_rococo,
sov_penpal_on_asset_hub_rococo.clone().into(),
3_000_000_000_000,
));
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
]
);
// 4. Create pool:
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::create_pool(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
asset_native.clone(),
foreign_asset1_at_asset_hub_rococo.clone(),
));
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);
// 5. Add liquidity:
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::add_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_rococo.clone()
),
asset_native.clone(),
foreign_asset1_at_asset_hub_rococo.clone(),
1_000_000_000_000,
2_000_000_000_000,
0,
0,
sov_penpal_on_asset_hub_rococo.clone().into()
));
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => {
lp_token_minted: *lp_token_minted == 1414213562273,
},
]
);
// 6. Swap!
let path = BoundedVec::<_, _>::truncate_from(vec![
asset_native.clone(),
foreign_asset1_at_asset_hub_rococo.clone(),
]);
assert_ok!(
<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
path,
100000,
1000,
AssetHubRococoSender::get().into(),
true
)
);
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
amount_in: *amount_in == 100000,
amount_out: *amount_out == 199399,
},
]
);
// 7. Remove liquidity
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::remove_liquidity(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_rococo.clone()
),
asset_native,
foreign_asset1_at_asset_hub_rococo,
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
0,
0,
sov_penpal_on_asset_hub_rococo.clone().into(),
));
});
}
#[test]
fn cannot_create_pool_from_pool_assets() {
let asset_native = Box::new(asset_hub_rococo_runtime::xcm_config::TokenLocation::get());
let mut asset_one = asset_hub_rococo_runtime::xcm_config::PoolAssetsPalletLocation::get();
asset_one.append_with(GeneralIndex(ASSET_ID.into())).expect("pool assets");
AssetHubRococo::execute_with(|| {
let pool_owner_account_id = asset_hub_rococo_runtime::AssetConversionOrigin::get();
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::PoolAssets::create(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(pool_owner_account_id.clone()),
ASSET_ID.into(),
pool_owner_account_id.clone().into(),
1000,
));
assert!(<AssetHubRococo as AssetHubRococoPallet>::PoolAssets::asset_exists(ASSET_ID));
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::PoolAssets::mint(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(pool_owner_account_id),
ASSET_ID.into(),
AssetHubRococoSender::get().into(),
3_000_000_000_000,
));
assert_matches::assert_matches!(
<AssetHubRococo as AssetHubRococoPallet>::AssetConversion::create_pool(
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get()),
asset_native.clone(),
Box::new(asset_one),
),
Err(DispatchError::Module(ModuleError{index: _, error: _, message})) => assert_eq!(message, Some("UnsupportedAsset"))
);
});
}
@@ -0,0 +1,408 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig;
use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig;
fn relay_origin_assertions(t: RelayToSystemParaTest) {
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
Rococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(631_531_000, 7_186)));
assert_expected_events!(
Rococo,
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 == <Rococo as RococoPallet>::XcmPallet::check_account(),
amount: *amount == t.args.amount,
},
]
);
}
fn relay_dest_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
Rococo::assert_ump_queue_processed(
true,
Some(AssetHubRococo::para_id()),
Some(Weight::from_parts(307_225_000, 7_186)),
);
assert_expected_events!(
Rococo,
vec![
// Amount is witdrawn from Relay Chain's `CheckAccount`
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
who: *who == <Rococo as RococoPallet>::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) {
Rococo::assert_ump_queue_processed(
false,
Some(AssetHubRococo::para_id()),
Some(Weight::from_parts(157_718_000, 3_593)),
);
}
fn para_origin_assertions(t: SystemParaToRelayTest) {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
720_053_000,
7_203,
)));
AssetHubRococo::assert_parachain_system_ump_sent();
assert_expected_events!(
AssetHubRococo,
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 = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_dmp_queue_complete(Some(Weight::from_parts(157_718_000, 3593)));
assert_expected_events!(
AssetHubRococo,
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 {
<Rococo as RococoPallet>::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 {
<Rococo as RococoPallet>::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 {
<AssetHubRococo as AssetHubRococoPallet>::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,
)
}
fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::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,
)
}
/// 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 = ROCOCO_ED * 1000;
let test_args = TestContext {
sender: RococoSender::get(),
receiver: AssetHubRococoReceiver::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::<Rococo>(relay_origin_assertions);
test.set_assertion::<AssetHubRococo>(para_dest_assertions);
test.set_dispatchable::<Rococo>(relay_limited_teleport_assets);
test.assert();
let delivery_fees = Rococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<RococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
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 - delivery_fees, 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_ROCOCO_ED * 1000;
let destination = AssetHubRococo::parent_location();
let beneficiary_id = RococoReceiver::get();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: RococoReceiver::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::<AssetHubRococo>(para_origin_assertions);
test.set_assertion::<Rococo>(relay_dest_assertions);
test.set_dispatchable::<AssetHubRococo>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
let delivery_fees = AssetHubRococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubRococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, 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_ROCOCO_ED * 1000;
let destination = AssetHubRococo::parent_location().into();
let beneficiary_id = RococoReceiver::get().into();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: RococoReceiver::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::<AssetHubRococo>(para_origin_assertions);
test.set_assertion::<Rococo>(relay_dest_assertions_fail);
test.set_dispatchable::<AssetHubRococo>(system_para_limited_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
let delivery_fees = AssetHubRococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubRococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, 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 = ROCOCO_ED * 1000;
let test_args = TestContext {
sender: RococoSender::get(),
receiver: AssetHubRococoReceiver::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::<Rococo>(relay_origin_assertions);
test.set_assertion::<AssetHubRococo>(para_dest_assertions);
test.set_dispatchable::<Rococo>(relay_teleport_assets);
test.assert();
let delivery_fees = Rococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<RococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
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 - delivery_fees, sender_balance_after);
// Receiver's balance is increased
assert!(receiver_balance_after > receiver_balance_before);
}
/// 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_ROCOCO_ED * 1000;
let destination = AssetHubRococo::parent_location();
let beneficiary_id = RococoReceiver::get();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: RococoReceiver::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::<AssetHubRococo>(para_origin_assertions);
test.set_assertion::<Rococo>(relay_dest_assertions);
test.set_dispatchable::<AssetHubRococo>(system_para_teleport_assets);
test.assert();
let sender_balance_after = test.sender.balance;
let receiver_balance_after = test.receiver.balance;
let delivery_fees = AssetHubRococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubRococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
// Sender's balance is reduced
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, 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_ROCOCO_ED * 1000;
let destination = AssetHubRococo::parent_location();
let beneficiary_id = RococoReceiver::get();
let assets = (Parent, amount_to_send).into();
let test_args = TestContext {
sender: AssetHubRococoSender::get(),
receiver: RococoReceiver::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::<AssetHubRococo>(para_origin_assertions);
test.set_assertion::<Rococo>(relay_dest_assertions_fail);
test.set_dispatchable::<AssetHubRococo>(system_para_teleport_assets);
test.assert();
let delivery_fees = AssetHubRococo::execute_with(|| {
xcm_helpers::transfer_assets_delivery_fees::<
<AssetHubRococoXcmConfig as xcm_executor::Config>::XcmSender,
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
});
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 - delivery_fees, sender_balance_after);
// Receiver's balance does not change
assert_eq!(receiver_balance_after, receiver_balance_before);
}
#[test]
fn teleport_to_other_system_parachains_works() {
let amount = ASSET_HUB_ROCOCO_ED * 100;
let native_asset: MultiAssets = (Parent, amount).into();
test_parachain_is_trusted_teleporter!(
AssetHubRococo, // Origin
AssetHubRococoXcmConfig, // XCM Configuration
vec![BridgeHubRococo], // Destinations
(native_asset, amount)
);
}