Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions bridges/modules/xcm-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,11 @@ pub mod pallet {
.into()),
}
}

/// Get the bridge deposit amount required to open a new bridge.
pub fn bridge_deposit() -> BalanceOf<ThisChainOf<T, I>> {
T::BridgeDeposit::get()
}
}

#[cfg(feature = "runtime-benchmarks")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ where

// collect messages from `OutboundMessages` for each active outbound lane in the source
for lane in active_outbound_lanes {
if OutboundLanes::<S, SI>::get(lane).is_none() {
// TODO: FAIL - investigate how was this created
continue;
}

let latest_generated_nonce =
OutboundLanes::<S, SI>::get(lane).unwrap().latest_generated_nonce;
let latest_received_nonce =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,9 @@ decl_test_bridges! {
}
}

type AssetHubRococoRuntime = <AssetHubRococoPara as Chain>::Runtime;
type AssetHubWestendRuntime = <AssetHubWestendPara as Chain>::Runtime;
type BridgeHubRococoRuntime = <BridgeHubRococoPara as Chain>::Runtime;
type BridgeHubWestendRuntime = <BridgeHubWestendPara as Chain>::Runtime;

pub type AssetHubRococoWestendMessageHandler = BridgeMessagesHandler<
AssetHubRococoRuntime,
BridgeMessagesInstance1,
AssetHubWestendRuntime,
BridgeMessagesInstance1,
>;
pub type AssetHubWestendRococoMessageHandler = BridgeMessagesHandler<
AssetHubWestendRuntime,
BridgeMessagesInstance1,
AssetHubRococoRuntime,
BridgeMessagesInstance1,
>;
pub type RococoWestendMessageHandler = BridgeMessagesHandler<
BridgeHubRococoRuntime,
BridgeMessagesInstance3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ emulated-integration-tests-common = { workspace = true }
parachains-common = { workspace = true, default-features = true }
rococo-system-emulated-network = { workspace = true }
westend-system-emulated-network = { workspace = true }
rococo-westend-system-emulated-network = { workspace = true }

# Bridge
bp-asset-hub-westend = { workspace = true }
bp-asset-hub-rococo = { workspace = true }
bp-xcm-bridge = { workspace = true }
pallet-xcm-bridge = { workspace = true }

[dev-dependencies]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,6 @@ mod imports {
PenpalATeleportableAssetLocation, ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, USDT_ID, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::AssetHubRococoUniversalLocation,
AssetHubRococoParaPallet as AssetHubRococoPallet, AssetHubRococoRuntimeOrigin,
},
AssetHubRococoPara as AssetHubRococo,
};
pub use westend_system_emulated_network::{
asset_hub_westend_emulated_chain::{
asset_hub_westend_runtime::{
Expand All @@ -67,11 +60,8 @@ mod imports {
AssetConversionOrigin as AssetHubWestendAssetConversionOrigin,
ExistentialDeposit as AssetHubWestendExistentialDeposit,
},
genesis::{
AssetHubWestendAssetOwner, AssetHubWestendUniversalLocation,
ED as ASSET_HUB_WESTEND_ED,
},
AssetHubWestendParaPallet as AssetHubWestendPallet, AssetHubWestendRuntimeOrigin,
genesis::{AssetHubWestendAssetOwner, ED as ASSET_HUB_WESTEND_ED},
AssetHubWestendParaPallet as AssetHubWestendPallet,
},
bridge_hub_westend_emulated_chain::{
bridge_hub_westend_runtime::xcm_config::{self as bhw_xcm_config},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,35 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::imports::*;
use crate::imports::assert_ok;
pub use codec::Encode;
use emulated_integration_tests_common::{
xcm_emulator::{bx, Chain, Parachain as Para, TestExt},
xcm_helpers::xcm_transact_paid_execution,
};
use xcm::{
latest::{ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH},
prelude::*,
};

// For a bridging we need rococo_westend system and not separated ones (because different Penpal setups).
use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
asset_hub_rococo_runtime::ExistentialDeposit as AssetHubRococoExistentialDeposit,
genesis::AssetHubRococoUniversalLocation, AssetHubRococoParaPallet as AssetHubRococoPallet,
AssetHubRococoRuntimeOrigin,
},
asset_hub_westend_emulated_chain::{
asset_hub_westend_runtime::ExistentialDeposit as AssetHubWestendExistentialDeposit,
genesis::AssetHubWestendUniversalLocation,
AssetHubWestendParaPallet as AssetHubWestendPallet, AssetHubWestendRuntimeOrigin,
},
penpal_emulated_chain::{
PenpalAParaPallet as PenpalAPallet, PenpalBParaPallet as PenpalBPallet,
},
AssetHubRococoPara as AssetHubRococo, AssetHubWestendPara as AssetHubWestend,
PenpalAPara as PenpalA, PenpalBPara as PenpalB,
};

#[test]
fn ah_to_ah_open_close_bridge_works() {
Expand Down Expand Up @@ -108,3 +136,136 @@ fn ah_to_ah_open_close_bridge_works() {
});
assert!(rococo_bridge_pruned_lane_id.is_some(), "Rococo BridgePruned event not found");
}

