xcm-emulator: add Rococo<>Westend bridge and add tests for assets transfers over the bridge (#2251)

- switch from Rococo<>Wococo to Rococo<>Westend bridge
- add bidirectional simple tests
- remove Wococo chains from xcm-emulator
- added tests for assets transfers over Rococo<>Westend bridge 

fixes https://github.com/paritytech/parity-bridges-common/issues/2405
This commit is contained in:
Adrian Catangiu
2023-11-14 14:47:04 +02:00
committed by GitHub
parent a393cfcb28
commit 39cc95740a
30 changed files with 711 additions and 469 deletions
@@ -11,7 +11,9 @@ publish = false
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
# Substrate
frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false}
frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false }
pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false }
pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false }
pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue" }
# Polkadot
@@ -30,4 +32,4 @@ cumulus-pallet-xcmp-queue = { path = "../../../../../../pallets/xcmp-queue", def
cumulus-pallet-dmp-queue = { path = "../../../../../../pallets/dmp-queue", default-features = false}
bridge-hub-westend-runtime = { path = "../../../../../../parachains/runtimes/bridge-hubs/bridge-hub-westend", default-features = false }
emulated-integration-tests-common = { path = "../../../common", default-features = false}
westend-system-emulated-network ={ path = "../../../networks/westend-system" }
rococo-westend-system-emulated-network = { path = "../../../networks/rococo-westend-system" }
@@ -19,7 +19,10 @@ pub use frame_support::assert_ok;
// Polkadot
pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{Error, NetworkId::Rococo as RococoId},
v3::{
Error,
NetworkId::{Rococo as RococoId, Westend as WestendId},
},
};
// Bridges
@@ -27,6 +30,8 @@ pub use bp_messages::LaneId;
// Cumulus
pub use emulated_integration_tests_common::{
accounts::ALICE,
impls::Inspect,
test_parachain_is_trusted_teleporter,
xcm_emulator::{
assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para,
@@ -36,16 +41,22 @@ pub use emulated_integration_tests_common::{
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use westend_system_emulated_network::{
bridge_hub_westend_emulated_chain::{
genesis::ED as BRIDGE_HUB_ROCOCO_ED, BridgeHubWestendParaPallet as BridgeHubWestendPallet,
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
westend_emulated_chain::{genesis::ED as ROCOCO_ED, WestendRelayPallet as WestendPallet},
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
bridge_hub_westend_emulated_chain::{
genesis::ED as BRIDGE_HUB_WESTEND_ED, BridgeHubWestendParaPallet as BridgeHubWestendPallet,
},
westend_emulated_chain::WestendRelayPallet as WestendPallet,
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend,
BridgeHubWestendParaReceiver as BridgeHubWestendReceiver,
BridgeHubWestendParaSender as BridgeHubWestendSender, WestendRelay as Westend,
WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender,
AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubWestendPara as BridgeHubWestend, BridgeHubWestendParaSender as BridgeHubWestendSender,
WestendRelay as Westend,
};
pub const ASSET_ID: u32 = 1;
@@ -0,0 +1,218 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
fn send_asset_from_asset_hub_westend_to_asset_hub_rococo(id: MultiLocation, amount: u128) {
let signed_origin =
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get().into());
let asset_hub_rococo_para_id = AssetHubRococo::para_id().into();
let destination = MultiLocation {
parents: 2,
interior: X2(GlobalConsensus(NetworkId::Rococo), Parachain(asset_hub_rococo_para_id)),
};
let beneficiary_id = AssetHubRococoReceiver::get();
let beneficiary: MultiLocation =
AccountId32Junction { network: None, id: beneficiary_id.into() }.into();
let assets: MultiAssets = (id, amount).into();
let fee_asset_item = 0;
// fund the AHW's SA on BHW for paying bridge transport fees
let ahw_as_seen_by_bhw = BridgeHubWestend::sibling_location_of(AssetHubWestend::para_id());
let sov_ahw_on_bhw = BridgeHubWestend::sovereign_account_id_of(ahw_as_seen_by_bhw);
BridgeHubWestend::fund_accounts(vec![(sov_ahw_on_bhw.into(), 10_000_000_000_000u128)]);
AssetHubWestend::execute_with(|| {
assert_ok!(
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
signed_origin,
bx!(destination.into()),
bx!(beneficiary.into()),
bx!(assets.into()),
fee_asset_item,
WeightLimit::Unlimited,
)
);
});
BridgeHubWestend::execute_with(|| {
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubWestend,
vec![
// pay for bridge fees
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { .. }) => {},
// message exported
RuntimeEvent::BridgeRococoMessages(
pallet_bridge_messages::Event::MessageAccepted { .. }
) => {},
// message processed successfully
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubRococo,
vec![
// message dispatched successfully
RuntimeEvent::XcmpQueue(
cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }
) => {},
]
);
});
}
#[test]
fn send_wnds_from_asset_hub_westend_to_asset_hub_rococo() {
let wnd_at_asset_hub_westend: MultiLocation = Parent.into();
let wnd_at_asset_hub_rococo =
MultiLocation { parents: 2, interior: X1(GlobalConsensus(NetworkId::Westend)) };
let owner: AccountId = AssetHubRococo::account_id_of(ALICE);
AssetHubRococo::force_create_foreign_asset(
wnd_at_asset_hub_rococo,
owner,
true,
ASSET_MIN_BALANCE,
vec![],
);
let sov_ahr_on_ahw = AssetHubWestend::sovereign_account_of_parachain_on_other_global_consensus(
NetworkId::Rococo,
AssetHubRococo::para_id(),
);
let wnds_in_reserve_on_ahw_before =
<AssetHubWestend as Chain>::account_data_of(sov_ahr_on_ahw.clone()).free;
let sender_wnds_before =
<AssetHubWestend as Chain>::account_data_of(AssetHubWestendSender::get()).free;
let receiver_wnds_before = AssetHubRococo::execute_with(|| {
type Assets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(wnd_at_asset_hub_rococo, &AssetHubRococoReceiver::get())
});
let amount = ASSET_HUB_WESTEND_ED * 1_000;
send_asset_from_asset_hub_westend_to_asset_hub_rococo(wnd_at_asset_hub_westend, amount);
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubRococo,
vec![
// issue WNDs on AHR
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => {
asset_id: *asset_id == wnd_at_asset_hub_rococo,
owner: *owner == AssetHubRococoReceiver::get(),
},
// message processed successfully
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
let sender_wnds_after =
<AssetHubWestend as Chain>::account_data_of(AssetHubWestendSender::get()).free;
let receiver_wnds_after = AssetHubRococo::execute_with(|| {
type Assets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(wnd_at_asset_hub_rococo, &AssetHubRococoReceiver::get())
});
let wnds_in_reserve_on_ahw_after =
<AssetHubWestend as Chain>::account_data_of(sov_ahr_on_ahw).free;
// Sender's balance is reduced
assert!(sender_wnds_before > sender_wnds_after);
// Receiver's balance is increased
assert!(receiver_wnds_after > receiver_wnds_before);
// Reserve balance is increased by sent amount
assert_eq!(wnds_in_reserve_on_ahw_after, wnds_in_reserve_on_ahw_before + amount);
}
#[test]
fn send_rocs_from_asset_hub_westend_to_asset_hub_rococo() {
let prefund_amount = 10_000_000_000_000u128;
let roc_at_asset_hub_westend =
MultiLocation { parents: 2, interior: X1(GlobalConsensus(NetworkId::Rococo)) };
let owner: AccountId = AssetHubWestend::account_id_of(ALICE);
AssetHubWestend::force_create_foreign_asset(
roc_at_asset_hub_westend,
owner,
true,
ASSET_MIN_BALANCE,
vec![(AssetHubWestendSender::get(), prefund_amount)],
);
// fund the AHW's SA on AHR with the ROC tokens held in reserve
let sov_ahw_on_ahr = AssetHubRococo::sovereign_account_of_parachain_on_other_global_consensus(
NetworkId::Westend,
AssetHubWestend::para_id(),
);
AssetHubRococo::fund_accounts(vec![(sov_ahw_on_ahr.clone(), prefund_amount)]);
let rocs_in_reserve_on_ahr_before =
<AssetHubRococo as Chain>::account_data_of(sov_ahw_on_ahr.clone()).free;
assert_eq!(rocs_in_reserve_on_ahr_before, prefund_amount);
let sender_rocs_before = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(roc_at_asset_hub_westend, &AssetHubWestendSender::get())
});
assert_eq!(sender_rocs_before, prefund_amount);
let receiver_rocs_before =
<AssetHubRococo as Chain>::account_data_of(AssetHubRococoReceiver::get()).free;
let amount_to_send = ASSET_HUB_ROCOCO_ED * 1_000;
send_asset_from_asset_hub_westend_to_asset_hub_rococo(roc_at_asset_hub_westend, amount_to_send);
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubRococo,
vec![
// ROC is withdrawn from AHW's SA on AHR
RuntimeEvent::Balances(
pallet_balances::Event::Withdraw { who, amount }
) => {
who: *who == sov_ahw_on_ahr,
amount: *amount == amount_to_send,
},
// ROCs deposited to beneficiary
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == AssetHubRococoReceiver::get(),
},
// message processed successfully
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
let sender_rocs_after = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(roc_at_asset_hub_westend, &AssetHubWestendSender::get())
});
let receiver_rocs_after =
<AssetHubRococo as Chain>::account_data_of(AssetHubRococoReceiver::get()).free;
let rocs_in_reserve_on_ahr_after =
<AssetHubRococo as Chain>::account_data_of(sov_ahw_on_ahr.clone()).free;
// Sender's balance is reduced
assert!(sender_rocs_before > sender_rocs_after);
// Receiver's balance is increased
assert!(receiver_rocs_after > receiver_rocs_before);
// Reserve balance is reduced by sent amount
assert_eq!(rocs_in_reserve_on_ahr_after, rocs_in_reserve_on_ahr_before - amount_to_send);
}
@@ -13,5 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod example;
mod asset_transfers;
mod send_xcm;
mod teleport;
@@ -16,7 +16,7 @@
use crate::*;
#[test]
fn example() {
fn send_xcm_from_westend_relay_to_rococo_asset_hub() {
// Init tests variables
// XcmPallet send arguments
let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
@@ -30,7 +30,7 @@ fn example() {
UnpaidExecution { weight_limit, check_origin },
ExportMessage {
network: RococoId,
destination: X1(Parachain(AssetHubWestend::para_id().into())),
destination: X1(Parachain(AssetHubRococo::para_id().into())),
xcm: remote_xcm,
},
]));
@@ -71,4 +71,30 @@ fn example() {
]
);
});
// Rococo Global Consensus
// Receive XCM message in Bridge Hub target Parachain
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});
// Receive embedded XCM message within `ExportMessage` in Parachain destination
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::MessageQueue(pallet_message_queue::Event::ProcessingFailed {
..
}) => {},
]
);
});
}
@@ -18,7 +18,7 @@ use bridge_hub_westend_runtime::xcm_config::XcmConfig;
#[test]
fn teleport_to_other_system_parachains_works() {
let amount = BRIDGE_HUB_ROCOCO_ED * 100;
let amount = BRIDGE_HUB_WESTEND_ED * 100;
let native_asset: MultiAssets = (Parent, amount).into();
test_parachain_is_trusted_teleporter!(