mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
XCM WeightTrader: Swap Fee Asset for Native Asset (#1845)
Implements an XCM executor `WeightTrader`, facilitating fee payments in any asset that can be exchanged for a native asset. A few constraints need to be observed: - `buy_weight` and `refund` operations must be atomic, as another weight trader implementation might be attempted in case of failure. - swap credit must be utilized since there isn’t an account to which an asset of some class can be deposited with a guarantee to meet the existential deposit requirement. Also, operating with credits enhances the efficiency of the weight trader - https://github.com/paritytech/polkadot-sdk/pull/1677 related PRs: - (depends) https://github.com/paritytech/polkadot-sdk/pull/2031 - (depends) https://github.com/paritytech/polkadot-sdk/pull/1677 - (caused) https://github.com/paritytech/polkadot-sdk/pull/1847 - (caused) https://github.com/paritytech/polkadot-sdk/pull/1876 // DONE: impl `OnUnbalanced` for a `fungible/s` credit // DONE: make the trader free from a concept of a native currency and drop few fallible conversions. related issue - https://github.com/paritytech/polkadot-sdk/issues/1842 // DONE: tests --------- Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
-75
@@ -27,78 +27,3 @@ 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 =
|
||||
(X2(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,
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
+127
@@ -264,3 +264,130 @@ fn cannot_create_pool_from_pool_assets() {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pay_xcm_fee_with_some_asset_swapped_for_native() {
|
||||
let asset_native = asset_hub_westend_runtime::xcm_config::WestendLocation::get();
|
||||
let asset_one = MultiLocation {
|
||||
parents: 0,
|
||||
interior: X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())),
|
||||
};
|
||||
let penpal = AssetHubWestend::sovereign_account_id_of(AssetHubWestend::sibling_location_of(
|
||||
PenpalB::para_id(),
|
||||
));
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
// set up pool with ASSET_ID <> NATIVE pair
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::create(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
ASSET_ID.into(),
|
||||
AssetHubWestendSender::get().into(),
|
||||
ASSET_MIN_BALANCE,
|
||||
));
|
||||
assert!(<AssetHubWestend as AssetHubWestendPallet>::Assets::asset_exists(ASSET_ID));
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::mint(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
ASSET_ID.into(),
|
||||
AssetHubWestendSender::get().into(),
|
||||
3_000_000_000_000,
|
||||
));
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
Box::new(asset_native),
|
||||
Box::new(asset_one),
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
|
||||
]
|
||||
);
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
Box::new(asset_native),
|
||||
Box::new(asset_one),
|
||||
1_000_000_000_000,
|
||||
2_000_000_000_000,
|
||||
0,
|
||||
0,
|
||||
AssetHubWestendSender::get().into()
|
||||
));
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { lp_token_minted: *lp_token_minted == 1414213562273, },
|
||||
]
|
||||
);
|
||||
|
||||
// ensure `penpal` sovereign account has no native tokens and mint some `ASSET_ID`
|
||||
assert_eq!(
|
||||
<AssetHubWestend as AssetHubWestendPallet>::Balances::free_balance(penpal.clone()),
|
||||
0
|
||||
);
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::touch_other(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
ASSET_ID.into(),
|
||||
penpal.clone().into(),
|
||||
));
|
||||
|
||||
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::mint(
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
|
||||
ASSET_ID.into(),
|
||||
penpal.clone().into(),
|
||||
10_000_000_000_000,
|
||||
));
|
||||
});
|
||||
|
||||
PenpalB::execute_with(|| {
|
||||
// send xcm transact from `penpal` account which as only `ASSET_ID` tokens on
|
||||
// `AssetHubWestend`
|
||||
let call = AssetHubWestend::force_create_asset_call(
|
||||
ASSET_ID + 1000,
|
||||
penpal.clone(),
|
||||
true,
|
||||
ASSET_MIN_BALANCE,
|
||||
);
|
||||
|
||||
let penpal_root = <PenpalB as Chain>::RuntimeOrigin::root();
|
||||
let fee_amount = 4_000_000_000_000u128;
|
||||
let asset_one =
|
||||
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), fee_amount)
|
||||
.into();
|
||||
let asset_hub_location = PenpalB::sibling_location_of(AssetHubWestend::para_id()).into();
|
||||
let xcm = xcm_transact_paid_execution(
|
||||
call,
|
||||
OriginKind::SovereignAccount,
|
||||
asset_one,
|
||||
penpal.clone(),
|
||||
);
|
||||
|
||||
assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send(
|
||||
penpal_root,
|
||||
bx!(asset_hub_location),
|
||||
bx!(xcm),
|
||||
));
|
||||
|
||||
PenpalB::assert_xcm_pallet_sent();
|
||||
});
|
||||
|
||||
AssetHubWestend::execute_with(|| {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_xcmp_queue_success(None);
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapCreditExecuted { .. },) => {},
|
||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true,.. }) => {},
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user