mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 00:31:02 +00:00
pallet-xcm: add new flexible transfer_assets() call/extrinsic (#2388)
# Motivation (+testing)
### Enable easy `ForeignAssets` transfers using `pallet-xcm`
We had just previously added capabilities to teleport fees during
reserve-based transfers, but what about reserve-transferring fees when
needing to teleport some non-fee asset?
This PR aligns everything under either explicit reserve-transfer,
explicit teleport, or this new flexible `transfer_assets()` which can
mix and match as needed with fewer artificial constraints imposed to the
user.
This will enable, for example, a (non-system) parachain to teleport
their `ForeignAssets` assets to AssetHub while using DOT to pay fees.
(the assets are teleported - as foreign assets should from their owner
chain - while DOT used for fees can only be reserve-based transferred
between said parachain and AssetHub).
Added `xcm-emulator` tests for this scenario ^.
# Description
Reverts `(limited_)reserve_transfer_assets` to only allow reserve-based
transfers for all `assets` including fees.
Similarly `(limited_)teleport_assets` only allows teleports for all
`assets` including fees.
For complex combinations of asset transfers where assets and fees may
have different reserves or different reserve/teleport trust
configurations, users can use the newly added `transfer_assets()`
extrinsic which is more flexible in allowing more complex scenarios.
`assets` (excluding `fees`) must have same reserve location or otherwise
be teleportable to `dest`.
No limitations imposed on `fees`.
- for local reserve: transfer assets to sovereign account of destination
chain and forward a notification XCM to `dest` to mint and deposit
reserve-based assets to `beneficiary`.
- for destination reserve: burn local assets and forward a notification
to `dest` chain to withdraw the reserve assets from this chain's
sovereign account and deposit them to `beneficiary`.
- for remote reserve: burn local assets, forward XCM to reserve chain to
move reserves from this chain's SA to `dest` chain's SA, and forward
another XCM to `dest` to mint and deposit reserve-based assets to
`beneficiary`.
- for teleports: burn local assets and forward XCM to `dest` chain to
mint/teleport assets and deposit them to `beneficiary`.
## Review notes
Only around 500 lines are prod code (see `pallet_xcm/src/lib.rs`), the
rest of the PR is new tests and improving existing tests.
---------
Co-authored-by: command-bot <>
This commit is contained in:
@@ -1431,6 +1431,55 @@ impl_runtime_apis! {
|
||||
ParentThen(Parachain(random_para_id).into()).into(),
|
||||
))
|
||||
}
|
||||
|
||||
fn set_up_complex_asset_transfer(
|
||||
) -> Option<(MultiAssets, u32, MultiLocation, Box<dyn FnOnce()>)> {
|
||||
// Transfer to Relay some local AH asset (local-reserve-transfer) while paying
|
||||
// fees using teleported native token.
|
||||
// (We don't care that Relay doesn't accept incoming unknown AH local asset)
|
||||
let dest = Parent.into();
|
||||
|
||||
let fee_amount = EXISTENTIAL_DEPOSIT;
|
||||
let fee_asset: MultiAsset = (MultiLocation::parent(), fee_amount).into();
|
||||
|
||||
let who = frame_benchmarking::whitelisted_caller();
|
||||
// Give some multiple of the existential deposit
|
||||
let balance = fee_amount + EXISTENTIAL_DEPOSIT * 1000;
|
||||
let _ = <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(
|
||||
&who, balance,
|
||||
);
|
||||
// verify initial balance
|
||||
assert_eq!(Balances::free_balance(&who), balance);
|
||||
|
||||
// set up local asset
|
||||
let asset_amount = 10u128;
|
||||
let initial_asset_amount = asset_amount * 10;
|
||||
let (asset_id, _, _) = pallet_assets::benchmarking::create_default_minted_asset::<
|
||||
Runtime,
|
||||
pallet_assets::Instance1
|
||||
>(true, initial_asset_amount);
|
||||
let asset_location = MultiLocation::new(
|
||||
0,
|
||||
X2(PalletInstance(50), GeneralIndex(u32::from(asset_id).into()))
|
||||
);
|
||||
let transfer_asset: MultiAsset = (asset_location, asset_amount).into();
|
||||
|
||||
let assets: MultiAssets = vec![fee_asset.clone(), transfer_asset].into();
|
||||
let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 };
|
||||
|
||||
// verify transferred successfully
|
||||
let verify = Box::new(move || {
|
||||
// verify native balance after transfer, decreased by transferred fee amount
|
||||
// (plus transport fees)
|
||||
assert!(Balances::free_balance(&who) <= balance - fee_amount);
|
||||
// verify asset balance decreased by exactly transferred amount
|
||||
assert_eq!(
|
||||
Assets::balance(asset_id.into(), &who),
|
||||
initial_asset_amount - asset_amount,
|
||||
);
|
||||
});
|
||||
Some((assets, fee_index as u32, dest, verify))
|
||||
}
|
||||
}
|
||||
|
||||
use pallet_xcm_bridge_hub_router::benchmarking::{
|
||||
|
||||
Reference in New Issue
Block a user