Direct XCM ExportMessage fees for different bridges to different receiver accounts (#2021)

This commit is contained in:
Serban Iorga
2023-11-01 17:11:07 +02:00
committed by GitHub
parent 8507f45cef
commit dce5a8da66
14 changed files with 275 additions and 71 deletions
@@ -53,7 +53,7 @@ use xcm_builder::{
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeesToAccount,
XcmFeeManagerFromComponents, XcmFeeToAccount,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
@@ -75,7 +75,7 @@ parameter_types! {
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub const GovernanceLocation: MultiLocation = MultiLocation::parent();
pub TreasuryAccount: Option<AccountId> = Some(TREASURY_PALLET_ID.into_account_truncating());
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
}
@@ -619,7 +619,10 @@ impl xcm_executor::Config for XcmConfig {
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type AssetLocker = ();
type AssetExchanger = ();
type FeeManager = XcmFeesToAccount<Self, WaivedLocations, AccountId, TreasuryAccount>;
type FeeManager = XcmFeeManagerFromComponents<
WaivedLocations,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
type MessageExporter = ();
type UniversalAliases =
(bridging::to_wococo::UniversalAliases, bridging::to_rococo::UniversalAliases);
@@ -683,7 +683,7 @@ mod asset_hub_rococo_tests {
bridging_to_asset_hub_wococo,
WeightLimit::Unlimited,
Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()),
Some(xcm_config::TreasuryAccount::get().unwrap()),
Some(xcm_config::TreasuryAccount::get()),
)
}
@@ -871,7 +871,7 @@ mod asset_hub_wococo_tests {
with_wococo_flavor_bridging_to_asset_hub_rococo,
WeightLimit::Unlimited,
Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()),
Some(xcm_config::TreasuryAccount::get().unwrap()),
Some(xcm_config::TreasuryAccount::get()),
)
}
@@ -52,7 +52,7 @@ use xcm_builder::{
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeesToAccount,
XcmFeeManagerFromComponents, XcmFeeToAccount,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
@@ -73,7 +73,7 @@ parameter_types! {
pub PoolAssetsPalletLocation: MultiLocation =
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub TreasuryAccount: Option<AccountId> = Some(TREASURY_PALLET_ID.into_account_truncating());
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(westend_runtime_constants::TREASURY_PALLET_ID)).into();
}
@@ -562,7 +562,10 @@ impl xcm_executor::Config for XcmConfig {
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type AssetLocker = ();
type AssetExchanger = ();
type FeeManager = XcmFeesToAccount<Self, WaivedLocations, AccountId, TreasuryAccount>;
type FeeManager = XcmFeeManagerFromComponents<
WaivedLocations,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = WithOriginFilter<SafeCallFilter>;
@@ -24,9 +24,18 @@ use crate::{
BridgeGrandpaRococoInstance, BridgeGrandpaWococoInstance, DeliveryRewardInBalance,
RequiredStakeForStakeAndSlash,
},
bridge_hub_rococo_config::ToBridgeHubWococoHaulBlobExporter,
bridge_hub_wococo_config::ToBridgeHubRococoHaulBlobExporter,
bridge_hub_rococo_config::{
AssetHubRococoParaId, BridgeHubWococoChainId, BridgeHubWococoMessagesLane,
ToBridgeHubWococoHaulBlobExporter, WococoGlobalConsensusNetwork,
},
bridge_hub_wococo_config::{
AssetHubWococoParaId, BridgeHubRococoChainId, BridgeHubRococoMessagesLane,
RococoGlobalConsensusNetwork, ToBridgeHubRococoHaulBlobExporter,
},
};
use bp_messages::LaneId;
use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams};
use bp_runtime::ChainId;
use frame_support::{
match_types, parameter_types,
traits::{ConstU32, Contains, Equals, Everything, Nothing},
@@ -43,18 +52,20 @@ use polkadot_runtime_common::xcm_sender::ExponentialPrice;
use rococo_runtime_constants::system_parachain;
use sp_core::Get;
use sp_runtime::traits::AccountIdConversion;
use sp_std::marker::PhantomData;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter,
DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, IsConcrete, ParentAsSuperuser,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeesToAccount,
deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom,
AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, HandleFee,
IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
XcmFeeToAccount,
};
use xcm_executor::{
traits::{ExportXcm, WithOriginFilter},
traits::{ExportXcm, FeeReason, TransactAsset, WithOriginFilter},
XcmExecutor,
};
@@ -66,7 +77,7 @@ parameter_types! {
X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into()));
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
pub TreasuryAccount: Option<AccountId> = Some(TREASURY_PALLET_ID.into_account_truncating());
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
}
@@ -290,7 +301,26 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = PolkadotXcm;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = XcmFeesToAccount<Self, WaivedLocations, AccountId, TreasuryAccount>;
type FeeManager = XcmFeeManagerFromComponents<
WaivedLocations,
(
XcmExportFeeToRelayerRewardAccounts<
Self::AssetTransactor,
WococoGlobalConsensusNetwork,
AssetHubWococoParaId,
BridgeHubWococoChainId,
BridgeHubWococoMessagesLane,
>,
XcmExportFeeToRelayerRewardAccounts<
Self::AssetTransactor,
RococoGlobalConsensusNetwork,
AssetHubRococoParaId,
BridgeHubRococoChainId,
BridgeHubRococoMessagesLane,
>,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
),
>;
type MessageExporter = BridgeHubRococoOrBridgeHubWococoSwitchExporter;
type UniversalAliases = Nothing;
type CallDispatcher = WithOriginFilter<SafeCallFilter>;
@@ -401,3 +431,96 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter {
}
}
}
/// A `HandleFee` implementation that simply deposits the fees for `ExportMessage` XCM instructions
/// into the accounts that are used for paying the relayer rewards.
/// Burns the fees in case of a failure.
pub struct XcmExportFeeToRelayerRewardAccounts<
AssetTransactor,
DestNetwork,
DestParaId,
DestBridgeHubId,
BridgeLaneId,
>(PhantomData<(AssetTransactor, DestNetwork, DestParaId, DestBridgeHubId, BridgeLaneId)>);
impl<
AssetTransactor: TransactAsset,
DestNetwork: Get<NetworkId>,
DestParaId: Get<cumulus_primitives_core::ParaId>,
DestBridgeHubId: Get<ChainId>,
BridgeLaneId: Get<LaneId>,
> HandleFee
for XcmExportFeeToRelayerRewardAccounts<
AssetTransactor,
DestNetwork,
DestParaId,
DestBridgeHubId,
BridgeLaneId,
>
{
fn handle_fee(
fee: MultiAssets,
maybe_context: Option<&XcmContext>,
reason: FeeReason,
) -> MultiAssets {
if matches!(reason, FeeReason::Export { network: bridged_network, destination }
if bridged_network == DestNetwork::get() &&
destination == X1(Parachain(DestParaId::get().into())))
{
// We have 2 relayer rewards accounts:
// - the SA of the source parachain on this BH: this pays the relayers for delivering
// Source para -> Target Para message delivery confirmations
// - the SA of the destination parachain on this BH: this pays the relayers for
// delivering Target para -> Source Para messages
// We split the `ExportMessage` fee between these 2 accounts.
let source_para_account = PayRewardFromAccount::<
pallet_balances::Pallet<Runtime>,
AccountId,
>::rewards_account(RewardsAccountParams::new(
BridgeLaneId::get(),
DestBridgeHubId::get(),
RewardsAccountOwner::ThisChain,
));
let dest_para_account = PayRewardFromAccount::<
pallet_balances::Pallet<Runtime>,
AccountId,
>::rewards_account(RewardsAccountParams::new(
BridgeLaneId::get(),
DestBridgeHubId::get(),
RewardsAccountOwner::BridgedChain,
));
for asset in fee.into_inner() {
match asset.fun {
Fungible(total_fee) => {
let source_fee = total_fee / 2;
deposit_or_burn_fee::<AssetTransactor, _>(
MultiAsset { id: asset.id, fun: Fungible(source_fee) }.into(),
maybe_context,
source_para_account.clone(),
);
let dest_fee = total_fee - source_fee;
deposit_or_burn_fee::<AssetTransactor, _>(
MultiAsset { id: asset.id, fun: Fungible(dest_fee) }.into(),
maybe_context,
dest_para_account.clone(),
);
},
NonFungible(_) => {
deposit_or_burn_fee::<AssetTransactor, _>(
asset.into(),
maybe_context,
source_para_account.clone(),
);
},
}
}
return MultiAssets::new()
}
fee
}
}
@@ -41,7 +41,7 @@ use xcm_builder::{
NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WithComputedOrigin, WithUniqueTopic, XcmFeesToAccount,
WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount,
};
use xcm_executor::XcmExecutor;
@@ -51,7 +51,7 @@ parameter_types! {
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
pub UniversalLocation: InteriorMultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
pub const ExecutiveBody: BodyId = BodyId::Executive;
pub TreasuryAccount: Option<AccountId> = Some(TREASURY_PALLET_ID.into_account_truncating());
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
}
@@ -199,7 +199,10 @@ impl xcm_executor::Config for XcmConfig {
type MaxAssetsIntoHolding = ConstU32<8>;
type AssetLocker = ();
type AssetExchanger = ();
type FeeManager = XcmFeesToAccount<Self, WaivedLocations, AccountId, TreasuryAccount>;
type FeeManager = XcmFeeManagerFromComponents<
WaivedLocations,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
+7 -3
View File
@@ -43,7 +43,8 @@ use xcm_builder::{
DescribeFamily, FixedWeightBounds, HashedDescription, IsChildSystemParachain, IsConcrete,
MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeesToAccount,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
XcmFeeToAccount,
};
use xcm_executor::XcmExecutor;
@@ -53,7 +54,7 @@ parameter_types! {
pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into();
pub CheckAccount: AccountId = XcmPallet::check_account();
pub LocalCheckAccount: (AccountId, MintLocation) = (CheckAccount::get(), MintLocation::Local);
pub TreasuryAccount: Option<AccountId> = Some(Treasury::account_id());
pub TreasuryAccount: AccountId = Treasury::account_id();
}
pub type LocationConverter = (
@@ -191,7 +192,10 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = XcmFeesToAccount<Self, SystemParachains, AccountId, TreasuryAccount>;
type FeeManager = XcmFeeManagerFromComponents<
SystemParachains,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
+6 -3
View File
@@ -44,7 +44,7 @@ use xcm_builder::{
DescribeFamily, HashedDescription, IsConcrete, MintLocation, OriginToPluralityVoice,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeesToAccount,
XcmFeeManagerFromComponents, XcmFeeToAccount,
};
use xcm_executor::XcmExecutor;
@@ -54,7 +54,7 @@ parameter_types! {
pub const UniversalLocation: InteriorMultiLocation = X1(GlobalConsensus(ThisNetwork::get()));
pub CheckAccount: AccountId = XcmPallet::check_account();
pub LocalCheckAccount: (AccountId, MintLocation) = (CheckAccount::get(), MintLocation::Local);
pub TreasuryAccount: Option<AccountId> = Some(Treasury::account_id());
pub TreasuryAccount: AccountId = Treasury::account_id();
/// The asset ID for the asset that we use to pay for message delivery fees.
pub FeeAssetId: AssetId = Concrete(TokenLocation::get());
/// The base fee for the message delivery fees.
@@ -185,7 +185,10 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = XcmFeesToAccount<Self, SystemParachains, AccountId, TreasuryAccount>;
type FeeManager = XcmFeeManagerFromComponents<
SystemParachains,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
@@ -561,7 +561,7 @@ benchmarks! {
let (expected_fees_mode, expected_assets_in_holding) = T::DeliveryHelper::ensure_successful_delivery(
&origin,
&destination.into(),
FeeReason::Export(network),
FeeReason::Export { network, destination },
);
let sender_account = T::AccountIdConverter::convert_location(&origin).unwrap();
let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
+3 -5
View File
@@ -34,7 +34,7 @@ use xcm_builder::{
AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia,
ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible,
FixedWeightBounds, IsConcrete, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, XcmFeesToAccount,
SovereignSignedViaLocation, TakeWeightCredit, XcmFeeManagerFromComponents, XcmFeeToAccount,
};
use xcm_executor::XcmExecutor;
@@ -343,11 +343,9 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = XcmFeesToAccount<
Self,
type FeeManager = XcmFeeManagerFromComponents<
EverythingBut<XcmFeesNotWaivedLocations>,
AccountId,
XcmFeesTargetAccount,
XcmFeeToAccount<Self::AssetTransactor, AccountId, XcmFeesTargetAccount>,
>;
type MessageExporter = ();
type UniversalAliases = Nothing;
+90 -27
View File
@@ -19,40 +19,103 @@ use frame_support::traits::{Contains, Get};
use xcm::prelude::*;
use xcm_executor::traits::{FeeManager, FeeReason, TransactAsset};
/// A `FeeManager` implementation that simply deposits the fees handled into a specific on-chain
/// `ReceiverAccount`.
///
/// It reuses the `AssetTransactor` configured on the XCM executor to deposit fee assets, and also
/// permits specifying `WaivedLocations` for locations that are privileged to not pay for fees. If
/// the `AssetTransactor` returns an error while calling `deposit_asset`, then a warning will be
/// logged.
pub struct XcmFeesToAccount<XcmConfig, WaivedLocations, AccountId, ReceiverAccount>(
PhantomData<(XcmConfig, WaivedLocations, AccountId, ReceiverAccount)>,
/// 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: MultiAssets, context: Option<&XcmContext>, reason: FeeReason)
-> MultiAssets;
}
// Default `HandleFee` implementation that just burns the fee.
impl HandleFee for () {
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>, _: FeeReason) -> MultiAssets {
MultiAssets::new()
}
}
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
impl HandleFee for Tuple {
fn handle_fee(
fee: MultiAssets,
context: Option<&XcmContext>,
reason: FeeReason,
) -> MultiAssets {
let mut unconsumed_fee = fee;
for_tuples!( #(
unconsumed_fee = Tuple::handle_fee(unconsumed_fee, context, reason);
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<
XcmConfig: xcm_executor::Config,
WaivedLocations: Contains<MultiLocation>,
AccountId: Clone + Into<[u8; 32]>,
ReceiverAccount: Get<Option<AccountId>>,
> FeeManager for XcmFeesToAccount<XcmConfig, WaivedLocations, AccountId, ReceiverAccount>
impl<WaivedLocations: Contains<MultiLocation>, FeeHandler: HandleFee> FeeManager
for XcmFeeManagerFromComponents<WaivedLocations, FeeHandler>
{
fn is_waived(origin: Option<&MultiLocation>, _: FeeReason) -> bool {
let Some(loc) = origin else { return false };
WaivedLocations::contains(loc)
}
fn handle_fee(fees: MultiAssets, context: Option<&XcmContext>) {
if let Some(receiver) = ReceiverAccount::get() {
let dest = AccountId32 { network: None, id: receiver.into() }.into();
for asset in fees.into_inner() {
if let Err(e) = XcmConfig::AssetTransactor::deposit_asset(&asset, &dest, context) {
log::trace!(
target: "xcm::fees",
"`AssetTransactor::deposit_asset` returned error: {:?}, burning fees: {:?}",
e, asset,
);
}
}
fn handle_fee(fee: MultiAssets, 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: MultiAssets,
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: MultiAssets,
context: Option<&XcmContext>,
_reason: FeeReason,
) -> MultiAssets {
deposit_or_burn_fee::<AssetTransactor, _>(fee, context, ReceiverAccount::get());
MultiAssets::new()
}
}
+3 -1
View File
@@ -68,7 +68,9 @@ mod currency_adapter;
pub use currency_adapter::CurrencyAdapter;
mod fee_handling;
pub use fee_handling::XcmFeesToAccount;
pub use fee_handling::{
deposit_or_burn_fee, HandleFee, XcmFeeManagerFromComponents, XcmFeeToAccount,
};
mod fungibles_adapter;
pub use fungibles_adapter::{
+2 -1
View File
@@ -526,7 +526,8 @@ impl FeeManager for TestFeeManager {
fn is_waived(_: Option<&MultiLocation>, r: FeeReason) -> bool {
IS_WAIVED.with(|l| l.borrow().contains(&r))
}
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>) {}
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>, _: FeeReason) {}
}
#[derive(Clone, Eq, PartialEq, Debug)]
+3 -3
View File
@@ -248,7 +248,7 @@ impl<Config: config::Config> ExecuteXcm<Config::RuntimeCall> for XcmExecutor<Con
for asset in fees.inner() {
Config::AssetTransactor::withdraw_asset(&asset, &origin, None)?;
}
Config::FeeManager::handle_fee(fees, None);
Config::FeeManager::handle_fee(fees, None, FeeReason::ChargeFees);
}
Ok(())
}
@@ -851,7 +851,7 @@ impl<Config: config::Config> XcmExecutor<Config> {
destination,
xcm,
)?;
self.take_fee(fee, FeeReason::Export(network))?;
self.take_fee(fee, FeeReason::Export { network, destination })?;
Config::MessageExporter::deliver(ticket)?;
Ok(())
},
@@ -962,7 +962,7 @@ impl<Config: config::Config> XcmExecutor<Config> {
} else {
self.holding.try_take(fee.into()).map_err(|_| XcmError::NotHoldingFees)?.into()
};
Config::FeeManager::handle_fee(paid, Some(&self.context));
Config::FeeManager::handle_fee(paid, Some(&self.context), reason);
Ok(())
}
@@ -18,12 +18,12 @@ use xcm::prelude::*;
/// Handle stuff to do with taking fees in certain XCM instructions.
pub trait FeeManager {
/// Determine if a fee which would normally payable should be waived.
/// Determine if a fee should be waived.
fn is_waived(origin: Option<&MultiLocation>, r: FeeReason) -> bool;
/// Do something with the fee which has been paid. Doing nothing here silently burns the
/// fees.
fn handle_fee(fee: MultiAssets, context: Option<&XcmContext>);
fn handle_fee(fee: MultiAssets, context: Option<&XcmContext>, r: FeeReason);
}
/// Context under which a fee is paid.
@@ -42,7 +42,7 @@ pub enum FeeReason {
/// When the `QueryPallet` instruction is called.
QueryPallet,
/// When the `ExportMessage` instruction is called (and includes the network ID).
Export(NetworkId),
Export { network: NetworkId, destination: InteriorMultiLocation },
/// The `charge_fees` API.
ChargeFees,
/// When the `LockAsset` instruction is called.
@@ -55,5 +55,6 @@ impl FeeManager for () {
fn is_waived(_: Option<&MultiLocation>, _: FeeReason) -> bool {
false
}
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>) {}
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>, _: FeeReason) {}
}