mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 11:41:02 +00:00
[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:
+32
@@ -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" }
|
||||
+104
@@ -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;
|
||||
+20
@@ -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;
|
||||
+439
@@ -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();
|
||||
}
|
||||
+104
@@ -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,
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+83
@@ -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, },
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+364
@@ -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"))
|
||||
);
|
||||
});
|
||||
}
|
||||
+408
@@ -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)
|
||||
);
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
[package]
|
||||
name = "asset-hub-westend-integration-tests"
|
||||
version = "1.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license = "Apache-2.0"
|
||||
description = "Asset Hub Westend 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}
|
||||
pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false}
|
||||
pallet-asset-rate = { path = "../../../../../../../substrate/frame/asset-rate", default-features = false}
|
||||
pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false }
|
||||
|
||||
# Polkadot
|
||||
polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" }
|
||||
xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false}
|
||||
xcm-builder = { package = "staging-xcm-builder", path = "../../../../../../../polkadot/xcm/xcm-builder", default-features = false}
|
||||
xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false}
|
||||
pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false}
|
||||
westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" }
|
||||
westend-runtime-constants = { path = "../../../../../../../polkadot/runtime/westend/constants", default-features = false }
|
||||
|
||||
# Cumulus
|
||||
parachains-common = { path = "../../../../../../parachains/common" }
|
||||
asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" }
|
||||
asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
|
||||
cumulus-pallet-dmp-queue = { default-features = false, path = "../../../../../../pallets/dmp-queue" }
|
||||
cumulus-pallet-parachain-system = { default-features = false, path = "../../../../../../pallets/parachain-system" }
|
||||
emulated-integration-tests-common = { path = "../../../common", default-features = false}
|
||||
westend-system-emulated-network ={ path = "../../../networks/westend-system" }
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// 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,
|
||||
instances::Instance2,
|
||||
pallet_prelude::Weight,
|
||||
sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError},
|
||||
traits::fungibles::Inspect,
|
||||
BoundedVec,
|
||||
};
|
||||
|
||||
// Polkadot
|
||||
pub use xcm::{
|
||||
prelude::{AccountId32 as AccountId32Junction, *},
|
||||
v3::{Error, NetworkId::Westend as WestendId},
|
||||
};
|
||||
|
||||
// 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 westend_system_emulated_network::{
|
||||
asset_hub_westend_emulated_chain::{
|
||||
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
|
||||
},
|
||||
penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet,
|
||||
westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet},
|
||||
AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver,
|
||||
AssetHubWestendParaSender as AssetHubWestendSender, PenpalAPara as PenpalA,
|
||||
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
|
||||
WestendRelay as Westend, WestendRelayReceiver as WestendReceiver,
|
||||
WestendRelaySender as WestendSender,
|
||||
};
|
||||
|
||||
pub const ASSET_ID: u32 = 1;
|
||||
pub const ASSET_MIN_BALANCE: u128 = 1000;
|
||||
// `Assets` pallet index
|
||||
pub const ASSETS_PALLET_ID: u8 = 50;
|
||||
|
||||
pub type RelayToSystemParaTest = Test<Westend, AssetHubWestend>;
|
||||
pub type SystemParaToRelayTest = Test<AssetHubWestend, Westend>;
|
||||
pub type SystemParaToParaTest = Test<AssetHubWestend, 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: Westend::child_location_of(AssetHubWestend::para_id()),
|
||||
beneficiary: AccountId32Junction {
|
||||
network: None,
|
||||
id: AssetHubWestendReceiver::get().into(),
|
||||
}
|
||||
.into(),
|
||||
amount,
|
||||
assets: (Here, amount).into(),
|
||||
asset_id: None,
|
||||
fee_asset_item: 0,
|
||||
weight_limit: WeightLimit::Unlimited,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests
|
||||
pub fn system_para_test_args(
|
||||
dest: MultiLocation,
|
||||
beneficiary_id: AccountId32,
|
||||
amount: Balance,
|
||||
assets: MultiAssets,
|
||||
asset_id: Option<u32>,
|
||||
) -> TestArgs {
|
||||
TestArgs {
|
||||
dest,
|
||||
beneficiary: AccountId32Junction { network: None, id: beneficiary_id.into() }.into(),
|
||||
amount,
|
||||
assets,
|
||||
asset_id,
|
||||
fee_asset_item: 0,
|
||||
weight_limit: WeightLimit::Unlimited,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// 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;
|
||||
mod treasury;
|
||||
+447
@@ -0,0 +1,447 @@
|
||||
// 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_westend_runtime::xcm_config::XcmConfig;
|
||||
use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig;
|
||||
|
||||
fn relay_origin_assertions(t: RelayToSystemParaTest) {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
|
||||
Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(629_384_000, 6_196)));
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to System Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => {
|
||||
from: *from == t.sender.account_id,
|
||||
to: *to == Westend::sovereign_account_id_of(
|
||||
t.args.dest
|
||||
),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_dest_assertions(_t: RelayToSystemParaTest) {
|
||||
AssetHubWestend::assert_dmp_queue_incomplete(Some(Weight::from_parts(31_352_000, 1489)));
|
||||
}
|
||||
|
||||
fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) {
|
||||
AssetHubWestend::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier))
|
||||
}
|
||||
|
||||
fn system_para_to_para_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
|
||||
676_119_000,
|
||||
6196,
|
||||
)));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereing account
|
||||
RuntimeEvent::Balances(
|
||||
pallet_balances::Event::Transfer { from, to, amount }
|
||||
) => {
|
||||
from: *from == t.sender.account_id,
|
||||
to: *to == AssetHubWestend::sovereign_account_id_of(
|
||||
t.args.dest
|
||||
),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
|
||||
676_119_000,
|
||||
6196,
|
||||
)));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereing account
|
||||
RuntimeEvent::Assets(
|
||||
pallet_assets::Event::Transferred { asset_id, from, to, amount }
|
||||
) => {
|
||||
asset_id: *asset_id == ASSET_ID,
|
||||
from: *from == t.sender.account_id,
|
||||
to: *to == AssetHubWestend::sovereign_account_id_of(
|
||||
t.args.dest
|
||||
),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
<Westend as WestendPallet>::XcmPallet::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
<Westend as WestendPallet>::XcmPallet::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't
|
||||
/// work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = WESTEND_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: WestendSender::get(),
|
||||
receiver: AssetHubWestendReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Westend>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubWestend>(system_para_dest_assertions);
|
||||
test.set_dispatchable::<Westend>(relay_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Westend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<WestendXcmConfig 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 = AssetHubWestend::parent_location();
|
||||
let beneficiary_id = WestendReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(system_para_to_relay_assertions);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
|
||||
#[test]
|
||||
fn reserve_transfer_native_asset_from_relay_to_system_para_fails() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = WESTEND_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: WestendSender::get(),
|
||||
receiver: AssetHubWestendReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Westend>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubWestend>(system_para_dest_assertions);
|
||||
test.set_dispatchable::<Westend>(relay_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Westend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<WestendXcmConfig 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 = AssetHubWestend::parent_location();
|
||||
let beneficiary_id = WestendReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(system_para_to_relay_assertions);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from System Parachain to Parachain should work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_system_para_to_para() {
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubWestend::sibling_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: 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::<AssetHubWestend>(system_para_to_para_assertions);
|
||||
// TODO: Add assertion for Penpal runtime. Right now message is failing with
|
||||
// `UntrustedReserveLocation`
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<<XcmConfig 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 = AssetHubWestend::sibling_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: 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::<AssetHubWestend>(system_para_to_para_assertions);
|
||||
// TODO: Add assertion for Penpal runtime. Right now message is failing with
|
||||
// `UntrustedReserveLocation`
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_to_para_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<<XcmConfig 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
|
||||
AssetHubWestend::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
AssetHubWestendSender::get(),
|
||||
Some(Weight::from_parts(1_019_445_000, 200_000)),
|
||||
ASSET_MIN_BALANCE * 1000000,
|
||||
);
|
||||
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubWestend::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: AssetHubWestendSender::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::<AssetHubWestend>(system_para_to_para_assets_assertions);
|
||||
// TODO: Add assertions when Penpal is able to manage assets
|
||||
system_para_test
|
||||
.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
system_para_test.assert();
|
||||
}
|
||||
|
||||
/// Reserve Transfers of a local asset from System Parachain to Parachain should work
|
||||
#[test]
|
||||
fn reserve_transfer_asset_from_system_para_to_para() {
|
||||
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
|
||||
AssetHubWestend::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
AssetHubWestendSender::get(),
|
||||
Some(Weight::from_parts(1_019_445_000, 200_000)),
|
||||
ASSET_MIN_BALANCE * 1000000,
|
||||
);
|
||||
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubWestend::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: AssetHubWestendSender::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::<AssetHubWestend>(system_para_to_para_assets_assertions);
|
||||
// TODO: Add assertions when Penpal is able to manage assets
|
||||
system_para_test
|
||||
.set_dispatchable::<AssetHubWestend>(system_para_to_para_reserve_transfer_assets);
|
||||
system_para_test.assert();
|
||||
}
|
||||
+104
@@ -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() {
|
||||
AssetHubWestend::force_create_asset_from_relay_as_root(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
AssetHubWestendSender::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 = AssetHubWestend::sovereign_account_id_of(
|
||||
AssetHubWestend::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
|
||||
// Force create and mint assets for Parachain's sovereign account
|
||||
AssetHubWestend::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
para_sovereign_account.clone(),
|
||||
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 = AssetHubWestend::force_create_asset_call(
|
||||
ASSET_ID,
|
||||
para_sovereign_account.clone(),
|
||||
true,
|
||||
ASSET_MIN_BALANCE,
|
||||
);
|
||||
|
||||
let origin_kind = OriginKind::SovereignAccount;
|
||||
let fee_amount = ASSET_MIN_BALANCE * 1000000;
|
||||
let native_asset =
|
||||
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), fee_amount).into();
|
||||
|
||||
let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
|
||||
let system_para_destination = PenpalA::sibling_location_of(AssetHubWestend::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();
|
||||
});
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts(
|
||||
16_290_336_000,
|
||||
562_893,
|
||||
)));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
|
||||
asset_id: *asset_id == ASSET_ID,
|
||||
owner: *owner == para_sovereign_account,
|
||||
balance: *balance == fee_amount,
|
||||
},
|
||||
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
|
||||
asset_id: *asset_id == ASSET_ID,
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
// 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 = <Westend as Chain>::RuntimeOrigin::root();
|
||||
let system_para_destination: MultiLocation =
|
||||
Westend::child_location_of(AssetHubWestend::para_id());
|
||||
|
||||
// Relay Chain sets supported version for Asset Parachain
|
||||
Westend::execute_with(|| {
|
||||
assert_ok!(<Westend as WestendPallet>::XcmPallet::force_xcm_version(
|
||||
sudo_origin,
|
||||
bx!(system_para_destination),
|
||||
XCM_V3
|
||||
));
|
||||
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
RuntimeEvent::XcmPallet(pallet_xcm::Event::SupportedVersionChanged {
|
||||
location,
|
||||
version: XCM_V3
|
||||
}) => { location: *location == system_para_destination, },
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn system_para_sets_relay_xcm_supported_version() {
|
||||
// Init test variables
|
||||
let parent_location = AssetHubWestend::parent_location();
|
||||
let force_xcm_version_call =
|
||||
<AssetHubWestend as Chain>::RuntimeCall::PolkadotXcm(pallet_xcm::Call::<
|
||||
<AssetHubWestend as Chain>::Runtime,
|
||||
>::force_xcm_version {
|
||||
location: bx!(parent_location),
|
||||
version: XCM_V3,
|
||||
})
|
||||
.encode()
|
||||
.into();
|
||||
|
||||
// System Parachain sets supported version for Relay Chain through it
|
||||
Westend::send_unpaid_transact_to_parachain_as_root(
|
||||
AssetHubWestend::para_id(),
|
||||
force_xcm_version_call,
|
||||
);
|
||||
|
||||
// System Parachain receive the XCM message
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(
|
||||
1_019_210_000,
|
||||
200_000,
|
||||
)));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::SupportedVersionChanged {
|
||||
location,
|
||||
version: XCM_V3
|
||||
}) => { location: *location == parent_location, },
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
+350
@@ -0,0 +1,350 @@
|
||||
// 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 swap_locally_on_chain_using_local_assets() {
|
||||
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
|
||||
let asset_one = Box::new(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())),
|
||||
});
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::create(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
ASSET_ID.into(),
|
||||
AssetHubWestendSender::get().into(),
|
||||
1000,
|
||||
));
|
||||
assert!(<AssetHubWestend as AssetHubWestendPallet>::Assets::asset_exists(ASSET_ID));
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::mint(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
ASSET_ID.into(),
|
||||
AssetHubWestendSender::get().into(),
|
||||
3_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
asset_native.clone(),
|
||||
asset_one.clone(),
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
asset_native.clone(),
|
||||
asset_one.clone(),
|
||||
1_000_000_000_000,
|
||||
2_000_000_000_000,
|
||||
0,
|
||||
0,
|
||||
AssetHubWestendSender::get().into()
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
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!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
path,
|
||||
100,
|
||||
1,
|
||||
AssetHubWestendSender::get().into(),
|
||||
true
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. }) => {
|
||||
amount_in: *amount_in == 100,
|
||||
amount_out: *amount_out == 199,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
asset_native,
|
||||
asset_one,
|
||||
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
|
||||
0,
|
||||
0,
|
||||
AssetHubWestendSender::get().into(),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swap_locally_on_chain_using_foreign_assets() {
|
||||
use frame_support::weights::WeightToFee;
|
||||
|
||||
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
|
||||
|
||||
let foreign_asset1_at_asset_hub_westend = Box::new(MultiLocation {
|
||||
parents: 1,
|
||||
interior: X3(
|
||||
Parachain(PenpalA::para_id().into()),
|
||||
PalletInstance(ASSETS_PALLET_ID),
|
||||
GeneralIndex(ASSET_ID.into()),
|
||||
),
|
||||
});
|
||||
|
||||
let assets_para_destination: VersionedMultiLocation =
|
||||
MultiLocation { parents: 1, interior: X1(Parachain(AssetHubWestend::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_westend:
|
||||
|
||||
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_westend = AssetHubWestend::sovereign_account_id_of(penpal_location);
|
||||
|
||||
AssetHubWestend::fund_accounts(vec![
|
||||
(AssetHubWestendSender::get().into(), 5_000_000 * WESTEND_ED),
|
||||
(sov_penpal_on_asset_hub_westend.clone().into(), 1000_000_000_000_000_000 * WESTEND_ED),
|
||||
]);
|
||||
|
||||
let sov_penpal_on_asset_hub_westend_as_location: MultiLocation = MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(AccountId32Junction {
|
||||
network: None,
|
||||
id: sov_penpal_on_asset_hub_westend.clone().into(),
|
||||
}),
|
||||
};
|
||||
|
||||
let call_foreign_assets_create =
|
||||
<AssetHubWestend as Chain>::RuntimeCall::ForeignAssets(pallet_assets::Call::<
|
||||
<AssetHubWestend as Chain>::Runtime,
|
||||
Instance2,
|
||||
>::create {
|
||||
id: *foreign_asset1_at_asset_hub_westend,
|
||||
min_balance: 1000,
|
||||
admin: sov_penpal_on_asset_hub_westend.clone().into(),
|
||||
})
|
||||
.encode()
|
||||
.into();
|
||||
|
||||
let buy_execution_fee_amount = parachains_common::westend::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_westend_as_location,
|
||||
},
|
||||
]));
|
||||
|
||||
// Send XCM message from penpal => asset_hub_westend
|
||||
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 in the next block.
|
||||
AssetHubWestend::execute_with(|| {
|
||||
assert!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::asset_exists(
|
||||
*foreign_asset1_at_asset_hub_westend
|
||||
));
|
||||
|
||||
// 3: Mint foreign asset on asset_hub_westend:
|
||||
//
|
||||
// (While it might be nice to use batch,
|
||||
// currently that's disabled due to safe call filters.)
|
||||
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
// 3. Mint foreign asset (in reality this should be a teleport or some such)
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::mint(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(
|
||||
sov_penpal_on_asset_hub_westend.clone().into()
|
||||
),
|
||||
*foreign_asset1_at_asset_hub_westend,
|
||||
sov_penpal_on_asset_hub_westend.clone().into(),
|
||||
3_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
// 4. Create pool:
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
asset_native.clone(),
|
||||
foreign_asset1_at_asset_hub_westend.clone(),
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
// 5. Add liquidity:
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(
|
||||
sov_penpal_on_asset_hub_westend.clone()
|
||||
),
|
||||
asset_native.clone(),
|
||||
foreign_asset1_at_asset_hub_westend.clone(),
|
||||
1_000_000_000_000,
|
||||
2_000_000_000_000,
|
||||
0,
|
||||
0,
|
||||
sov_penpal_on_asset_hub_westend.clone().into()
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
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_westend.clone(),
|
||||
]);
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
path,
|
||||
100000,
|
||||
1000,
|
||||
AssetHubWestendSender::get().into(),
|
||||
true
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
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!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(
|
||||
sov_penpal_on_asset_hub_westend.clone()
|
||||
),
|
||||
asset_native,
|
||||
foreign_asset1_at_asset_hub_westend,
|
||||
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
|
||||
0,
|
||||
0,
|
||||
sov_penpal_on_asset_hub_westend.clone().into(),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cannot_create_pool_from_pool_assets() {
|
||||
let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get());
|
||||
let mut asset_one = asset_hub_westend_runtime::xcm_config::PoolAssetsPalletLocation::get();
|
||||
asset_one.append_with(GeneralIndex(ASSET_ID.into())).expect("pool assets");
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
let pool_owner_account_id = asset_hub_westend_runtime::AssetConversionOrigin::get();
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::create(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(pool_owner_account_id.clone()),
|
||||
ASSET_ID.into(),
|
||||
pool_owner_account_id.clone().into(),
|
||||
1000,
|
||||
));
|
||||
assert!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::asset_exists(ASSET_ID));
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PoolAssets::mint(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(pool_owner_account_id),
|
||||
ASSET_ID.into(),
|
||||
AssetHubWestendSender::get().into(),
|
||||
3_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_matches::assert_matches!(
|
||||
<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
asset_native.clone(),
|
||||
Box::new(asset_one),
|
||||
),
|
||||
Err(DispatchError::Module(ModuleError{index: _, error: _, message})) => assert_eq!(message, Some("UnsupportedAsset"))
|
||||
);
|
||||
});
|
||||
}
|
||||
+409
@@ -0,0 +1,409 @@
|
||||
// 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_westend_runtime::xcm_config::XcmConfig as AssetHubWestendXcmConfig;
|
||||
use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig;
|
||||
|
||||
fn relay_origin_assertions(t: RelayToSystemParaTest) {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
|
||||
Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(632_207_000, 7_186)));
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
// Amount to teleport is withdrawn from Sender
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
|
||||
who: *who == t.sender.account_id,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
// Amount to teleport is deposited in Relay's `CheckAccount`
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, amount }) => {
|
||||
who: *who == <Westend as WestendPallet>::XcmPallet::check_account(),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_dest_assertions(t: SystemParaToRelayTest) {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
|
||||
Westend::assert_ump_queue_processed(
|
||||
true,
|
||||
Some(AssetHubWestend::para_id()),
|
||||
Some(Weight::from_parts(308_222_000, 7_186)),
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
// Amount is witdrawn from Relay Chain's `CheckAccount`
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
|
||||
who: *who == <Westend as WestendPallet>::XcmPallet::check_account(),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
// Amount minus fees are deposited in Receiver's account
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
|
||||
who: *who == t.receiver.account_id,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) {
|
||||
Westend::assert_ump_queue_processed(
|
||||
false,
|
||||
Some(AssetHubWestend::para_id()),
|
||||
Some(Weight::from_parts(148_705_000, 3_593)),
|
||||
);
|
||||
}
|
||||
|
||||
fn para_origin_assertions(t: SystemParaToRelayTest) {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
|
||||
533_910_000,
|
||||
7167,
|
||||
)));
|
||||
|
||||
AssetHubWestend::assert_parachain_system_ump_sent();
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
// Amount is withdrawn from Sender's account
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
|
||||
who: *who == t.sender.account_id,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn para_dest_assertions(t: RelayToSystemParaTest) {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(164_793_000, 3593)));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
// Amount minus fees are deposited in Receiver's account
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
|
||||
who: *who == t.receiver.account_id,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_limited_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
<Westend as WestendPallet>::XcmPallet::limited_teleport_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn relay_teleport_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
<Westend as WestendPallet>::XcmPallet::teleport_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_limited_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_teleport_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::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 = WESTEND_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: WestendSender::get(),
|
||||
receiver: AssetHubWestendReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Westend>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubWestend>(para_dest_assertions);
|
||||
test.set_dispatchable::<Westend>(relay_limited_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Westend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<WestendXcmConfig 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_WESTEND_ED * 1000;
|
||||
let destination = AssetHubWestend::parent_location();
|
||||
let beneficiary_id = WestendReceiver::get();
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(para_origin_assertions);
|
||||
test.set_assertion::<Westend>(relay_dest_assertions);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_limited_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<AssetHubWestendXcmConfig 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_WESTEND_ED * 1000;
|
||||
let destination = AssetHubWestend::parent_location().into();
|
||||
let beneficiary_id = WestendReceiver::get().into();
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(para_origin_assertions);
|
||||
test.set_assertion::<Westend>(relay_dest_assertions_fail);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_limited_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<AssetHubWestendXcmConfig 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 = WESTEND_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: WestendSender::get(),
|
||||
receiver: AssetHubWestendReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Westend>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubWestend>(para_dest_assertions);
|
||||
test.set_dispatchable::<Westend>(relay_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Westend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<WestendXcmConfig 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_WESTEND_ED * 1000;
|
||||
let destination = AssetHubWestend::parent_location();
|
||||
let beneficiary_id = WestendReceiver::get();
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(para_origin_assertions);
|
||||
test.set_assertion::<Westend>(relay_dest_assertions);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<AssetHubWestendXcmConfig 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 Parachain to Relay Chain
|
||||
/// shouldn't work when there is not enough balance in Relay Chain's `CheckAccount`
|
||||
#[test]
|
||||
fn teleport_native_assets_from_system_para_to_relay_fails() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let destination = AssetHubWestend::parent_location();
|
||||
let beneficiary_id = WestendReceiver::get();
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(para_origin_assertions);
|
||||
test.set_assertion::<Westend>(relay_dest_assertions_fail);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_teleport_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<AssetHubWestendXcmConfig 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);
|
||||
}
|
||||
|
||||
// TODO: uncomment when CollectivesWestend and BridgeHubWestend are implemented
|
||||
// https://github.com/paritytech/polkadot-sdk/pull/1737 (CollectivesWestend)
|
||||
// #[test]
|
||||
// fn teleport_to_other_system_parachains_works() {
|
||||
// let amount = ASSET_HUB_WESTEND_ED * 100;
|
||||
// let native_asset: VersionedMultiAssets = (Parent, amount).into();
|
||||
|
||||
// test_parachain_is_trusted_teleporter!(
|
||||
// AssetHubWestend, // Origin
|
||||
// vec![CollectivesWestend, BridgeHubWestend], // Destinations
|
||||
// (native_asset, amount)
|
||||
// );
|
||||
// }
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
// 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 emulated_integration_tests_common::accounts::{ALICE, BOB};
|
||||
use frame_support::traits::fungibles::{Create, Inspect, Mutate};
|
||||
use polkadot_runtime_common::impls::VersionedLocatableAsset;
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
#[test]
|
||||
fn create_and_claim_treasury_spend() {
|
||||
const ASSET_ID: u32 = 1984;
|
||||
const SPEND_AMOUNT: u128 = 1_000_000;
|
||||
// treasury location from a sibling parachain.
|
||||
let treasury_location: MultiLocation = MultiLocation::new(1, PalletInstance(37));
|
||||
// treasury account on a sibling parachain.
|
||||
let treasury_account =
|
||||
asset_hub_westend_runtime::xcm_config::LocationToAccountId::convert_location(
|
||||
&treasury_location,
|
||||
)
|
||||
.unwrap();
|
||||
let asset_hub_location = MultiLocation::new(0, Parachain(AssetHubWestend::para_id().into()));
|
||||
let root = <Westend as Chain>::RuntimeOrigin::root();
|
||||
// asset kind to be spend from the treasury.
|
||||
let asset_kind = VersionedLocatableAsset::V3 {
|
||||
location: asset_hub_location,
|
||||
asset_id: AssetId::Concrete((PalletInstance(50), GeneralIndex(ASSET_ID.into())).into()),
|
||||
};
|
||||
// treasury spend beneficiary.
|
||||
let alice: AccountId = Westend::account_id_of(ALICE);
|
||||
let bob: AccountId = Westend::account_id_of(BOB);
|
||||
let bob_signed = <Westend as Chain>::RuntimeOrigin::signed(bob.clone());
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type Assets = <AssetHubWestend as AssetHubWestendPallet>::Assets;
|
||||
|
||||
// create an asset class and mint some assets to the treasury account.
|
||||
assert_ok!(<Assets as Create<_>>::create(
|
||||
ASSET_ID,
|
||||
treasury_account.clone(),
|
||||
true,
|
||||
SPEND_AMOUNT / 2
|
||||
));
|
||||
assert_ok!(<Assets as Mutate<_>>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4));
|
||||
// beneficiary has zero balance.
|
||||
assert_eq!(<Assets as Inspect<_>>::balance(ASSET_ID, &alice,), 0u128,);
|
||||
});
|
||||
|
||||
Westend::execute_with(|| {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
type Treasury = <Westend as WestendPallet>::Treasury;
|
||||
type AssetRate = <Westend as WestendPallet>::AssetRate;
|
||||
|
||||
// create a conversion rate from `asset_kind` to the native currency.
|
||||
assert_ok!(AssetRate::create(root.clone(), Box::new(asset_kind.clone()), 2.into()));
|
||||
|
||||
// create and approve a treasury spend.
|
||||
assert_ok!(Treasury::spend(
|
||||
root,
|
||||
Box::new(asset_kind),
|
||||
SPEND_AMOUNT,
|
||||
Box::new(MultiLocation::new(0, Into::<[u8; 32]>::into(alice.clone())).into()),
|
||||
None,
|
||||
));
|
||||
// claim the spend.
|
||||
assert_ok!(Treasury::payout(bob_signed.clone(), 0));
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
type Assets = <AssetHubWestend as AssetHubWestendPallet>::Assets;
|
||||
|
||||
// assert events triggered by xcm pay program
|
||||
// 1. treasury asset transferred to spend beneficiary
|
||||
// 2. response to Relay Chain treasury pallet instance sent back
|
||||
// 3. XCM program completed
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => {
|
||||
id: id == &ASSET_ID,
|
||||
from: from == &treasury_account,
|
||||
to: to == &alice,
|
||||
amount: amount == &SPEND_AMOUNT,
|
||||
},
|
||||
RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {},
|
||||
]
|
||||
);
|
||||
// beneficiary received the assets from the treasury.
|
||||
assert_eq!(<Assets as Inspect<_>>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,);
|
||||
});
|
||||
|
||||
Westend::execute_with(|| {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
type Treasury = <Westend as WestendPallet>::Treasury;
|
||||
|
||||
// check the payment status to ensure the response from the AssetHub was received.
|
||||
assert_ok!(Treasury::check_status(bob_signed, 0));
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
RuntimeEvent::Treasury(pallet_treasury::Event::SpendProcessed { .. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user