From d6036ddb56936831d3d820b0d99f6bb3e40fe830 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 24 Jun 2024 18:36:09 +0300 Subject: [PATCH] emulated-test: Send WNDs: PenpalRococo -> AssetHubRococo -> AssetHubWestend Send both ROCs and WNDs, ROCs are only used to pay for transport fees on AHR, and are not sent over the bridge. --- Cargo.lock | 1 + .../bridges/bridge-hub-rococo/Cargo.toml | 5 +- .../bridges/bridge-hub-rococo/src/lib.rs | 1 + .../src/tests/asset_transfers.rs | 173 +++++++++++++----- 4 files changed, 132 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22564aa9cae31..87bb601675ce5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1991,6 +1991,7 @@ dependencies = [ "pallet-xcm", "parachains-common", "parity-scale-codec", + "penpal-runtime", "rococo-system-emulated-network", "rococo-westend-system-emulated-network", "scale-info", diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index 23dee370bf33d..12ae785f0eefa 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -36,11 +36,12 @@ pallet-bridge-messages = { workspace = true } parachains-common = { workspace = true, default-features = true } testnet-parachains-constants = { features = ["rococo"], workspace = true, default-features = true } cumulus-pallet-xcmp-queue = { workspace = true } -bridge-hub-rococo-runtime = { workspace = true } emulated-integration-tests-common = { workspace = true } +asset-hub-rococo-runtime = { workspace = true } +bridge-hub-rococo-runtime = { workspace = true } +penpal-runtime = { workspace = true } rococo-westend-system-emulated-network = { workspace = true } rococo-system-emulated-network = { workspace = true } -asset-hub-rococo-runtime = { workspace = true } # Snowbridge snowbridge-core = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs index 0415af580ef8a..4cce11ec16b56 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs @@ -37,6 +37,7 @@ mod imports { }, }; pub use parachains_common::AccountId; + pub use penpal_runtime::xcm_config::UniversalLocation as PenpalUniversalLocation; pub use rococo_westend_system_emulated_network::{ asset_hub_rococo_emulated_chain::{ genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs index 9bc6b70d5c7cb..3f32b65f31acf 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs @@ -31,7 +31,7 @@ fn send_asset_from_asset_hub_rococo_to_asset_hub_westend(id: Location, amount: u assert_bridge_hub_westend_message_received(); } -fn send_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( +fn send_local_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( id: Location, transfer_amount: u128, ) { @@ -102,6 +102,100 @@ fn send_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( assert_bridge_hub_westend_message_received(); } +fn send_bridged_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( + asset: Asset, + // needs to be ROCs + fee: Asset, +) { + let destination = asset_hub_westend_location(); + let local_asset_hub: Location = PenpalA::sibling_location_of(AssetHubRococo::para_id()); + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of( + AssetHubRococo::sibling_location_of(PenpalA::para_id()), + ); + let sov_ahw_on_ahr = AssetHubRococo::sovereign_account_of_parachain_on_other_global_consensus( + Westend, + AssetHubWestend::para_id(), + ); + + // fund the AHR's SA on BHR for paying bridge transport fees + BridgeHubRococo::fund_para_sovereign(AssetHubRococo::para_id(), 10_000_000_000_000u128); + + // set XCM versions + PenpalA::force_xcm_version(local_asset_hub.clone(), XCM_VERSION); + AssetHubRococo::force_xcm_version(destination.clone(), XCM_VERSION); + BridgeHubRococo::force_xcm_version(bridge_hub_westend_location(), XCM_VERSION); + + // send message over bridge + assert_ok!(PenpalA::execute_with(|| { + let signed_origin = ::RuntimeOrigin::signed(PenpalASender::get()); + let beneficiary: Location = + AccountId32Junction { network: None, id: AssetHubWestendReceiver::get().into() }.into(); + + let context = PenpalUniversalLocation::get(); + // use WND as fees on the final destination (AHW) + let remote_fees = asset.clone().reanchored(&destination, &context).unwrap(); + // buy execution using WNDs, then deposit all remaining WNDs + let xcm_on_final_dest = Xcm::<()>(vec![ + BuyExecution { fees: remote_fees.into(), weight_limit: WeightLimit::Unlimited }, + DepositAsset { assets: Wild(AllCounted(1)), beneficiary }, + ]); + + // reanchor final dest (Asset Hub Westend) to the view of hop (Asset Hub Rococo) + let mut dest = destination.clone(); + dest.reanchor(&local_asset_hub, &context).unwrap(); + // on Asset Hub Rococo, forward a request to withdraw reserve on Asset Hub Westend + let xcm_on_hop = Xcm::<()>(vec![InitiateReserveWithdraw { + assets: Definite(asset.clone().into()), // WNDs + reserve: dest, // AHW + xcm: xcm_on_final_dest, // XCM to execute on AHW + }]); + + let assets: Assets = vec![asset, fee.clone()].into(); + let fees_id: AssetId = fee.id; + + // asset transfers: + // - bridged asset (WND): + // 1. reserve-withdraw derivative (wWND) from Penpal's SA on AHR + // 2. reserve-withdraw actual asset (WND) from AHR's SA on AHW + // - fee/local asset (ROC) - doesn't get bridged over, we pay fees with WND on other side: + // 1. reserve-withdraw asset (ROC) from Penpal's SA on AHR (only used to pay for fees on + // AHR, because we didn't have wWND on Penpal) + ::PolkadotXcm::transfer_assets_using_type_and_then( + signed_origin, + bx!(local_asset_hub.into()), + bx!(assets.clone().into()), + bx!(TransferType::DestinationReserve), + bx!(fees_id.into()), + bx!(TransferType::DestinationReserve), + bx!(VersionedXcm::from(xcm_on_hop)), + WeightLimit::Unlimited, + ) + })); + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + AssetHubRococo, + vec![ + // Amount to reserve transfer is withdrawn from Penpal's sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Burned { who, .. } + ) => { + who: *who == sov_penpal_on_ahr.clone().into(), + }, + // Amount deposited in AHW's sovereign account + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { + who: *who == sov_ahw_on_ahr.clone().into(), + }, + RuntimeEvent::XcmpQueue( + cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. } + ) => {}, + ] + ); + }); + assert_bridge_hub_rococo_message_accepted(true); + assert_bridge_hub_westend_message_received(); +} + #[test] fn send_rocs_from_asset_hub_rococo_to_asset_hub_westend() { let roc_at_asset_hub_rococo: v3::Location = v3::Parent.into(); @@ -290,24 +384,20 @@ fn send_wnds_from_asset_hub_rococo_to_asset_hub_westend() { assert_eq!(wnds_in_reserve_on_ahw_after, wnds_in_reserve_on_ahw_before - amount_to_send); } -#[test] -fn send_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() { +fn set_up_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend( + amount: u128, +) -> (Location, Location) { let roc_at_rococo_parachains: Location = Parent.into(); let roc_at_asset_hub_westend = Location::new(2, [Junction::GlobalConsensus(NetworkId::Rococo)]); - let owner: AccountId = AssetHubWestend::account_id_of(ALICE); + let asset_owner: AccountId = AssetHubWestend::account_id_of(ALICE); AssetHubWestend::force_create_foreign_asset( roc_at_asset_hub_westend.clone().try_into().unwrap(), - owner, + asset_owner, true, ASSET_MIN_BALANCE, vec![], ); - let sov_ahw_on_ahr = AssetHubRococo::sovereign_account_of_parachain_on_other_global_consensus( - Westend, - AssetHubWestend::para_id(), - ); - let amount = ASSET_HUB_ROCOCO_ED * 10_000_000; let penpal_location = AssetHubRococo::sibling_location_of(PenpalA::para_id()); let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location); // fund Penpal's sovereign account on AssetHub @@ -319,7 +409,19 @@ fn send_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() PenpalASender::get(), amount * 2, ); + (roc_at_rococo_parachains, roc_at_asset_hub_westend) +} + +#[test] +fn send_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() { + let amount = ASSET_HUB_ROCOCO_ED * 10_000_000; + let (roc_at_rococo_parachains, roc_at_asset_hub_westend) = + set_up_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend(amount); + let sov_ahw_on_ahr = AssetHubRococo::sovereign_account_of_parachain_on_other_global_consensus( + Westend, + AssetHubWestend::para_id(), + ); let rocs_in_reserve_on_ahr_before = ::account_data_of(sov_ahw_on_ahr.clone()).free; let sender_rocs_before = PenpalA::execute_with(|| { @@ -336,7 +438,7 @@ fn send_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() &AssetHubWestendReceiver::get(), ) }); - send_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( + send_local_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( roc_at_rococo_parachains.clone(), amount, ); @@ -388,7 +490,11 @@ fn send_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() v3::Location::new(2, [v3::Junction::GlobalConsensus(v3::NetworkId::Westend)]); let wnd_at_rococo_parachains_latest: Location = wnd_at_rococo_parachains.try_into().unwrap(); let owner: AccountId = AssetHubRococo::account_id_of(ALICE); - println!("🤡 1"); + let amount = ASSET_HUB_ROCOCO_ED * 10_000_000; + + let (roc_at_rococo_parachains, _) = + set_up_rocs_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend(amount); + AssetHubRococo::force_create_foreign_asset( wnd_at_rococo_parachains, owner.clone(), @@ -403,8 +509,6 @@ fn send_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() ASSET_MIN_BALANCE, vec![], ); - let amount = ASSET_HUB_ROCOCO_ED * 10_000_000; - println!("🤡 2"); // 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( @@ -413,12 +517,6 @@ fn send_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() ); AssetHubWestend::fund_accounts(vec![(sov_ahr_on_ahw.clone(), amount * 2)]); - let sov_ahw_on_ahr = AssetHubRococo::sovereign_account_of_parachain_on_other_global_consensus( - NetworkId::Westend, - AssetHubWestend::para_id(), - ); - println!("🤡 3"); - let penpal_location = AssetHubRococo::sibling_location_of(PenpalA::para_id()); let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location); // fund Penpal's sovereign account on AssetHub @@ -428,7 +526,7 @@ fn send_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() sov_penpal_on_ahr, amount * 2, ); - println!("🤡 4"); + // fund Penpal's sender account PenpalA::mint_foreign_asset( ::RuntimeOrigin::signed(PenpalAssetOwner::get()), @@ -436,12 +534,6 @@ fn send_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() PenpalASender::get(), amount * 2, ); - println!("🤡 5"); - - let wnds_in_reserve_on_ahr_before = AssetHubRococo::execute_with(|| { - type Assets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains, &sov_ahw_on_ahr) - }); let sender_wnds_before = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; >::balance( @@ -449,26 +541,21 @@ fn send_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() &PenpalASender::get(), ) }); - println!("🤡 6"); let receiver_wnds_before = ::account_data_of(AssetHubWestendReceiver::get()).free; - send_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( - wnd_at_rococo_parachains_latest.clone(), - amount, + send_bridged_asset_from_penpal_rococo_through_local_asset_hub_to_westend_asset_hub( + (wnd_at_rococo_parachains_latest.clone(), amount).into(), + (roc_at_rococo_parachains, amount).into(), ); AssetHubWestend::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; - println!("🤡 AHW events: {:?}", ::events()); assert_expected_events!( AssetHubWestend, vec![ // issue ROCs on AHW - // RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { - // asset_id: *asset_id == roc_at_rococo_parachains, - // owner: *owner == AssetHubWestendReceiver::get(), - // }, + RuntimeEvent::Balances(pallet_balances::Event::Issued { .. }) => {}, // message processed successfully RuntimeEvent::MessageQueue( pallet_message_queue::Event::Processed { success: true, .. } @@ -486,16 +573,10 @@ fn send_wnds_from_penpal_rococo_through_asset_hub_rococo_to_asset_hub_westend() }); let receiver_wnds_after = ::account_data_of(AssetHubWestendReceiver::get()).free; - let wnds_in_reserve_on_ahr_after = AssetHubRococo::execute_with(|| { - type Assets = ::ForeignAssets; - >::balance(wnd_at_rococo_parachains, &sov_ahw_on_ahr) - }); - // Sender's balance is reduced - assert!(sender_wnds_after < sender_wnds_before); - // Receiver's balance is increased + // Sender's balance is reduced by sent "amount" + assert_eq!(sender_wnds_after, sender_wnds_before - amount); + // Receiver's balance is increased by no more than "amount" assert!(receiver_wnds_after > receiver_wnds_before); - // Reserve balance is increased by sent amount (less fess) - assert!(wnds_in_reserve_on_ahr_after > wnds_in_reserve_on_ahr_before); - assert!(wnds_in_reserve_on_ahr_after <= wnds_in_reserve_on_ahr_before + amount); + assert!(receiver_wnds_after <= receiver_wnds_before + amount); }