Files
pezkuwi-subxt/polkadot/xcm/xcm-builder/src/fee_handling.rs
T
Francisco Aguirre 8428f678fe XCMv4 (#1230)
# Note for reviewer

Most changes are just syntax changes necessary for the new version.
Most important files should be the ones under the `xcm` folder.

# Description 

Added XCMv4.

## Removed `Multi` prefix
The following types have been renamed:
- MultiLocation -> Location
- MultiAsset -> Asset
- MultiAssets -> Assets
- InteriorMultiLocation -> InteriorLocation
- MultiAssetFilter -> AssetFilter
- VersionedMultiAsset -> VersionedAsset
- WildMultiAsset -> WildAsset
- VersionedMultiLocation -> VersionedLocation

In order to fix a name conflict, the `Assets` in `xcm-executor` were
renamed to `HoldingAssets`, as they represent assets in holding.

## Removed `Abstract` asset id

It was not being used anywhere and this simplifies the code.

Now assets are just constructed as follows:

```rust
let asset: Asset = (AssetId(Location::new(1, Here)), 100u128).into();
```

No need for specifying `Concrete` anymore.

## Outcome is now a named fields struct

Instead of

```rust
pub enum Outcome {
  Complete(Weight),
  Incomplete(Weight, Error),
  Error(Error),
}
```

we now have

```rust
pub enum Outcome {
  Complete { used: Weight },
  Incomplete { used: Weight, error: Error },
  Error { error: Error },
}
```

## Added Reanchorable trait

Now both locations and assets implement this trait, making it easier to
reanchor both.

## New syntax for building locations and junctions

Now junctions are built using the following methods:

```rust
let location = Location {
    parents: 1,
    interior: [Parachain(1000), PalletInstance(50), GeneralIndex(1984)].into()
};
```

or

```rust
let location = Location::new(1, [Parachain(1000), PalletInstance(50), GeneralIndex(1984)]);
```

And they are matched like so:

```rust
match location.unpack() {
  (1, [Parachain(id)]) => ...
  (0, Here) => ...,
  (1, [_]) => ...,
}
```

This syntax is mandatory in v4, and has been also implemented for v2 and
v3 for easier migration.

This was needed to make all sizes smaller.

# TODO
- [x] Scaffold v4
- [x] Port github.com/paritytech/polkadot/pull/7236
- [x] Remove `Multi` prefix
- [x] Remove `Abstract` asset id

---------

Co-authored-by: command-bot <>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
2024-01-16 18:18:04 +00:00

113 lines
3.9 KiB
Rust

// Copyright Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use core::marker::PhantomData;
use frame_support::traits::{Contains, Get};
use xcm::prelude::*;
use xcm_executor::traits::{FeeManager, FeeReason, TransactAsset};
/// Handles the fees that are taken by certain XCM instructions.
pub trait HandleFee {
/// Do something with the fee which has been paid. Doing nothing here silently burns the
/// fees.
///
/// Returns any part of the fee that wasn't consumed.
fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) -> Assets;
}
// Default `HandleFee` implementation that just burns the fee.
impl HandleFee for () {
fn handle_fee(_: Assets, _: Option<&XcmContext>, _: FeeReason) -> Assets {
Assets::new()
}
}
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
impl HandleFee for Tuple {
fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) -> Assets {
let mut unconsumed_fee = fee;
for_tuples!( #(
unconsumed_fee = Tuple::handle_fee(unconsumed_fee, context, reason.clone());
if unconsumed_fee.is_none() {
return unconsumed_fee;
}
)* );
unconsumed_fee
}
}
/// A `FeeManager` implementation that permits the specified `WaivedLocations` to not pay for fees
/// and that uses the provided `HandleFee` implementation otherwise.
pub struct XcmFeeManagerFromComponents<WaivedLocations, HandleFee>(
PhantomData<(WaivedLocations, HandleFee)>,
);
impl<WaivedLocations: Contains<Location>, FeeHandler: HandleFee> FeeManager
for XcmFeeManagerFromComponents<WaivedLocations, FeeHandler>
{
fn is_waived(origin: Option<&Location>, _: FeeReason) -> bool {
let Some(loc) = origin else { return false };
WaivedLocations::contains(loc)
}
fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) {
FeeHandler::handle_fee(fee, context, reason);
}
}
/// Try to deposit the given fee in the specified account.
/// Burns the fee in case of a failure.
pub fn deposit_or_burn_fee<AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 32]>>(
fee: Assets,
context: Option<&XcmContext>,
receiver: AccountId,
) {
let dest = AccountId32 { network: None, id: receiver.into() }.into();
for asset in fee.into_inner() {
if let Err(e) = AssetTransactor::deposit_asset(&asset, &dest, context) {
log::trace!(
target: "xcm::fees",
"`AssetTransactor::deposit_asset` returned error: {:?}. Burning fee: {:?}. \
They might be burned.",
e, asset,
);
}
}
}
/// A `HandleFee` implementation that simply deposits the fees into a specific on-chain
/// `ReceiverAccount`.
///
/// It reuses the `AssetTransactor` configured on the XCM executor to deposit fee assets. If
/// the `AssetTransactor` returns an error while calling `deposit_asset`, then a warning will be
/// logged and the fee burned.
pub struct XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>(
PhantomData<(AssetTransactor, AccountId, ReceiverAccount)>,
);
impl<
AssetTransactor: TransactAsset,
AccountId: Clone + Into<[u8; 32]>,
ReceiverAccount: Get<AccountId>,
> HandleFee for XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>
{
fn handle_fee(fee: Assets, context: Option<&XcmContext>, _reason: FeeReason) -> Assets {
deposit_or_burn_fee::<AssetTransactor, _>(fee, context, ReceiverAccount::get());
Assets::new()
}
}