Files
pezkuwi-subxt/parachains/common/src/xcm_config.rs
T
Keith Yeung cf4a6efbbd Companion for paritytech/polkadot#7098 (#2469)
* Companion for paritytech/polkadot#7098

* Fixes

* Add missing benchmarked function

* Fix typo

* update lockfile for {"polkadot", "substrate"}

---------

Co-authored-by: parity-processbot <>
2023-04-27 10:48:22 +00:00

140 lines
4.7 KiB
Rust

use crate::impls::AccountIdOf;
use core::{marker::PhantomData, ops::ControlFlow};
use frame_support::{
log,
traits::{
fungibles::Inspect, tokens::ConversionToAssetBalance, ContainsPair, ProcessMessageError,
},
weights::Weight,
};
use sp_runtime::traits::Get;
use xcm::latest::prelude::*;
use xcm_builder::{CreateMatcher, MatchXcm};
use xcm_executor::traits::ShouldExecute;
//TODO: move DenyThenTry to polkadot's xcm module.
/// Deny executing the XCM if it matches any of the Deny filter regardless of anything else.
/// If it passes the Deny, and matches one of the Allow cases then it is let through.
pub struct DenyThenTry<Deny, Allow>(PhantomData<Deny>, PhantomData<Allow>)
where
Deny: ShouldExecute,
Allow: ShouldExecute;
impl<Deny, Allow> ShouldExecute for DenyThenTry<Deny, Allow>
where
Deny: ShouldExecute,
Allow: ShouldExecute,
{
fn should_execute<RuntimeCall>(
origin: &MultiLocation,
message: &mut [Instruction<RuntimeCall>],
max_weight: Weight,
weight_credit: &mut Weight,
) -> Result<(), ProcessMessageError> {
Deny::should_execute(origin, message, max_weight, weight_credit)?;
Allow::should_execute(origin, message, max_weight, weight_credit)
}
}
// See issue <https://github.com/paritytech/polkadot/issues/5233>
pub struct DenyReserveTransferToRelayChain;
impl ShouldExecute for DenyReserveTransferToRelayChain {
fn should_execute<RuntimeCall>(
origin: &MultiLocation,
message: &mut [Instruction<RuntimeCall>],
_max_weight: Weight,
_weight_credit: &mut Weight,
) -> Result<(), ProcessMessageError> {
message.matcher().match_next_inst_while(
|_| true,
|inst| match inst {
InitiateReserveWithdraw {
reserve: MultiLocation { parents: 1, interior: Here },
..
} |
DepositReserveAsset {
dest: MultiLocation { parents: 1, interior: Here }, ..
} |
TransferReserveAsset {
dest: MultiLocation { parents: 1, interior: Here }, ..
} => {
Err(ProcessMessageError::Unsupported) // Deny
},
// An unexpected reserve transfer has arrived from the Relay Chain. Generally,
// `IsReserve` should not allow this, but we just log it here.
ReserveAssetDeposited { .. }
if matches!(origin, MultiLocation { parents: 1, interior: Here }) =>
{
log::warn!(
target: "xcm::barrier",
"Unexpected ReserveAssetDeposited from the Relay Chain",
);
Ok(ControlFlow::Continue(()))
},
_ => Ok(ControlFlow::Continue(())),
},
)?;
// Permit everything else
Ok(())
}
}
/// A `ChargeFeeInFungibles` implementation that converts the output of
/// a given WeightToFee implementation an amount charged in
/// a particular assetId from pallet-assets
pub struct AssetFeeAsExistentialDepositMultiplier<
Runtime,
WeightToFee,
BalanceConverter,
AssetInstance: 'static,
>(PhantomData<(Runtime, WeightToFee, BalanceConverter, AssetInstance)>);
impl<CurrencyBalance, Runtime, WeightToFee, BalanceConverter, AssetInstance>
cumulus_primitives_utility::ChargeWeightInFungibles<
AccountIdOf<Runtime>,
pallet_assets::Pallet<Runtime, AssetInstance>,
> for AssetFeeAsExistentialDepositMultiplier<Runtime, WeightToFee, BalanceConverter, AssetInstance>
where
Runtime: pallet_assets::Config<AssetInstance>,
WeightToFee: frame_support::weights::WeightToFee<Balance = CurrencyBalance>,
BalanceConverter: ConversionToAssetBalance<
CurrencyBalance,
<Runtime as pallet_assets::Config<AssetInstance>>::AssetId,
<Runtime as pallet_assets::Config<AssetInstance>>::Balance,
>,
AccountIdOf<Runtime>:
From<polkadot_primitives::AccountId> + Into<polkadot_primitives::AccountId>,
{
fn charge_weight_in_fungibles(
asset_id: <pallet_assets::Pallet<Runtime, AssetInstance> as Inspect<
AccountIdOf<Runtime>,
>>::AssetId,
weight: Weight,
) -> Result<
<pallet_assets::Pallet<Runtime, AssetInstance> as Inspect<AccountIdOf<Runtime>>>::Balance,
XcmError,
> {
let amount = WeightToFee::weight_to_fee(&weight);
// If the amount gotten is not at least the ED, then make it be the ED of the asset
// This is to avoid burning assets and decreasing the supply
let asset_amount = BalanceConverter::to_asset_balance(amount, asset_id)
.map_err(|_| XcmError::TooExpensive)?;
Ok(asset_amount)
}
}
/// Accepts an asset if it is a native asset from a particular `MultiLocation`.
pub struct ConcreteNativeAssetFrom<Location>(PhantomData<Location>);
impl<Location: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation>
for ConcreteNativeAssetFrom<Location>
{
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
log::trace!(target: "xcm::filter_asset_location",
"ConcreteNativeAsset asset: {:?}, origin: {:?}, location: {:?}",
asset, origin, Location::get());
matches!(asset.id, Concrete(ref id) if id == origin && origin == &Location::get())
}
}