cumulus: add asset-hub-rococo runtime based on asset-hub-kusama and add asset-bridging support to it (#1215)

This commit adds Rococo Asset Hub dedicated runtime so we can test new
features here, before merging them in Kusama Asset Hub.
Also adds one such feature: asset transfer over bridge (Rococo AssetHub
<> Wococo AssetHub)

- clone `asset-hub-kusama-runtime` -> `asset-hub-rococo-runtime`
- make it use Rococo primitives, names, assets, constants, etc
- add asset-transfer-over-bridge support to Rococo AssetHub <> Wococo
AssetHub

Fixes #1128

---------

Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
This commit is contained in:
Adrian Catangiu
2023-10-18 09:47:45 +03:00
committed by GitHub
parent e73729b15f
commit 8b3905d2a5
95 changed files with 14143 additions and 767 deletions
@@ -3,15 +3,32 @@ 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}
frame-system = { path = "../../../../../../substrate/frame/system", 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
polkadot-core-primitives = { path = "../../../../../../polkadot/core-primitives", default-features = false}
polkadot-parachain-primitives = { path = "../../../../../../polkadot/parachain", default-features = false}
polkadot-runtime-parachains = { path = "../../../../../../polkadot/runtime/parachains" }
xcm = { package = "staging-xcm", path = "../../../../../../polkadot/xcm", default-features = false}
pallet-xcm = { path = "../../../../../../polkadot/xcm/pallet-xcm", default-features = false}
# Cumulus
parachains-common = { path = "../../../../common" }
asset-hub-rococo-runtime = { path = "../../../../runtimes/assets/asset-hub-rococo" }
# Local
xcm-emulator = { path = "../../../../../xcm/xcm-emulator", default-features = false}
@@ -19,6 +36,16 @@ integration-tests-common = { path = "../../common", default-features = false}
[features]
runtime-benchmarks = [
"asset-hub-rococo-runtime/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"integration-tests-common/runtime-benchmarks",
"pallet-asset-conversion/runtime-benchmarks",
"pallet-assets/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"parachains-common/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
@@ -13,14 +13,79 @@
// See the License for the specific language governing permissions and
// limitations under the License.
pub use frame_support::assert_ok;
pub use integration_tests_common::{
constants::asset_hub_rococo::ED as ASSET_HUB_ROCOCO_ED, test_parachain_is_trusted_teleporter,
AssetHubRococo, AssetHubRococoPallet, AssetHubRococoSender, BridgeHubRococo,
BridgeHubRococoReceiver,
pub use codec::Encode;
pub use frame_support::{
assert_err, assert_ok,
pallet_prelude::Weight,
sp_runtime::{AccountId32, DispatchError, DispatchResult},
traits::fungibles::Inspect,
};
pub use xcm::prelude::*;
pub use xcm_emulator::{assert_expected_events, bx, Chain, Parachain, TestExt};
pub use integration_tests_common::{
constants::{
asset_hub_rococo::ED as ASSET_HUB_ROCOCO_ED, rococo::ED as ROCOCO_ED, PROOF_SIZE_THRESHOLD,
REF_TIME_THRESHOLD, XCM_V3,
},
test_parachain_is_trusted_teleporter,
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
AssetHubRococo, AssetHubRococoPallet, AssetHubRococoReceiver, AssetHubRococoSender,
BridgeHubRococo, BridgeHubRococoReceiver, PenpalRococoA, PenpalRococoAPallet,
PenpalRococoAReceiver, PenpalRococoASender, PenpalRococoB, PenpalRococoBPallet, Rococo,
RococoPallet, RococoReceiver, RococoSender,
};
pub use parachains_common::{AccountId, Balance};
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{Error, NetworkId::Rococo as RococoId},
};
pub use xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
RelayChain as Relay, Test, TestArgs, TestContext, TestExt,
};
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, PenpalRococoA>;
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
pub fn relay_test_args(amount: Balance) -> TestArgs {
TestArgs {
dest: Rococo::child_location_of(AssetHubRococo::para_id()),
beneficiary: AccountId32Junction {
network: None,
id: AssetHubRococoReceiver::get().into(),
}
.into(),
amount,
assets: (Here, amount).into(),
asset_id: None,
fee_asset_item: 0,
weight_limit: WeightLimit::Unlimited,
}
}
/// 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;
@@ -13,4 +13,8 @@
// 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,416 @@
// 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::*;
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(1_000_000_000, 0)),
Some(Error::UntrustedReserveLocation),
);
}
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(
630_092_000,
6_196,
)));
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(
676_119_000,
6196,
)));
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 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 = 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 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 = 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(PenpalRococoA::para_id());
let beneficiary_id = PenpalRococoAReceiver::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: PenpalRococoAReceiver::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;
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 = AssetHubRococo::sibling_location_of(PenpalRococoA::para_id());
let beneficiary_id = PenpalRococoAReceiver::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: PenpalRococoAReceiver::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;
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
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(PenpalRococoA::para_id());
let beneficiary_id = PenpalRococoAReceiver::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: PenpalRococoAReceiver::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(PenpalRococoA::para_id());
let beneficiary_id = PenpalRococoAReceiver::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: PenpalRococoAReceiver::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,102 @@
// 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(PenpalRococoA::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 = <PenpalRococoA as Chain>::RuntimeOrigin::root();
let system_para_destination =
PenpalRococoA::sibling_location_of(AssetHubRococo::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);
PenpalRococoA::execute_with(|| {
assert_ok!(<PenpalRococoA as PenpalRococoAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));
PenpalRococoA::assert_xcm_pallet_sent();
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_xcmp_queue_success(Some(Weight::from_parts(2_176_414_000, 203_593)));
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(PenpalRococoA::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(PenpalRococoA::para_id().into())) };
// 1. Create asset on penpal:
PenpalRococoA::execute_with(|| {
assert_ok!(<PenpalRococoA as PenpalRococoAPallet>::Assets::create(
<PenpalRococoA as Chain>::RuntimeOrigin::signed(PenpalRococoASender::get()),
ASSET_ID.into(),
PenpalRococoASender::get().into(),
1000,
));
assert!(<PenpalRococoA as PenpalRococoAPallet>::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 = <PenpalRococoA as Chain>::RuntimeOrigin::root();
PenpalRococoA::execute_with(|| {
assert_ok!(<PenpalRococoA as PenpalRococoAPallet>::PolkadotXcm::send(
sudo_penpal_origin.clone(),
bx!(assets_para_destination.clone()),
bx!(xcm),
));
type RuntimeEvent = <PenpalRococoA as Chain>::RuntimeEvent;
assert_expected_events!(
PenpalRococoA,
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"))
);
});
}
@@ -15,6 +15,347 @@
use crate::*;
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(148_433_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(
534_872_000,
7_133,
)));
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(165_592_000, 0)));
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 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_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;
// 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_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;
// 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 = 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 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 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;
// 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_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 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);
}
#[test]
fn teleport_to_other_system_parachains_works() {
let amount = ASSET_HUB_ROCOCO_ED * 100;