Files
pezkuwi-subxt/cumulus/parachains/common/src/xcm_config.rs
T
girazoki 8f2a3a5077 Statemint runtimes to accept sufficient assets as xcm fee payment (#1278)
* point to my branch

* girazoki-add-TakeFirstAssetTrader-to-utility

* Commit lock

* point at custom branch

* add new trader to statemine runtimes

* compiles

* Back to master

* Update last tomls

* Imports up

* remove non-needing imports

* FMT

* log messages properly

* Use TakeRevenue instead of HandleCredit

* Introduce xcm fee handler

* check total supply in tests

* FMT

* fix test

* Start decoupling balance calculation into different traits

* Make traits a bit more generic

* PR suggestions

* add import

* import well

* Place xcmfeesassethandler into parachains common

* fix tests

* config parameters

* Min amount to fee receiver

* Make minimum amount for block author to be at least the ED

* Doc in AssetFeeAsExistentialDepositMultiplier

* saturating sub

* make sure we dont enter twice

* FMT

* fmt again

* adapt tests

* Add doc and struct for weight refund

* Doc

* More doc

* PR suggestions

* store all info related to asset payment as multiasset

* return AssetNotFound instead of TooExpensive

* Use asset transactor to deposit fee

* uninstall from statemint

* R for RUntime and CON for BalanceConverter

* Rework logic to avoid unnecesary match and error

* Rework ED check, also in case of refund

* rework typo

* In case refund makes drop below ED, just refund the difference

* fix test westmint

* clone id

* move test imports to preamble

* move test imports to preamble

* test-utils with builderS

* lock file updated

* remove unused imports

Co-authored-by: Stephen Shelton <steve@brewcraft.org>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: joepetrowski <joe@parity.io>
2022-08-03 16:04:13 +00:00

110 lines
3.6 KiB
Rust

use crate::impls::AccountIdOf;
use core::marker::PhantomData;
use frame_support::{
log,
traits::{fungibles::Inspect, tokens::BalanceConversion},
weights::{Weight, WeightToFee, WeightToFeePolynomial},
};
use xcm::latest::prelude::*;
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<Call>(
origin: &MultiLocation,
message: &mut Xcm<Call>,
max_weight: Weight,
weight_credit: &mut Weight,
) -> Result<(), ()> {
Deny::should_execute(origin, message, max_weight, weight_credit)?;
Allow::should_execute(origin, message, max_weight, weight_credit)
}
}
// See issue #5233
pub struct DenyReserveTransferToRelayChain;
impl ShouldExecute for DenyReserveTransferToRelayChain {
fn should_execute<Call>(
origin: &MultiLocation,
message: &mut Xcm<Call>,
_max_weight: Weight,
_weight_credit: &mut Weight,
) -> Result<(), ()> {
if message.0.iter().any(|inst| {
matches!(
inst,
InitiateReserveWithdraw {
reserve: MultiLocation { parents: 1, interior: Here },
..
} | DepositReserveAsset { dest: MultiLocation { parents: 1, interior: Here }, .. } |
TransferReserveAsset {
dest: MultiLocation { parents: 1, interior: Here },
..
}
)
}) {
return Err(()) // Deny
}
// An unexpected reserve transfer has arrived from the Relay Chain. Generally, `IsReserve`
// should not allow this, but we just log it here.
if matches!(origin, MultiLocation { parents: 1, interior: Here }) &&
message.0.iter().any(|inst| matches!(inst, ReserveAssetDeposited { .. }))
{
log::warn!(
target: "xcm::barrier",
"Unexpected ReserveAssetDeposited from the Relay Chain",
);
}
// 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>(
PhantomData<(Runtime, WeightToFee, BalanceConverter)>,
);
impl<CurrencyBalance, Runtime, WeightToFee, BalanceConverter>
cumulus_primitives_utility::ChargeWeightInFungibles<
AccountIdOf<Runtime>,
pallet_assets::Pallet<Runtime>,
> for AssetFeeAsExistentialDepositMultiplier<Runtime, WeightToFee, BalanceConverter>
where
Runtime: pallet_assets::Config,
WeightToFee: WeightToFeePolynomial<Balance = CurrencyBalance>,
BalanceConverter: BalanceConversion<
CurrencyBalance,
<Runtime as pallet_assets::Config>::AssetId,
<Runtime as pallet_assets::Config>::Balance,
>,
AccountIdOf<Runtime>:
From<polkadot_primitives::v2::AccountId> + Into<polkadot_primitives::v2::AccountId>,
{
fn charge_weight_in_fungibles(
asset_id: <pallet_assets::Pallet<Runtime> as Inspect<AccountIdOf<Runtime>>>::AssetId,
weight: Weight,
) -> Result<<pallet_assets::Pallet<Runtime> 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)
}
}