#[test]
fn para_to_para_open_close_bridge_works() {
// Ensure Penpal A/B locations (set `on_init` with `set_storage`).
let penpal_a_on_rococo_universal_location = PenpalA::execute_with(|| {
let loc = <<PenpalA as Chain>::Runtime as pallet_xcm::Config>::UniversalLocation::get();
assert_eq!(loc.global_consensus(), Ok(ByGenesis(ROCOCO_GENESIS_HASH)));
loc
});
let penpal_b_on_westend_universal_location = PenpalB::execute_with(|| {
let loc = <<PenpalB as Chain>::Runtime as pallet_xcm::Config>::UniversalLocation::get();
assert_eq!(loc.global_consensus(), Ok(ByGenesis(WESTEND_GENESIS_HASH)));
loc
});

// 1. Open bridge from PenpalA(Rococo) to PenpalB(Westend)
let penpal_a_para_sovereign_account = AssetHubRococo::sovereign_account_id_of(
AssetHubRococo::sibling_location_of(PenpalA::para_id()),
);
let fee_amount = AssetHubRococoExistentialDeposit::get() * 1000;
let bridge_deposit = AssetHubRococo::ext_wrapper(|| {
<AssetHubRococo as AssetHubRococoPallet>::XcmOverAssetHubWestend::bridge_deposit()
});
AssetHubRococo::fund_accounts(vec![(
penpal_a_para_sovereign_account.clone().into(),
AssetHubRococoExistentialDeposit::get() + fee_amount + bridge_deposit,
)]);

// send paid XCM with `open_bridge` from PenpalA to the AssetHubRococo
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
<PenpalA as Chain>::RuntimeOrigin::root(),
bx!(PenpalA::sibling_location_of(AssetHubRococo::para_id()).into()),
bx!(xcm_transact_paid_execution(
bp_asset_hub_rococo::Call::XcmOverAssetHubWestend(
bp_xcm_bridge::XcmBridgeCall::open_bridge {
bridge_destination_universal_location: Box::new(
penpal_b_on_westend_universal_location.into()
),
maybe_notify: None,
},
)
.encode()
.into(),
OriginKind::Xcm,
(Parent, fee_amount).into(),
penpal_a_para_sovereign_account,
)),
));

PenpalA::assert_xcm_pallet_sent();
});

// check BridgeOpened event on AssetHubRococo
let penpal_a_bridge_opened_lane_id = AssetHubRococo::execute_with(|| {
let events = AssetHubRococo::events();
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
AssetHubRococo::assert_xcmp_queue_success(None);
let e = events.iter().find_map(|event| {
if let RuntimeEvent::XcmOverAssetHubWestend(pallet_xcm_bridge::Event::BridgeOpened {
lane_id,
..
}) = event
{
Some(*lane_id)
} else {
None
}
});
e
});
assert!(penpal_a_bridge_opened_lane_id.is_some(), "PenpalA BridgeOpened event not found");

// 2. Open bridge from PenpalB(Westend) to PenpalA(Rococo)
let penpal_b_para_sovereign_account = AssetHubWestend::sovereign_account_id_of(
AssetHubWestend::sibling_location_of(PenpalB::para_id()),
);
let fee_amount = AssetHubWestendExistentialDeposit::get() * 1000;
let bridge_deposit = AssetHubWestend::ext_wrapper(|| {
<AssetHubWestend as AssetHubWestendPallet>::XcmOverAssetHubRococo::bridge_deposit()
});
AssetHubWestend::fund_accounts(vec![(
penpal_b_para_sovereign_account.clone().into(),
AssetHubWestendExistentialDeposit::get() + fee_amount + bridge_deposit,
)]);

