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
Generated
+10 -68
View File
@@ -1119,22 +1119,6 @@ dependencies = [
"westend-runtime-constants",
]
[[package]]
name = "asset-hub-wococo-emulated-chain"
version = "0.0.0"
dependencies = [
"asset-hub-rococo-emulated-chain",
"asset-hub-rococo-runtime",
"cumulus-primitives-core",
"emulated-integration-tests-common",
"frame-support",
"parachains-common",
"serde_json",
"sp-core",
"sp-runtime",
"wococo-emulated-chain",
]
[[package]]
name = "asset-test-utils"
version = "1.0.0"
@@ -2202,12 +2186,14 @@ dependencies = [
"cumulus-pallet-xcmp-queue",
"emulated-integration-tests-common",
"frame-support",
"pallet-assets",
"pallet-balances",
"pallet-bridge-messages",
"pallet-message-queue",
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"rococo-wococo-system-emulated-network",
"rococo-westend-system-emulated-network",
"staging-xcm",
"staging-xcm-executor",
]
@@ -2370,14 +2356,16 @@ dependencies = [
"cumulus-pallet-xcmp-queue",
"emulated-integration-tests-common",
"frame-support",
"pallet-assets",
"pallet-balances",
"pallet-bridge-messages",
"pallet-message-queue",
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"rococo-westend-system-emulated-network",
"staging-xcm",
"staging-xcm-executor",
"westend-system-emulated-network",
]
[[package]]
@@ -2463,21 +2451,6 @@ dependencies = [
"westend-runtime-constants",
]
[[package]]
name = "bridge-hub-wococo-emulated-chain"
version = "0.0.0"
dependencies = [
"bridge-hub-rococo-emulated-chain",
"bridge-hub-rococo-runtime",
"cumulus-primitives-core",
"emulated-integration-tests-common",
"frame-support",
"parachains-common",
"serde_json",
"sp-core",
"sp-runtime",
]
[[package]]
name = "bridge-runtime-common"
version = "0.1.0"
@@ -14578,16 +14551,16 @@ dependencies = [
]
[[package]]
name = "rococo-wococo-system-emulated-network"
name = "rococo-westend-system-emulated-network"
version = "0.0.0"
dependencies = [
"asset-hub-rococo-emulated-chain",
"asset-hub-wococo-emulated-chain",
"asset-hub-westend-emulated-chain",
"bridge-hub-rococo-emulated-chain",
"bridge-hub-wococo-emulated-chain",
"bridge-hub-westend-emulated-chain",
"emulated-integration-tests-common",
"rococo-emulated-chain",
"wococo-emulated-chain",
"westend-emulated-chain",
]
[[package]]
@@ -21236,37 +21209,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "wococo-emulated-chain"
version = "0.0.0"
dependencies = [
"emulated-integration-tests-common",
"pallet-im-online",
"parachains-common",
"polkadot-primitives",
"rococo-emulated-chain",
"rococo-runtime",
"rococo-runtime-constants",
"sc-consensus-grandpa",
"serde_json",
"sp-authority-discovery",
"sp-consensus-babe",
"sp-consensus-beefy",
"sp-core",
"sp-runtime",
]
[[package]]
name = "wococo-system-emulated-network"
version = "0.0.0"
dependencies = [
"asset-hub-wococo-emulated-chain",
"bridge-hub-wococo-emulated-chain",
"emulated-integration-tests-common",
"penpal-emulated-chain",
"wococo-emulated-chain",
]
[[package]]
name = "wyz"
version = "0.5.1"
+1 -4
View File
@@ -71,16 +71,13 @@ members = [
"cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend",
"cumulus/parachains/integration-tests/emulated/common",
"cumulus/parachains/integration-tests/emulated/chains/relays/rococo",
"cumulus/parachains/integration-tests/emulated/chains/relays/wococo",
"cumulus/parachains/integration-tests/emulated/chains/relays/westend",
"cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo",
"cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-wococo",
"cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend",
"cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo",
"cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend",
"cumulus/parachains/integration-tests/emulated/networks/rococo-system",
"cumulus/parachains/integration-tests/emulated/networks/wococo-system",
"cumulus/parachains/integration-tests/emulated/networks/rococo-wococo-system",
"cumulus/parachains/integration-tests/emulated/networks/rococo-westend-system",
"cumulus/parachains/integration-tests/emulated/networks/westend-system",
"cumulus/parachains/pallets/collective-content",
"cumulus/parachains/pallets/parachain-info",
@@ -21,7 +21,8 @@ use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain, impls::Parachain,
xcm_emulator::decl_test_parachains,
};
use rococo_emulated_chain::Rococo;
@@ -53,3 +54,4 @@ decl_test_parachains! {
impl_accounts_helpers_for_parachain!(AssetHubRococo);
impl_assert_events_helpers_for_parachain!(AssetHubRococo, false);
impl_assets_helpers_for_parachain!(AssetHubRococo, Rococo);
impl_foreign_assets_helpers_for_parachain!(AssetHubRococo, Rococo);
@@ -21,7 +21,8 @@ use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain, impls::Parachain,
xcm_emulator::decl_test_parachains,
};
use westend_emulated_chain::Westend;
@@ -53,3 +54,4 @@ decl_test_parachains! {
impl_accounts_helpers_for_parachain!(AssetHubWestend);
impl_assert_events_helpers_for_parachain!(AssetHubWestend, false);
impl_assets_helpers_for_parachain!(AssetHubWestend, Westend);
impl_foreign_assets_helpers_for_parachain!(AssetHubWestend, Westend);
@@ -1,26 +0,0 @@
[package]
name = "asset-hub-wococo-emulated-chain"
version = "0.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Asset Hub Wococo emulated chain"
publish = false
[dependencies]
serde_json = "1.0.104"
# Substrate
sp-core = { path = "../../../../../../../../substrate/primitives/core", default-features = false }
sp-runtime = { path = "../../../../../../../../substrate/primitives/runtime", default-features = false }
frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false }
# Polakadot
parachains-common = { path = "../../../../../../../parachains/common" }
# Cumulus
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
emulated-integration-tests-common = { path = "../../../../common", default-features = false }
asset-hub-rococo-runtime = { path = "../../../../../../runtimes/assets/asset-hub-rococo" }
wococo-emulated-chain = { path = "../../../relays/wococo" }
asset-hub-rococo-emulated-chain = { path = "../asset-hub-rococo" }
@@ -1,53 +0,0 @@
// 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.
// Substrate
use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
};
use wococo_emulated_chain::Wococo;
// AssetHubWococo Parachain declaration
decl_test_parachains! {
pub struct AssetHubWococo {
genesis = asset_hub_rococo_emulated_chain::genesis::genesis(),
on_init = {
asset_hub_rococo_runtime::AuraExt::on_initialize(1);
},
runtime = asset_hub_rococo_runtime,
core = {
XcmpMessageHandler: asset_hub_rococo_runtime::XcmpQueue,
LocationToAccountId: asset_hub_rococo_runtime::xcm_config::LocationToAccountId,
ParachainInfo: asset_hub_rococo_runtime::ParachainInfo,
},
pallets = {
PolkadotXcm: asset_hub_rococo_runtime::PolkadotXcm,
Assets: asset_hub_rococo_runtime::Assets,
ForeignAssets: asset_hub_rococo_runtime::ForeignAssets,
PoolAssets: asset_hub_rococo_runtime::PoolAssets,
AssetConversion: asset_hub_rococo_runtime::AssetConversion,
Balances: asset_hub_rococo_runtime::Balances,
}
},
}
// AssetHubWococo implementation
impl_accounts_helpers_for_parachain!(AssetHubWococo);
impl_assert_events_helpers_for_parachain!(AssetHubWococo, false);
impl_assets_helpers_for_parachain!(AssetHubWococo, Wococo);
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
xcm_emulator::decl_test_parachains,
impls::Parachain, xcm_emulator::decl_test_parachains,
};
// BridgeHubRococo Parachain declaration
@@ -22,7 +22,7 @@ use emulated_integration_tests_common::{
};
use parachains_common::Balance;
pub const PARA_ID: u32 = 1013;
pub const PARA_ID: u32 = 1002;
pub const ED: Balance = parachains_common::westend::currency::EXISTENTIAL_DEPOSIT;
pub fn genesis() -> Storage {
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
xcm_emulator::decl_test_parachains,
impls::Parachain, xcm_emulator::decl_test_parachains,
};
// BridgeHubWestend Parachain declaration
@@ -1,25 +0,0 @@
[package]
name = "bridge-hub-wococo-emulated-chain"
version = "0.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Bridge Hub Wococo emulated chain"
publish = false
[dependencies]
serde_json = "1.0.104"
# Substrate
sp-core = { path = "../../../../../../../../substrate/primitives/core", default-features = false }
sp-runtime = { path = "../../../../../../../../substrate/primitives/runtime", default-features = false }
frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false }
# Polakadot
parachains-common = { path = "../../../../../../../parachains/common" }
# Cumulus
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
emulated-integration-tests-common = { path = "../../../../common", default-features = false }
bridge-hub-rococo-runtime = { path = "../../../../../../runtimes/bridge-hubs/bridge-hub-rococo" }
bridge-hub-rococo-emulated-chain = { path = "../bridge-hub-rococo" }
@@ -1,47 +0,0 @@
// 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.
// Substrate
use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
xcm_emulator::decl_test_parachains,
};
// BridgeHubWococo Parachain declaration
decl_test_parachains! {
pub struct BridgeHubWococo {
genesis = bridge_hub_rococo_emulated_chain::genesis::genesis(),
on_init = {
bridge_hub_rococo_runtime::AuraExt::on_initialize(1);
},
runtime = bridge_hub_rococo_runtime,
core = {
XcmpMessageHandler: bridge_hub_rococo_runtime::XcmpQueue,
LocationToAccountId: bridge_hub_rococo_runtime::xcm_config::LocationToAccountId,
ParachainInfo: bridge_hub_rococo_runtime::ParachainInfo,
},
pallets = {
PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm,
Balances: bridge_hub_rococo_runtime::Balances,
}
},
}
// BridgeHubWococo implementation
impl_accounts_helpers_for_parachain!(BridgeHubWococo);
impl_assert_events_helpers_for_parachain!(BridgeHubWococo, false);
@@ -22,7 +22,7 @@ use frame_support::traits::OnInitialize;
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
impl_assets_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains,
};
use rococo_emulated_chain::Rococo;
@@ -1,30 +0,0 @@
[package]
name = "wococo-emulated-chain"
version = "0.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Wococo emulated chain"
publish = false
[dependencies]
serde_json = "1.0.104"
# Substrate
sp-core = { path = "../../../../../../../substrate/primitives/core", default-features = false }
sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false }
sp-authority-discovery = { path = "../../../../../../../substrate/primitives/authority-discovery", default-features = false }
sp-consensus-babe = { path = "../../../../../../../substrate/primitives/consensus/babe", default-features = false }
beefy-primitives = { package = "sp-consensus-beefy", path = "../../../../../../../substrate/primitives/consensus/beefy" }
grandpa = { package = "sc-consensus-grandpa", path = "../../../../../../../substrate/client/consensus/grandpa", default-features = false }
pallet-im-online = { path = "../../../../../../../substrate/frame/im-online", default-features = false }
# Polkadot
polkadot-primitives = { path = "../../../../../../../polkadot/primitives", default-features = false }
rococo-runtime-constants = { path = "../../../../../../../polkadot/runtime/rococo/constants", default-features = false }
rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" }
# Cumulus
parachains-common = { path = "../../../../../../parachains/common" }
emulated-integration-tests-common = { path = "../../../common", default-features = false }
rococo-emulated-chain = { path = "../rococo" }
@@ -1,46 +0,0 @@
// 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.
// Cumulus
use emulated_integration_tests_common::{
impl_accounts_helpers_for_relay_chain, impl_assert_events_helpers_for_relay_chain,
impl_hrmp_channels_helpers_for_relay_chain, impl_send_transact_helpers_for_relay_chain,
xcm_emulator::decl_test_relay_chains,
};
// Wococo declaration
decl_test_relay_chains! {
#[api_version(8)]
pub struct Wococo {
genesis = rococo_emulated_chain::genesis::genesis(),
on_init = (),
runtime = rococo_runtime,
core = {
SovereignAccountOf: rococo_runtime::xcm_config::LocationConverter,
},
pallets = {
XcmPallet: rococo_runtime::XcmPallet,
Sudo: rococo_runtime::Sudo,
Balances: rococo_runtime::Balances,
Hrmp: rococo_runtime::Hrmp,
}
},
}
// Wococo implementation
impl_accounts_helpers_for_relay_chain!(Wococo);
impl_assert_events_helpers_for_relay_chain!(Wococo);
impl_hrmp_channels_helpers_for_relay_chain!(Wococo);
impl_send_transact_helpers_for_relay_chain!(Wococo);
@@ -47,7 +47,8 @@ pub use xcm::{
pub use cumulus_pallet_parachain_system;
pub use cumulus_pallet_xcmp_queue;
pub use cumulus_primitives_core::{
relay_chain::HrmpChannelId, DmpMessageHandler, ParaId, XcmpMessageHandler,
relay_chain::HrmpChannelId, DmpMessageHandler, Junction, Junctions, NetworkId, ParaId,
XcmpMessageHandler,
};
pub use parachains_common::{AccountId, Balance};
pub use xcm_emulator::{
@@ -62,11 +63,14 @@ use bp_messages::{
LaneId, MessageKey, OutboundLaneData,
};
use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult;
pub use pallet_bridge_messages::Instance2 as BridgeMessagesInstance2;
use pallet_bridge_messages::{Config, Instance1, OutboundLanes, Pallet};
use pallet_bridge_messages::{Config, OutboundLanes, Pallet};
pub use pallet_bridge_messages::{
Instance1 as BridgeMessagesInstance1, Instance2 as BridgeMessagesInstance2,
Instance3 as BridgeMessagesInstance3,
};
pub struct BridgeHubMessageHandler<S, T, I> {
_marker: std::marker::PhantomData<(S, T, I)>,
pub struct BridgeHubMessageHandler<S, SI, T, TI> {
_marker: std::marker::PhantomData<(S, SI, T, TI)>,
}
struct LaneIdWrapper(LaneId);
@@ -83,13 +87,14 @@ impl From<u32> for LaneIdWrapper {
}
}
impl<S, T, I> BridgeMessageHandler for BridgeHubMessageHandler<S, T, I>
impl<S, SI, T, TI> BridgeMessageHandler for BridgeHubMessageHandler<S, SI, T, TI>
where
S: Config<Instance1>,
T: Config<I>,
I: 'static,
<T as Config<I>>::InboundPayload: From<Vec<u8>>,
<T as Config<I>>::MessageDispatch:
S: Config<SI>,
SI: 'static,
T: Config<TI>,
TI: 'static,
<T as Config<TI>>::InboundPayload: From<Vec<u8>>,
<T as Config<TI>>::MessageDispatch:
MessageDispatch<DispatchLevelResult = XcmBlobMessageDispatchResult>,
{
fn get_source_outbound_messages() -> Vec<BridgeMessage> {
@@ -100,16 +105,13 @@ where
// collect messages from `OutboundMessages` for each active outbound lane in the source
for lane in active_lanes {
let latest_generated_nonce =
OutboundLanes::<S, Instance1>::get(lane).latest_generated_nonce;
let latest_received_nonce =
OutboundLanes::<S, Instance1>::get(lane).latest_received_nonce;
let latest_generated_nonce = OutboundLanes::<S, SI>::get(lane).latest_generated_nonce;
let latest_received_nonce = OutboundLanes::<S, SI>::get(lane).latest_received_nonce;
(latest_received_nonce + 1..=latest_generated_nonce).for_each(|nonce| {
let encoded_payload: Vec<u8> =
Pallet::<S, Instance1>::outbound_message_data(*lane, nonce)
.expect("Bridge message does not exist")
.into();
let encoded_payload: Vec<u8> = Pallet::<S, SI>::outbound_message_data(*lane, nonce)
.expect("Bridge message does not exist")
.into();
let payload = Vec::<u8>::decode(&mut &encoded_payload[..])
.expect("Decodign XCM message failed");
let id: u32 = LaneIdWrapper(*lane).into();
@@ -133,9 +135,9 @@ where
// Directly dispatch outbound messages assuming everything is correct
// and bypassing the `Relayers` and `InboundLane` logic
let dispatch_result = TargetMessageDispatch::<T, I>::dispatch(DispatchMessage {
let dispatch_result = TargetMessageDispatch::<T, TI>::dispatch(DispatchMessage {
key: MessageKey { lane_id, nonce },
data: DispatchMessageData::<InboundPayload<T, I>> { payload },
data: DispatchMessageData::<InboundPayload<T, TI>> { payload },
});
let result = match dispatch_result.dispatch_level_result {
@@ -151,14 +153,14 @@ where
}
fn notify_source_message_delivery(lane_id: u32) {
let data = OutboundLanes::<S, Instance1>::get(LaneIdWrapper::from(lane_id).0);
let data = OutboundLanes::<S, SI>::get(LaneIdWrapper::from(lane_id).0);
let new_data = OutboundLaneData {
oldest_unpruned_nonce: data.oldest_unpruned_nonce + 1,
latest_received_nonce: data.latest_received_nonce + 1,
..data
};
OutboundLanes::<S, Instance1>::insert(LaneIdWrapper::from(lane_id).0, new_data);
OutboundLanes::<S, SI>::insert(LaneIdWrapper::from(lane_id).0, new_data);
}
}
@@ -392,6 +394,23 @@ macro_rules! impl_accounts_helpers_for_parachain {
}
});
}
/// Return local sovereign account of `para_id` on other `network_id`
pub fn sovereign_account_of_parachain_on_other_global_consensus(
network_id: $crate::impls::NetworkId,
para_id: $crate::impls::ParaId,
) -> $crate::impls::AccountId {
let remote_location = $crate::impls::MultiLocation {
parents: 2,
interior: $crate::impls::Junctions::X2(
$crate::impls::Junction::GlobalConsensus(network_id),
$crate::impls::Junction::Parachain(para_id.into()),
),
};
<Self as $crate::impls::TestExt>::execute_with(|| {
Self::sovereign_account_id_of(remote_location)
})
}
}
}
};
@@ -614,7 +633,9 @@ macro_rules! impl_assets_helpers_for_parachain {
$crate::impls::assert_expected_events!(
Self,
vec![
RuntimeEvent::<N>::Assets($crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount }) => {
RuntimeEvent::<N>::Assets(
$crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount }
) => {
asset_id: *asset_id == id,
owner: *owner == beneficiary.clone().into(),
amount: *amount == amount_to_mint,
@@ -687,3 +708,85 @@ macro_rules! impl_assets_helpers_for_parachain {
}
};
}
#[macro_export]
macro_rules! impl_foreign_assets_helpers_for_parachain {
( $chain:ident, $relay_chain:ident ) => {
$crate::impls::paste::paste! {
impl<N: $crate::impls::Network> $chain<N> {
/// Create foreign assets using sudo `ForeignAssets::force_create()`
pub fn force_create_foreign_asset(
id: $crate::impls::MultiLocation,
owner: $crate::impls::AccountId,
is_sufficient: bool,
min_balance: u128,
prefund_accounts: Vec<($crate::impls::AccountId, u128)>,
) {
use $crate::impls::Inspect;
let sudo_origin = <$chain<N> as $crate::impls::Chain>::RuntimeOrigin::root();
<Self as $crate::impls::TestExt>::execute_with(|| {
$crate::impls::assert_ok!(
<Self as [<$chain ParaPallet>]>::ForeignAssets::force_create(
sudo_origin,
id,
owner.clone().into(),
is_sufficient,
min_balance,
)
);
assert!(<Self as [<$chain ParaPallet>]>::ForeignAssets::asset_exists(id));
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
$crate::impls::assert_expected_events!(
Self,
vec![
RuntimeEvent::<N>::ForeignAssets(
$crate::impls::pallet_assets::Event::ForceCreated {
asset_id,
..
}
) => { asset_id: *asset_id == id, },
]
);
});
for (beneficiary, amount) in prefund_accounts.into_iter() {
let signed_origin =
<$chain<N> as $crate::impls::Chain>::RuntimeOrigin::signed(owner.clone());
Self::mint_foreign_asset(signed_origin, id, beneficiary, amount);
}
}
/// Mint assets making use of the ForeignAssets pallet-assets instance
pub fn mint_foreign_asset(
signed_origin: <Self as $crate::impls::Chain>::RuntimeOrigin,
id: $crate::impls::MultiLocation,
beneficiary: $crate::impls::AccountId,
amount_to_mint: u128,
) {
<Self as $crate::impls::TestExt>::execute_with(|| {
$crate::impls::assert_ok!(<Self as [<$chain ParaPallet>]>::ForeignAssets::mint(
signed_origin,
id.into(),
beneficiary.clone().into(),
amount_to_mint
));
type RuntimeEvent<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
$crate::impls::assert_expected_events!(
Self,
vec![
RuntimeEvent::<N>::ForeignAssets(
$crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount }
) => {
asset_id: *asset_id == id,
owner: *owner == beneficiary.clone().into(),
amount: *amount == amount_to_mint,
},
]
);
});
}
}
}
};
}
@@ -1,18 +1,18 @@
[package]
name = "rococo-wococo-system-emulated-network"
name = "rococo-westend-system-emulated-network"
version = "0.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Rococo<>Wococo emulated bridged network"
description = "Rococo<>Westend emulated bridged network"
publish = false
[dependencies]
# Cumulus
emulated-integration-tests-common = { path = "../../common", default-features = false }
rococo-emulated-chain = { path = "../../chains/relays/rococo" }
wococo-emulated-chain = { path = "../../chains/relays/wococo" }
westend-emulated-chain = { path = "../../chains/relays/westend" }
asset-hub-rococo-emulated-chain = { path = "../../chains/parachains/assets/asset-hub-rococo" }
asset-hub-wococo-emulated-chain = { path = "../../chains/parachains/assets/asset-hub-wococo" }
asset-hub-westend-emulated-chain = { path = "../../chains/parachains/assets/asset-hub-westend" }
bridge-hub-rococo-emulated-chain = { path = "../../chains/parachains/bridges/bridge-hub-rococo" }
bridge-hub-wococo-emulated-chain = { path = "../../chains/parachains/bridges/bridge-hub-wococo" }
bridge-hub-westend-emulated-chain = { path = "../../chains/parachains/bridges/bridge-hub-westend" }
@@ -14,23 +14,23 @@
// limitations under the License.
pub use asset_hub_rococo_emulated_chain;
pub use asset_hub_wococo_emulated_chain;
pub use asset_hub_westend_emulated_chain;
pub use bridge_hub_rococo_emulated_chain;
pub use bridge_hub_wococo_emulated_chain;
pub use bridge_hub_westend_emulated_chain;
pub use rococo_emulated_chain;
pub use wococo_emulated_chain;
pub use westend_emulated_chain;
use asset_hub_rococo_emulated_chain::AssetHubRococo;
use asset_hub_wococo_emulated_chain::AssetHubWococo;
use asset_hub_westend_emulated_chain::AssetHubWestend;
use bridge_hub_rococo_emulated_chain::BridgeHubRococo;
use bridge_hub_wococo_emulated_chain::BridgeHubWococo;
use bridge_hub_westend_emulated_chain::BridgeHubWestend;
use rococo_emulated_chain::Rococo;
use wococo_emulated_chain::Wococo;
use westend_emulated_chain::Westend;
// Cumulus
use emulated_integration_tests_common::{
accounts::{ALICE, BOB},
impls::{BridgeHubMessageHandler, BridgeMessagesInstance2},
impls::{BridgeHubMessageHandler, BridgeMessagesInstance1, BridgeMessagesInstance3},
xcm_emulator::{
decl_test_bridges, decl_test_networks, decl_test_sender_receiver_accounts_parameter_types,
Chain,
@@ -44,51 +44,53 @@ decl_test_networks! {
AssetHubRococo,
BridgeHubRococo,
],
bridge = RococoWococoMockBridge
bridge = RococoWestendMockBridge
},
pub struct WococoMockNet {
relay_chain = Wococo,
pub struct WestendMockNet {
relay_chain = Westend,
parachains = vec![
AssetHubWococo,
BridgeHubWococo,
AssetHubWestend,
BridgeHubWestend,
],
bridge = WococoRococoMockBridge
bridge = WestendRococoMockBridge
},
}
decl_test_bridges! {
pub struct RococoWococoMockBridge {
pub struct RococoWestendMockBridge {
source = BridgeHubRococoPara,
target = BridgeHubWococoPara,
handler = RococoWococoMessageHandler
target = BridgeHubWestendPara,
handler = RococoWestendMessageHandler
},
pub struct WococoRococoMockBridge {
source = BridgeHubWococoPara,
pub struct WestendRococoMockBridge {
source = BridgeHubWestendPara,
target = BridgeHubRococoPara,
handler = WococoRococoMessageHandler
handler = WestendRococoMessageHandler
}
}
type BridgeHubRococoRuntime = <BridgeHubRococoPara as Chain>::Runtime;
type BridgeHubWococoRuntime = <BridgeHubWococoPara as Chain>::Runtime;
type BridgeHubWestendRuntime = <BridgeHubWestendPara as Chain>::Runtime;
pub type RococoWococoMessageHandler = BridgeHubMessageHandler<
pub type RococoWestendMessageHandler = BridgeHubMessageHandler<
BridgeHubRococoRuntime,
BridgeHubWococoRuntime,
BridgeMessagesInstance2,
BridgeMessagesInstance3,
BridgeHubWestendRuntime,
BridgeMessagesInstance1,
>;
pub type WococoRococoMessageHandler = BridgeHubMessageHandler<
BridgeHubWococoRuntime,
pub type WestendRococoMessageHandler = BridgeHubMessageHandler<
BridgeHubWestendRuntime,
BridgeMessagesInstance1,
BridgeHubRococoRuntime,
BridgeMessagesInstance2,
BridgeMessagesInstance3,
>;
decl_test_sender_receiver_accounts_parameter_types! {
RococoRelay { sender: ALICE, receiver: BOB },
AssetHubRococoPara { sender: ALICE, receiver: BOB },
BridgeHubRococoPara { sender: ALICE, receiver: BOB },
WococoRelay { sender: ALICE, receiver: BOB },
AssetHubWococoPara { sender: ALICE, receiver: BOB },
BridgeHubWococoPara { sender: ALICE, receiver: BOB }
WestendRelay { sender: ALICE, receiver: BOB },
AssetHubWestendPara { sender: ALICE, receiver: BOB },
BridgeHubWestendPara { sender: ALICE, receiver: BOB }
}
@@ -1,16 +0,0 @@
[package]
name = "wococo-system-emulated-network"
version = "0.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Wococo System emulated network"
publish = false
[dependencies]
# Cumulus
emulated-integration-tests-common = { path = "../../common", default-features = false }
wococo-emulated-chain = { path = "../../chains/relays/wococo" }
asset-hub-wococo-emulated-chain = { path = "../../chains/parachains/assets/asset-hub-wococo" }
bridge-hub-wococo-emulated-chain = { path = "../../chains/parachains/bridges/bridge-hub-wococo" }
penpal-emulated-chain = { path = "../../chains/parachains/testing/penpal" }
@@ -1,50 +0,0 @@
// 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 asset_hub_wococo_emulated_chain;
pub use bridge_hub_wococo_emulated_chain;
pub use wococo_emulated_chain;
use asset_hub_wococo_emulated_chain::AssetHubWococo;
use bridge_hub_wococo_emulated_chain::BridgeHubWococo;
use penpal_emulated_chain::{PenpalA, PenpalB};
use wococo_emulated_chain::Wococo;
// Cumulus
use emulated_integration_tests_common::{
accounts::{ALICE, BOB},
xcm_emulator::{decl_test_networks, decl_test_sender_receiver_accounts_parameter_types},
};
decl_test_networks! {
pub struct WococoMockNet {
relay_chain = Wococo,
parachains = vec![
AssetHubWococo,
BridgeHubWococo,
PenpalA,
PenpalB,
],
bridge = ()
},
}
decl_test_sender_receiver_accounts_parameter_types! {
WococoRelay { sender: ALICE, receiver: BOB },
AssetHubWococoPara { sender: ALICE, receiver: BOB },
BridgeHubWococoPara { sender: ALICE, receiver: BOB },
PenpalAPara { sender: ALICE, receiver: BOB },
PenpalBPara { sender: ALICE, receiver: BOB }
}
@@ -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-rococo-runtime = { path = "../../../../../../parachains/runtimes/bridge-hubs/bridge-hub-rococo", default-features = false }
emulated-integration-tests-common = { path = "../../../common", default-features = false}
rococo-wococo-system-emulated-network ={ path = "../../../networks/rococo-wococo-system" }
rococo-westend-system-emulated-network = { path = "../../../networks/rococo-westend-system" }
@@ -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 {
..
@@ -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!(