Skip to content

Commit

Permalink
Add more emulated bridge tests
Browse files Browse the repository at this point in the history
  • Loading branch information
acatangiu committed Dec 17, 2024
1 parent c05f20f commit 3de0be8
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 92 deletions.
1 change: 1 addition & 0 deletions integration-tests/emulated/chains/relays/kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

pub mod genesis;
pub use kusama_runtime;

// Cumulus
use emulated_integration_tests_common::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

pub mod genesis;
pub use polkadot_runtime;

// Cumulus
use emulated_integration_tests_common::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ pub use kusama_polkadot_system_emulated_network::{
bridge_hub_kusama_emulated_chain::{
genesis::ED as BRIDGE_HUB_KUSAMA_ED, BridgeHubKusamaParaPallet as BridgeHubKusamaPallet,
},
kusama_emulated_chain::{genesis::ED as KUSAMA_ED, KusamaRelayPallet as KusamaPallet},
kusama_emulated_chain::{
genesis::ED as KUSAMA_ED,
kusama_runtime::xcm_config::UniversalLocation as KusamaRelayUniversalLocation,
KusamaRelayPallet as KusamaPallet,
},
penpal_emulated_chain::{
penpal_runtime::xcm_config::{
CustomizableAssetFromSystemAssetHub as PenpalCustomizableAssetFromSystemAssetHub,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,47 +55,21 @@ fn set_up_ksm_for_penpal_kusama_through_kah_to_pah(
(ksm_at_kusama_parachains, ksm_at_asset_hub_polkadot)
}

fn send_assets_from_penpal_kusama_through_kusama_ah_to_polkadot_ah(
destination: Location,
assets: (Assets, TransferType),
fees: (AssetId, TransferType),
custom_xcm_on_dest: Xcm<()>,
) {
fn send_assets_from_kusama_chain_through_kusama_ah_to_polkadot_ah<F: FnOnce()>(send_fn: F) {
send_assets_over_bridge(|| {
let sov_penpal_on_kah = AssetHubKusama::sovereign_account_id_of(
AssetHubKusama::sibling_location_of(PenpalA::para_id()),
);
let sov_pah_on_kah =
AssetHubKusama::sovereign_account_of_parachain_on_other_global_consensus(
Polkadot,
AssetHubPolkadot::para_id(),
);
// send message over bridge
assert_ok!(PenpalA::execute_with(|| {
let signed_origin = <PenpalA as Chain>::RuntimeOrigin::signed(PenpalASender::get());
<PenpalA as PenpalAPallet>::PolkadotXcm::transfer_assets_using_type_and_then(
signed_origin,
bx!(destination.into()),
bx!(assets.0.into()),
bx!(assets.1),
bx!(fees.0.into()),
bx!(fees.1),
bx!(VersionedXcm::from(custom_xcm_on_dest)),
WeightLimit::Unlimited,
)
}));
// call transfer extrinsic on sender chain
send_fn();
// verify intermediary AH Kusama hop
AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubKusama,
vec![
// Amount to reserve transfer is withdrawn from Penpal's sovereign account
RuntimeEvent::Balances(
pallet_balances::Event::Burned { who, .. }
) => {
who: *who == sov_penpal_on_kah.clone(),
},
// Amount deposited in PAH's sovereign account
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => {
who: *who == sov_pah_on_kah.clone(),
Expand All @@ -115,7 +89,6 @@ fn send_ksm_from_asset_hub_kusama_to_asset_hub_polkadot() {
let amount = ASSET_HUB_KUSAMA_ED * 1_000;
let sender = AssetHubKusamaSender::get();
let receiver = AssetHubPolkadotReceiver::get();
let ksm_at_asset_hub_kusama = ksm_at_ah_kusama();
let bridged_ksm_at_ah_polkadot = bridged_ksm_at_ah_polkadot();

create_foreign_on_ah_polkadot(bridged_ksm_at_ah_polkadot.clone(), true);
Expand All @@ -131,12 +104,10 @@ fn send_ksm_from_asset_hub_kusama_to_asset_hub_polkadot() {
let receiver_ksms_before =
foreign_balance_on_ah_polkadot(bridged_ksm_at_ah_polkadot.clone(), &receiver);

let ksm_at_ah_kusama_latest = ksm_at_ah_kusama();

// send KSMs, use them for fees
send_assets_over_bridge(|| {
let destination = asset_hub_polkadot_location();
let assets: Assets = (ksm_at_ah_kusama_latest, amount).into();
let assets: Assets = (ksm_at_ah_kusama(), amount).into();
let fee_idx = 0;
assert_ok!(send_assets_from_asset_hub_kusama(destination, assets, fee_idx));
});
Expand All @@ -149,7 +120,7 @@ fn send_ksm_from_asset_hub_kusama_to_asset_hub_polkadot() {
vec![
// issue KSMs on PAH
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => {
asset_id: *asset_id == ksm_at_asset_hub_kusama,
asset_id: *asset_id == bridged_ksm_at_ah_polkadot,
owner: *owner == AssetHubPolkadotReceiver::get(),
},
// message processed successfully
Expand Down Expand Up @@ -347,6 +318,115 @@ fn send_back_dot_usdt_and_weth_from_asset_hub_kusama_to_asset_hub_polkadot() {
assert_eq!(receiver_weth_after, receiver_weth_before + amount_to_send);
}

#[test]
/// Test transfer of KSM from Kusama Relay through AssetHub Kusama to AssetHub Polkadot.
fn send_ksm_from_kusama_relay_through_asset_hub_kusama_to_asset_hub_polkadot() {
let amount = KUSAMA_ED * 100;
let sender = KusamaSender::get();
let receiver = AssetHubPolkadotReceiver::get();
let ksm_at_kusama: Location = Here.into();
let bridged_ksm_at_ah_polkadot = bridged_ksm_at_ah_polkadot();

create_foreign_on_ah_polkadot(bridged_ksm_at_ah_polkadot.clone(), true);
set_up_pool_with_dot_on_ah_polkadot(bridged_ksm_at_ah_polkadot.clone(), true);

let sov_ahp_on_ahk = AssetHubKusama::sovereign_account_of_parachain_on_other_global_consensus(
Polkadot,
AssetHubPolkadot::para_id(),
);
let sender_ksms_before = <Kusama as Chain>::account_data_of(sender.clone()).free;
let ksms_in_reserve_on_ahk_before =
<AssetHubKusama as Chain>::account_data_of(sov_ahp_on_ahk.clone()).free;
let receiver_ksms_before =
foreign_balance_on_ah_polkadot(bridged_ksm_at_ah_polkadot.clone(), &receiver);

// send KSMs over the bridge, teleport to local AH, reserve deposit to remote AH
{
let final_destination = Location::new(
1,
[GlobalConsensus(Polkadot), Parachain(AssetHubPolkadot::para_id().into())],
);
let intermediary_hop = Kusama::child_location_of(AssetHubKusama::para_id());
let context = Kusama::execute_with(KusamaRelayUniversalLocation::get);

// what happens at final destination
let beneficiary = AccountId32Junction { network: None, id: receiver.clone().into() }.into();
// use KSM as fees on the final destination (PAH), only use half the amount as some
// of it was already spent on intermediate hop (KAH)
let remote_fees: Asset = (bridged_ksm_at_ah_polkadot.clone(), amount / 2).into();
// buy execution using KSMs, then deposit all unspent KSMs
let xcm_on_final_dest = Xcm::<()>(vec![
BuyExecution { fees: remote_fees, weight_limit: WeightLimit::Unlimited },
DepositAsset { assets: Wild(AllCounted(1)), beneficiary },
]);

// what happens at intermediary hop
// reanchor final dest (Asset Hub Polkadot) to the view of hop (Asset Hub Kusama)
let mut final_destination = final_destination.clone();
final_destination.reanchor(&intermediary_hop, &context).unwrap();
// on Asset Hub Kusama, forward a deposit reserve KSMs to Asset Hub Polkadot
let xcm_on_hop = Xcm::<()>(vec![DepositReserveAsset {
assets: Wild(AllCounted(1)), // KSMs
dest: final_destination, // PAH
xcm: xcm_on_final_dest, // XCM to execute on PAH
}]);
// assets to send from Kusama Relay and how they reach the intermediary hop
let assets: Assets = vec![(ksm_at_kusama.clone(), amount).into()].into();
let asset_transfer_type = TransferType::Teleport;
let fees_id: AssetId = ksm_at_kusama.into();
let fees_transfer_type = TransferType::Teleport;

// initiate the transfer
send_assets_from_kusama_chain_through_kusama_ah_to_polkadot_ah(|| {
// send message over bridge
assert_ok!(Kusama::execute_with(|| {
let signed_origin = <Kusama as Chain>::RuntimeOrigin::signed(sender.clone());
<Kusama as KusamaPallet>::XcmPallet::transfer_assets_using_type_and_then(
signed_origin,
bx!(intermediary_hop.into()),
bx!(assets.into()),
bx!(asset_transfer_type),
bx!(fees_id.into()),
bx!(fees_transfer_type),
bx!(VersionedXcm::from(xcm_on_hop)),
WeightLimit::Unlimited,
)
}));
});
}

// verify expected events on final destination
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubPolkadot,
vec![
// issue KSMs on PAH
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => {
asset_id: *asset_id == bridged_ksm_at_ah_polkadot,
owner: *owner == AssetHubPolkadotReceiver::get(),
},
// message processed successfully
RuntimeEvent::MessageQueue(
pallet_message_queue::Event::Processed { success: true, .. }
) => {},
]
);
});

let sender_ksms_after = <Kusama as Chain>::account_data_of(sender.clone()).free;
let receiver_ksms_after = foreign_balance_on_ah_polkadot(bridged_ksm_at_ah_polkadot, &receiver);
let ksms_in_reserve_on_ahk_after =
<AssetHubKusama as Chain>::account_data_of(sov_ahp_on_ahk.clone()).free;

// Sender's balance is reduced
assert!(sender_ksms_before > sender_ksms_after);
// Reserve balance on KAH increased
assert!(ksms_in_reserve_on_ahk_after > ksms_in_reserve_on_ahk_before);
// Receiver's balance is increased
assert!(receiver_ksms_after > receiver_ksms_before);
}

#[test]
fn send_ksm_from_penpal_kusama_through_asset_hub_kusama_to_asset_hub_polkadot() {
let amount = ASSET_HUB_KUSAMA_ED * 10_000_000;
Expand Down Expand Up @@ -382,12 +462,23 @@ fn send_ksm_from_penpal_kusama_through_asset_hub_kusama_to_asset_hub_polkadot()
assets: Wild(AllCounted(assets.len() as u32)),
beneficiary,
}]);
send_assets_from_penpal_kusama_through_kusama_ah_to_polkadot_ah(
destination,
(assets, asset_transfer_type),
(fees_id, fees_transfer_type),
custom_xcm_on_dest,
);

send_assets_from_kusama_chain_through_kusama_ah_to_polkadot_ah(|| {
// send message over bridge
assert_ok!(PenpalA::execute_with(|| {
let signed_origin = <PenpalA as Chain>::RuntimeOrigin::signed(sender.clone());
<PenpalA as PenpalAPallet>::PolkadotXcm::transfer_assets_using_type_and_then(
signed_origin,
bx!(destination.into()),
bx!(assets.into()),
bx!(asset_transfer_type),
bx!(fees_id.into()),
bx!(fees_transfer_type),
bx!(VersionedXcm::from(custom_xcm_on_dest)),
WeightLimit::Unlimited,
)
}));
});
}

// process PAH incoming message and check events
Expand Down Expand Up @@ -517,12 +608,22 @@ fn send_back_dot_from_penpal_kusama_through_asset_hub_kusama_to_asset_hub_polkad
let fees_transfer_type = TransferType::DestinationReserve;

// initiate the transfer
send_assets_from_penpal_kusama_through_kusama_ah_to_polkadot_ah(
intermediary_hop,
(assets, asset_transfer_type),
(fees_id, fees_transfer_type),
xcm_on_hop,
);
send_assets_from_kusama_chain_through_kusama_ah_to_polkadot_ah(|| {
// send message over bridge
assert_ok!(PenpalA::execute_with(|| {
let signed_origin = <PenpalA as Chain>::RuntimeOrigin::signed(PenpalASender::get());
<PenpalA as PenpalAPallet>::PolkadotXcm::transfer_assets_using_type_and_then(
signed_origin,
bx!(intermediary_hop.into()),
bx!(assets.into()),
bx!(asset_transfer_type),
bx!(fees_id.into()),
bx!(fees_transfer_type),
bx!(VersionedXcm::from(xcm_on_hop)),
WeightLimit::Unlimited,
)
}));
});
}

// process PAH incoming message and check events
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ pub use kusama_polkadot_system_emulated_network::{
},
PenpalAssetOwner, PenpalBParaPallet as PenpalBPallet,
},
polkadot_emulated_chain::{genesis::ED as POLKADOT_ED, PolkadotRelayPallet as PolkadotPallet},
polkadot_emulated_chain::{
genesis::ED as POLKADOT_ED,
polkadot_runtime::xcm_config::UniversalLocation as PolkadotRelayUniversalLocation,
PolkadotRelayPallet as PolkadotPallet,
},
AssetHubKusamaPara as AssetHubKusama, AssetHubKusamaParaReceiver as AssetHubKusamaReceiver,
AssetHubKusamaParaSender as AssetHubKusamaSender, AssetHubPolkadotPara as AssetHubPolkadot,
AssetHubPolkadotParaReceiver as AssetHubPolkadotReceiver,
Expand Down
Loading

0 comments on commit 3de0be8

Please sign in to comment.