// send paid XCM with `open_bridge` from PenpalB to the AssetHubWestend
PenpalB::execute_with(|| {
assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send(
<PenpalB as Chain>::RuntimeOrigin::root(),
bx!(PenpalB::sibling_location_of(AssetHubWestend::para_id()).into()),
bx!(xcm_transact_paid_execution(
bp_asset_hub_westend::Call::XcmOverAssetHubRococo(
bp_xcm_bridge::XcmBridgeCall::open_bridge {
bridge_destination_universal_location: Box::new(
penpal_a_on_rococo_universal_location.into()
),
maybe_notify: None,
},
)
.encode()
.into(),
OriginKind::Xcm,
(Parent, fee_amount).into(),
penpal_b_para_sovereign_account,
)),
));

PenpalB::assert_xcm_pallet_sent();
});

// check BridgeOpened event on AssetHubWestend
let penpal_b_bridge_opened_lane_id = AssetHubWestend::execute_with(|| {
let events = AssetHubWestend::events();
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
AssetHubWestend::assert_xcmp_queue_success(None);
events.iter().find_map(|event| {
if let RuntimeEvent::XcmOverAssetHubRococo(pallet_xcm_bridge::Event::BridgeOpened {
lane_id,
..
}) = event
{
Some(*lane_id)
} else {
None
}
})
});
assert!(penpal_b_bridge_opened_lane_id.is_some(), "PenpalB BridgeOpened event not found");

// check the same lane ID is generated
assert_eq!(penpal_a_bridge_opened_lane_id, penpal_b_bridge_opened_lane_id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ pub enum Call {
/// `ToWestendXcmRouter` bridge pallet.
#[codec(index = 45)]
ToWestendXcmRouter(XcmBridgeHubCall<sp_core::H256>),
/// Points to the `pallet_xcm_bridge` pallet instance for `AssetHubWestend`.
#[codec(index = 61)]
XcmOverAssetHubWestend(bp_xcm_bridge::XcmBridgeCall),
}

frame_support::parameter_types! {
Expand Down Expand Up @@ -165,11 +168,3 @@ frame_support::parameter_types! {
/// (initially was calculated by test `AssetHubRococo::can_calculate_fee_for_standalone_message_confirmation_transaction` + `33%`)
pub const AssetHubRococoBaseConfirmationFeeInRocs: u128 = 56_782_099;
}

/// Wrapper over `AssetHubRococo`'s `RuntimeCall` that can be used without a runtime.
#[derive(Decode, Encode)]
pub enum RuntimeCall {
/// Points to the `pallet_xcm_bridge` pallet instance for `AssetHubWestend`.
#[codec(index = 61)]
XcmOverAssetHubWestend(bp_xcm_bridge::XcmBridgeCall),
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ pub enum Call {
/// `ToRococoXcmRouter` bridge pallet.
#[codec(index = 34)]
ToRococoXcmRouter(XcmBridgeHubCall<sp_core::H256>),
/// Points to the `pallet_xcm_bridge_hub` pallet instance for `AssetHubRococo`.
#[codec(index = 62)]
XcmOverAssetHubRococo(bp_xcm_bridge::XcmBridgeCall),
}

frame_support::parameter_types! {
Expand Down Expand Up @@ -166,11 +169,3 @@ frame_support::parameter_types! {
/// (initially was calculated by test `AssetHubWestend::can_calculate_fee_for_standalone_message_confirmation_transaction` + `33%`)
pub const AssetHubWestendBaseConfirmationFeeInWnds: u128 = 56_782_099;
}

/// Wrapper over `AssetHubWestend`'s `RuntimeCall` that can be used without a runtime.
#[derive(Decode, Encode)]
pub enum RuntimeCall {
/// Points to the `pallet_xcm_bridge_hub` pallet instance for `AssetHubRococo`.
#[codec(index = 62)] // TODO: FAIL-CI - corect index when AssetHubWestend
XcmOverAssetHubRococo(bp_xcm_bridge::XcmBridgeCall),
}
Loading