Skip to content

Commit

Permalink
Westend/Rococo Asset Hub: pay xcm fees with sufficient assets (#2978)
Browse files Browse the repository at this point in the history
Set up the `TakeFirstAssetTrader` trader for Westend and Rococo Asset
Hubs to cover XCM fees with sufficient assets.

This PR reintroduces previously
[removed](#1845) trader
setups, as it was decided to keep both traders, `TakeFirstAssetTrader`
and `SwapFirstAssetTrader`, during the transition period.

---------

Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
  • Loading branch information
muharem and svyatonik authored Jan 18, 2024
1 parent 13f2342 commit dcc7652
Show file tree
Hide file tree
Showing 8 changed files with 1,071 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bridge-hub-westend-collator1: js-script ../helpers/best-finalized-header-at-brid

# step 4: send WND to //Alice on Rococo AH
# (that's a required part of a sibling 0001-asset-transfer-works-westend-to-rococo.zndsl test)
asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 60 seconds
asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 120 seconds

# step 5: elsewhere Rococo has sent ROC to //Alice - let's wait for it
asset-hub-westend-collator1: js-script ../helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Rococo" within 600 seconds
Expand All @@ -24,7 +24,7 @@ bridge-hub-westend-collator1: js-script ../helpers/relayer-rewards.js with "5FLS
bridge-hub-westend-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 300 seconds

# step 7: send wROC back to Alice at Rococo AH
asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-westend-local" within 60 seconds
asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-westend-local" within 120 seconds

# step 8: elsewhere Rococo has sent wWND to //Alice - let's wait for it
# (we wait until //Alice account increases here - there are no other transactionc that may increase it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bridge-hub-rococo-collator1: js-script ../helpers/best-finalized-header-at-bridg

# step 4: send ROC to //Alice on Westend AH
# (that's a required part of a sibling 0001-asset-transfer-works-rococo-to-westend.zndsl test)
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 60 seconds
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 120 seconds

# step 5: elsewhere Westend has sent WND to //Alice - let's wait for it
asset-hub-rococo-collator1: js-script ../helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Westend" within 600 seconds
Expand All @@ -24,7 +24,7 @@ bridge-hub-rococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSi
bridge-hub-rococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 300 seconds

# step 7: send wWND back to Alice at Westend AH
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local" within 60 seconds
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local" within 120 seconds

# step 8: elsewhere Westend has sent wROC to //Alice - let's wait for it
# (we wait until //Alice account increases here - there are no other transactionc that may increase it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,78 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() {
Some(Weight::from_parts(1_019_445_000, 200_000)),
)
}

/// Parachain should be able to send XCM paying its fee with sufficient asset
/// in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
let para_sovereign_account = AssetHubRococo::sovereign_account_id_of(
AssetHubRococo::sibling_location_of(PenpalA::para_id()),
);

// Force create and mint assets for Parachain's sovereign account
AssetHubRococo::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
ASSET_MIN_BALANCE * 1000000000,
);

// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubRococo::force_create_asset_call(
ASSET_ID,
para_sovereign_account.clone(),
true,
ASSET_MIN_BALANCE,
);

let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();

let root_origin = <PenpalA as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);

PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));

PenpalA::assert_xcm_pallet_sent();
});

AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;

AssetHubRococo::assert_xcmp_queue_success(Some(Weight::from_parts(
15_594_564_000,
562_893,
)));

assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account,
balance: *balance == fee_amount,
},
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == ASSET_ID,
},
]
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,78 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() {
Some(Weight::from_parts(1_019_445_000, 200_000)),
)
}

/// Parachain should be able to send XCM paying its fee with sufficient asset
/// in the System Parachain
#[test]
fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() {
let para_sovereign_account = AssetHubWestend::sovereign_account_id_of(
AssetHubWestend::sibling_location_of(PenpalB::para_id()),
);

// Force create and mint assets for Parachain's sovereign account
AssetHubWestend::force_create_and_mint_asset(
ASSET_ID,
ASSET_MIN_BALANCE,
true,
para_sovereign_account.clone(),
Some(Weight::from_parts(1_019_445_000, 200_000)),
ASSET_MIN_BALANCE * 1000000000,
);

// We just need a call that can pass the `SafeCallFilter`
// Call values are not relevant
let call = AssetHubWestend::force_create_asset_call(
ASSET_ID,
para_sovereign_account.clone(),
true,
ASSET_MIN_BALANCE,
);

let origin_kind = OriginKind::SovereignAccount;
let fee_amount = ASSET_MIN_BALANCE * 1000000;
let native_asset =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();

let root_origin = <PenpalB as Chain>::RuntimeOrigin::root();
let system_para_destination = PenpalB::sibling_location_of(AssetHubWestend::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
origin_kind,
native_asset,
para_sovereign_account.clone(),
);

PenpalB::execute_with(|| {
assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send(
root_origin,
bx!(system_para_destination),
bx!(xcm),
));

PenpalB::assert_xcm_pallet_sent();
});

AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;

AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts(
16_290_336_000,
562_893,
)));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => {
asset_id: *asset_id == ASSET_ID,
owner: *owner == para_sovereign_account,
balance: *balance == fee_amount,
},
RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == ASSET_ID,
},
]
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,32 @@ impl xcm_executor::Config for XcmConfig {
ResolveAssetTo<StakingPot, crate::NativeAndAssets>,
AccountId,
>,
// This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated
// `pallet_assets` instance - `Assets`.
cumulus_primitives_utility::TakeFirstAssetTrader<
AccountId,
AssetFeeAsExistentialDepositMultiplierFeeCharger,
TrustBackedAssetsConvertedConcreteId,
Assets,
cumulus_primitives_utility::XcmFeesTo32ByteAccount<
FungiblesTransactor,
AccountId,
XcmAssetFeesReceiver,
>,
>,
// This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated
// `pallet_assets` instance - `ForeignAssets`.
cumulus_primitives_utility::TakeFirstAssetTrader<
AccountId,
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger,
ForeignAssetsConvertedConcreteId,
ForeignAssets,
cumulus_primitives_utility::XcmFeesTo32ByteAccount<
ForeignFungiblesTransactor,
AccountId,
XcmAssetFeesReceiver,
>,
>,
);
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
Expand Down
Loading

0 comments on commit dcc7652

Please sign in to comment.