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
@@ -21,7 +21,7 @@ pub use xcm::{
prelude::{AccountId32 as AccountId32Junction, *},
v3::{
Error,
NetworkId::{Rococo as RococoId, Wococo as WococoId},
NetworkId::{Rococo as RococoId, Westend as WestendId},
},
};
@@ -30,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,
@@ -39,17 +41,22 @@ pub use emulated_integration_tests_common::{
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_wococo_system_emulated_network::{
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
},
asset_hub_westend_emulated_chain::{
genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet,
},
bridge_hub_rococo_emulated_chain::{
genesis::ED as BRIDGE_HUB_ROCOCO_ED, BridgeHubRococoParaPallet as BridgeHubRococoPallet,
},
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
rococo_emulated_chain::RococoRelayPallet as RococoPallet,
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWococoPara as AssetHubWococo,
BridgeHubRococoPara as BridgeHubRococo, BridgeHubRococoParaReceiver as BridgeHubRococoReceiver,
BridgeHubRococoParaSender as BridgeHubRococoSender, BridgeHubWococoPara as BridgeHubWococo,
RococoRelay as Rococo, RococoRelayReceiver as RococoReceiver,
RococoRelaySender as RococoSender,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaSender as BridgeHubRococoSender, BridgeHubWestendPara as BridgeHubWestend,
RococoRelay as Rococo,
};
pub const ASSET_ID: u32 = 1;
@@ -0,0 +1,219 @@
// 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_rococo_to_asset_hub_westend(id: MultiLocation, amount: u128) {
let signed_origin =
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get().into());
let asset_hub_westend_para_id = AssetHubWestend::para_id().into();
let destination = MultiLocation {
parents: 2,
interior: X2(GlobalConsensus(NetworkId::Westend), Parachain(asset_hub_westend_para_id)),
};
let beneficiary_id = AssetHubWestendReceiver::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 AHR's SA on BHR for paying bridge transport fees
let ahr_as_seen_by_bhr = BridgeHubRococo::sibling_location_of(AssetHubRococo::para_id());
let sov_ahr_on_bhr = BridgeHubRococo::sovereign_account_id_of(ahr_as_seen_by_bhr);
BridgeHubRococo::fund_accounts(vec![(sov_ahr_on_bhr.into(), 10_000_000_000_000u128)]);
AssetHubRococo::execute_with(|| {
assert_ok!(
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::limited_reserve_transfer_assets(
signed_origin,
bx!(destination.into()),
bx!(beneficiary.into()),
bx!(assets.into()),
fee_asset_item,
WeightLimit::Unlimited,
)
);
});
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubRococo,
vec![
// pay for bridge fees
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { .. }) => {},
// message exported
RuntimeEvent::BridgeWestendMessages(
pallet_bridge_messages::Event::MessageAccepted { .. }
) => {},
// message processed successfully
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
BridgeHubWestend::execute_with(|| {
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubWestend,
vec![
// message dispatched successfully
RuntimeEvent::XcmpQueue(
cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }
) => {},
]
);
});
}
#[test]
fn send_rocs_from_asset_hub_rococo_to_asset_hub_westend() {
let roc_at_asset_hub_rococo: MultiLocation = Parent.into();
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![],
);
let sov_ahw_on_ahr = AssetHubRococo::sovereign_account_of_parachain_on_other_global_consensus(
NetworkId::Westend,
AssetHubWestend::para_id(),
);
let rocs_in_reserve_on_ahr_before =
<AssetHubRococo as Chain>::account_data_of(sov_ahw_on_ahr.clone()).free;
let sender_rocs_before =
<AssetHubRococo as Chain>::account_data_of(AssetHubRococoSender::get()).free;
let receiver_rocs_before = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(roc_at_asset_hub_westend, &AssetHubWestendReceiver::get())
});
let amount = ASSET_HUB_ROCOCO_ED * 1_000;
send_asset_from_asset_hub_rococo_to_asset_hub_westend(roc_at_asset_hub_rococo, amount);
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubWestend,
vec![
// issue ROCs on AHW
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => {
asset_id: *asset_id == roc_at_asset_hub_rococo,
owner: *owner == AssetHubWestendReceiver::get(),
},
// message processed successfully
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
let sender_rocs_after =
<AssetHubRococo as Chain>::account_data_of(AssetHubRococoSender::get()).free;
let receiver_rocs_after = AssetHubWestend::execute_with(|| {
type Assets = <AssetHubWestend as AssetHubWestendPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(roc_at_asset_hub_westend, &AssetHubWestendReceiver::get())
});
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);
}
#[test]
fn send_wnds_from_asset_hub_rococo_to_asset_hub_westend() {
let prefund_amount = 10_000_000_000_000u128;
let wnd_at_asset_hub_rococo =
MultiLocation { parents: 2, interior: X1(GlobalConsensus(NetworkId::Westend)) };
let owner: AccountId = AssetHubWestend::account_id_of(ALICE);
AssetHubRococo::force_create_foreign_asset(
wnd_at_asset_hub_rococo,
owner,
true,
ASSET_MIN_BALANCE,
vec![(AssetHubRococoSender::get(), prefund_amount)],
);
// fund the AHR's SA on AHW with the WND tokens held in reserve
let sov_ahr_on_ahw = AssetHubWestend::sovereign_account_of_parachain_on_other_global_consensus(
NetworkId::Rococo,
AssetHubRococo::para_id(),
);
AssetHubWestend::fund_accounts(vec![(sov_ahr_on_ahw.clone(), prefund_amount)]);
let wnds_in_reserve_on_ahw_before =
<AssetHubWestend as Chain>::account_data_of(sov_ahr_on_ahw.clone()).free;
assert_eq!(wnds_in_reserve_on_ahw_before, prefund_amount);
let sender_wnds_before = AssetHubRococo::execute_with(|| {
type Assets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(wnd_at_asset_hub_rococo, &AssetHubRococoSender::get())
});
assert_eq!(sender_wnds_before, prefund_amount);
let receiver_wnds_before =
<AssetHubWestend as Chain>::account_data_of(AssetHubWestendReceiver::get()).free;
let amount_to_send = ASSET_HUB_WESTEND_ED * 1_000;
send_asset_from_asset_hub_rococo_to_asset_hub_westend(wnd_at_asset_hub_rococo, amount_to_send);
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubWestend,
vec![
// WND is withdrawn from AHR's SA on AHW
RuntimeEvent::Balances(
pallet_balances::Event::Withdraw { who, amount }
) => {
who: *who == sov_ahr_on_ahw,
amount: *amount == amount_to_send,
},
// WNDs deposited to beneficiary
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == AssetHubWestendReceiver::get(),
},
// message processed successfully
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});
let sender_wnds_after = AssetHubRococo::execute_with(|| {
type Assets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(wnd_at_asset_hub_rococo, &AssetHubRococoSender::get())
});
let receiver_wnds_after =
<AssetHubWestend as Chain>::account_data_of(AssetHubWestendReceiver::get()).free;
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 reduced by sent amount
assert_eq!(wnds_in_reserve_on_ahw_after, wnds_in_reserve_on_ahw_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_rococo_relay_to_westend_asset_hub() {
// Init tests variables
// XcmPallet send arguments
let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
@@ -29,13 +29,13 @@ fn example() {
let xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit, check_origin },
ExportMessage {
network: WococoId,
destination: X1(Parachain(AssetHubWococo::para_id().into())),
network: WestendId,
destination: X1(Parachain(AssetHubWestend::para_id().into())),
xcm: remote_xcm,
},
]));
//Rococo Global Consensus
// Rococo Global Consensus
// Send XCM message from Relay Chain to Bridge Hub source Parachain
Rococo::execute_with(|| {
assert_ok!(<Rococo as RococoPallet>::XcmPallet::send(
@@ -64,32 +64,32 @@ fn example() {
success: true,
..
}) => {},
RuntimeEvent::BridgeWococoMessages(pallet_bridge_messages::Event::MessageAccepted {
lane_id: LaneId([0, 0, 0, 1]),
RuntimeEvent::BridgeWestendMessages(pallet_bridge_messages::Event::MessageAccepted {
lane_id: LaneId([0, 0, 0, 2]),
nonce: 1,
}) => {},
]
);
});
// Wococo GLobal Consensus
// Westend Global Consensus
// Receive XCM message in Bridge Hub target Parachain
BridgeHubWococo::execute_with(|| {
type RuntimeEvent = <BridgeHubWococo as Chain>::RuntimeEvent;
BridgeHubWestend::execute_with(|| {
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubWococo,
BridgeHubWestend,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});
// Receive embeded XCM message within `ExportMessage` in Parachain destination
AssetHubWococo::execute_with(|| {
type RuntimeEvent = <AssetHubWococo as Chain>::RuntimeEvent;
// Receive embedded XCM message within `ExportMessage` in Parachain destination
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubWococo,
AssetHubWestend,
vec![
RuntimeEvent::MessageQueue(pallet_message_queue::Event::ProcessingFailed {
..