Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ 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::AssetHubWestendParaPallet as AssetHubWestendPallet,
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,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,7 @@

use crate::*;

#[test]
fn send_rocs_from_asset_hub_rococo_to_asset_hub_westend() {
let prefund_amount = 10_000_000_000_000u128;
let owner: AccountId = AssetHubWestend::account_id_of(ALICE);
let roc_at_asset_hub_westend =
MultiLocation { parents: 2, interior: X1(GlobalConsensus(NetworkId::Rococo)) };
AssetHubWestend::force_create_foreign_asset(
roc_at_asset_hub_westend,
owner,
true,
ASSET_MIN_BALANCE,
vec![],
);

let sender_balance_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())
});

fn send_asset_from_asset_hub_rococo_to_asset_hub_westend(id: MultiLocation, amount: u128) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@acatangiu I dont know if this is possible to deduplicate easily:

fn send_asset_from_asset_hub_rococo_to_asset_hub_westend
fn send_asset_from_asset_hub_westend_to_asset_hub_rococo

to the one generic

fn send_asset_from_asset_hub_to_asset_hub

they are doing exactly the same thing AH1 -> BH1 -> BH2 -> AH2 and AH2 -> BH2 -> BH1 -> AH1,
we could possibly reuse for BHKusama/BHPolkadot,
maybe with some macro helper? But sure, also no that big issue to have copies.

but very cool that we have bi-directional tests now 👍 👍 👍

let signed_origin =
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get().into());
let asset_hub_westend_para_id = AssetHubWestend::para_id().into();
Expand All @@ -46,14 +26,13 @@ fn send_rocs_from_asset_hub_rococo_to_asset_hub_westend() {
let beneficiary_id = AssetHubWestendReceiver::get();
let beneficiary: MultiLocation =
AccountId32Junction { network: None, id: beneficiary_id.into() }.into();
let amount_to_send = ASSET_HUB_ROCOCO_ED * 10;
let assets: MultiAssets = (Parent, amount_to_send).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(), prefund_amount)]);
BridgeHubRococo::fund_accounts(vec![(sov_ahr_on_bhr.into(), 10_000_000_000_000u128)]);

AssetHubRococo::execute_with(|| {
assert_ok!(
Expand Down Expand Up @@ -98,18 +77,39 @@ fn send_rocs_from_asset_hub_rococo_to_asset_hub_westend() {
]
);
});
}

#[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 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_westend,
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
Expand All @@ -120,15 +120,89 @@ fn send_rocs_from_asset_hub_rococo_to_asset_hub_westend() {
);
});

let sender_balance_after =
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())
});

// Sender's balance is reduced
assert!(sender_balance_before > sender_balance_after);
assert!(sender_rocs_before > sender_rocs_after);
// Receiver's balance is increased
assert!(receiver_rocs_after > receiver_rocs_before);
}

#[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 ahr_as_seen_by_ahw = MultiLocation {
parents: 2,
interior: X2(
GlobalConsensus(NetworkId::Rococo),
Parachain(AssetHubRococo::para_id().into()),
),
};
let sov_ahr_on_ahw = AssetHubWestend::execute_with(|| {
AssetHubWestend::sovereign_account_id_of(ahr_as_seen_by_ahw)
});
AssetHubWestend::fund_accounts(vec![(sov_ahr_on_ahw.clone(), 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;

// Sender's balance is reduced
assert!(sender_wnds_before > sender_wnds_after);
// Receiver's balance is increased
assert!(receiver_wnds_after > receiver_wnds_before);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ pub use emulated_integration_tests_common::{
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::AssetHubRococoParaPallet as AssetHubRococoPallet,
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,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,7 @@

use crate::*;

#[test]
fn send_wnds_from_asset_hub_westend_to_asset_hub_rococo() {
let prefund_amount = 10_000_000_000_000u128;
let owner: AccountId = AssetHubRococo::account_id_of(ALICE);
let wnd_at_asset_hub_rococo =
MultiLocation { parents: 2, interior: X1(GlobalConsensus(NetworkId::Westend)) };
AssetHubRococo::force_create_foreign_asset(
wnd_at_asset_hub_rococo,
owner,
true,
ASSET_MIN_BALANCE,
vec![],
);

let sender_balance_before =
<AssetHubWestend as Chain>::account_data_of(AssetHubWestendSender::get()).free;
let receiver_rocs_before = AssetHubRococo::execute_with(|| {
type Assets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(wnd_at_asset_hub_rococo, &AssetHubRococoReceiver::get())
});

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();
Expand All @@ -46,14 +26,13 @@ fn send_wnds_from_asset_hub_westend_to_asset_hub_rococo() {
let beneficiary_id = AssetHubRococoReceiver::get();
let beneficiary: MultiLocation =
AccountId32Junction { network: None, id: beneficiary_id.into() }.into();
let amount_to_send = ASSET_HUB_WESTEND_ED * 10;
let assets: MultiAssets = (Parent, amount_to_send).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(), prefund_amount)]);
BridgeHubWestend::fund_accounts(vec![(sov_ahw_on_bhw.into(), 10_000_000_000_000u128)]);

AssetHubWestend::execute_with(|| {
assert_ok!(
Expand Down Expand Up @@ -98,17 +77,38 @@ fn send_wnds_from_asset_hub_westend_to_asset_hub_rococo() {
]
);
});
}

#[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 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 ROCs on AHW
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued {
asset_id,
owner,
..
}) => {
// 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(),
},
Expand All @@ -120,15 +120,89 @@ fn send_wnds_from_asset_hub_westend_to_asset_hub_rococo() {
);
});

let sender_balance_after =
let sender_wnds_after =
<AssetHubWestend as Chain>::account_data_of(AssetHubWestendSender::get()).free;
let receiver_rocs_after = AssetHubRococo::execute_with(|| {
let receiver_wnds_after = AssetHubRococo::execute_with(|| {
type Assets = <AssetHubRococo as AssetHubRococoPallet>::ForeignAssets;
<Assets as Inspect<_>>::balance(wnd_at_asset_hub_rococo, &AssetHubRococoReceiver::get())
});

// Sender's balance is reduced
assert!(sender_balance_before > sender_balance_after);
assert!(sender_wnds_before > sender_wnds_after);
// Receiver's balance is increased
assert!(receiver_wnds_after > receiver_wnds_before);
}

#[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 ahw_as_seen_by_ahr = MultiLocation {
parents: 2,
interior: X2(
GlobalConsensus(NetworkId::Westend),
Parachain(AssetHubWestend::para_id().into()),
),
};
let sov_ahw_on_ahr = AssetHubRococo::execute_with(|| {
AssetHubRococo::sovereign_account_id_of(ahw_as_seen_by_ahr)
});
AssetHubRococo::fund_accounts(vec![(sov_ahw_on_ahr.clone(), 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;

// Sender's balance is reduced
assert!(sender_rocs_before > sender_rocs_after);
// Receiver's balance is increased
assert!(receiver_rocs_after > receiver_rocs_before);
}