Skip to content

Commit

Permalink
extend XCM FeeManager
Browse files Browse the repository at this point in the history
  • Loading branch information
serban300 committed Oct 25, 2023
1 parent 230bd47 commit fd93ccc
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -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();
}

/// Adapter for resolving `NetworkId` based on `pub storage Flavor: RuntimeFlavor`.
Expand Down Expand Up @@ -614,7 +614,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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -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();
}

/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
Expand Down Expand Up @@ -570,7 +570,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>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use crate::{
BridgeGrandpaRococoInstance, BridgeGrandpaWococoInstance, DeliveryRewardInBalance,
RequiredStakeForStakeAndSlash,
},
bridge_hub_rococo_config::ToBridgeHubWococoHaulBlobExporter,
bridge_hub_wococo_config::ToBridgeHubRococoHaulBlobExporter,
bridge_hub_rococo_config::{ToBridgeHubWococoHaulBlobExporter, WococoGlobalConsensusNetwork},
bridge_hub_wococo_config::{RococoGlobalConsensusNetwork, ToBridgeHubRococoHaulBlobExporter},
};
use frame_support::{
match_types, parameter_types,
Expand All @@ -51,7 +51,7 @@ use xcm_builder::{
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeesToAccount,
XcmExportFeeToAccount, XcmFeeManagerFromComponents, XcmFeeToAccount,
};
use xcm_executor::{
traits::{ExportXcm, WithOriginFilter},
Expand All @@ -66,7 +66,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();
}

/// Adapter for resolving `NetworkId` based on `pub storage Flavor: RuntimeFlavor`.
Expand Down Expand Up @@ -282,7 +282,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,
// Just showcasing that we can direct fees from different bridges to different accounts.
// We use the `TreasuryAccount` as the receiver account in any case by design.
(
XcmExportFeeToAccount<
Self::AssetTransactor,
RococoGlobalConsensusNetwork,
AccountId,
TreasuryAccount,
>,
XcmExportFeeToAccount<
Self::AssetTransactor,
WococoGlobalConsensusNetwork,
AccountId,
TreasuryAccount,
>,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
),
>;
type MessageExporter = BridgeHubRococoOrBridgeHubWococoSwitchExporter;
type UniversalAliases = Nothing;
type CallDispatcher = WithOriginFilter<SafeCallFilter>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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();
}

/// We allow root and the Relay Chain council to execute privileged collator selection operations.
Expand Down Expand Up @@ -174,11 +174,9 @@ impl xcm_executor::Config for XcmConfig {
type MaxAssetsIntoHolding = ConstU32<8>;
type AssetLocker = ();
type AssetExchanger = ();
type FeeManager = XcmFeesToAccount<
Self,
type FeeManager = XcmFeeManagerFromComponents<
RelayOrOtherSystemParachains<SystemParachains, Runtime>,
AccountId,
TreasuryAccount,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
type MessageExporter = ();
type UniversalAliases = Nothing;
Expand Down
10 changes: 7 additions & 3 deletions polkadot/runtime/rococo/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 = (
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 6 additions & 3 deletions polkadot/runtime/westend/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 3 additions & 5 deletions polkadot/xcm/pallet-xcm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
95 changes: 70 additions & 25 deletions polkadot/xcm/xcm-builder/src/fee_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,87 @@
use core::marker::PhantomData;
use frame_support::traits::{Contains, Get};
use xcm::prelude::*;
use xcm_executor::traits::{FeeManager, FeeReason, TransactAsset};
use xcm_executor::traits::{FeeManager, FeeReason, HandleFee, TransactAsset};

/// A `FeeManager` implementation that simply deposits the fees handled into a specific on-chain
/// 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<MultiLocation>, FeeHandler: HandleFee> FeeManager
for XcmFeeManagerFromComponents<WaivedLocations, FeeHandler>
{
type HandleFee = FeeHandler;

fn is_waived(origin: Option<&MultiLocation>, _: FeeReason) -> bool {
let Some(loc) = origin else { return false };
WaivedLocations::contains(loc)
}
}

/// 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, and also
/// permits specifying `WaivedLocations` for locations that are privileged to not pay for fees. If
/// 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.
pub struct XcmFeesToAccount<XcmConfig, WaivedLocations, AccountId, ReceiverAccount>(
PhantomData<(XcmConfig, WaivedLocations, AccountId, ReceiverAccount)>,
pub struct XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>(
PhantomData<(AssetTransactor, AccountId, ReceiverAccount)>,
);

impl<
XcmConfig: xcm_executor::Config,
WaivedLocations: Contains<MultiLocation>,
AssetTransactor: TransactAsset,
AccountId: Clone + Into<[u8; 32]>,
ReceiverAccount: Get<Option<AccountId>>,
> FeeManager for XcmFeesToAccount<XcmConfig, WaivedLocations, AccountId, ReceiverAccount>
ReceiverAccount: Get<AccountId>,
> HandleFee for XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>
{
fn is_waived(origin: Option<&MultiLocation>, _: FeeReason) -> bool {
let Some(loc) = origin else { return false };
WaivedLocations::contains(loc)
fn handle_fee(
fee: MultiAssets,
context: Option<&XcmContext>,
_reason: FeeReason,
) -> MultiAssets {
let receiver = ReceiverAccount::get();
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: {:?}. Skipping fees: {:?}. \
They might be burned.",
e, asset,
);
}
}

MultiAssets::new()
}
}

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,
);
}
}
/// A `HandleFee` implementation that simply deposits the fees for
/// `ExportMessage { network: BridgedNetwork::get(), .. }` XCM instructions into a specific
/// on-chain `ReceiverAccount`.
pub struct XcmExportFeeToAccount<AssetTransactor, BridgedNetwork, AccountId, ReceiverAccount>(
PhantomData<(AssetTransactor, BridgedNetwork, AccountId, ReceiverAccount)>,
);

impl<
AssetTransactor: TransactAsset,
BridgedNetwork: Get<NetworkId>,
AccountId: Clone + Into<[u8; 32]>,
ReceiverAccount: Get<AccountId>,
> HandleFee for XcmExportFeeToAccount<AssetTransactor, BridgedNetwork, AccountId, ReceiverAccount>
{
fn handle_fee(
fee: MultiAssets,
context: Option<&XcmContext>,
reason: FeeReason,
) -> MultiAssets {
match reason {
FeeReason::Export(bridged_network) if bridged_network == BridgedNetwork::get() =>
XcmFeeToAccount::<AssetTransactor, AccountId, ReceiverAccount>::handle_fee(
fee, context, reason,
),
_ => fee,
}
}
}
2 changes: 1 addition & 1 deletion polkadot/xcm/xcm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ mod currency_adapter;
pub use currency_adapter::CurrencyAdapter;

mod fee_handling;
pub use fee_handling::XcmFeesToAccount;
pub use fee_handling::{XcmExportFeeToAccount, XcmFeeManagerFromComponents, XcmFeeToAccount};

mod fungibles_adapter;
pub use fungibles_adapter::{
Expand Down
3 changes: 2 additions & 1 deletion polkadot/xcm/xcm-builder/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,10 +523,11 @@ pub fn set_fee_waiver(waived: Vec<FeeReason>) {

pub struct TestFeeManager;
impl FeeManager for TestFeeManager {
type HandleFee = ();

fn is_waived(_: Option<&MultiLocation>, r: FeeReason) -> bool {
IS_WAIVED.with(|l| l.borrow().contains(&r))
}
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>) {}
}

#[derive(Clone, Eq, PartialEq, Debug)]
Expand Down
Loading

0 comments on commit fd93ccc

Please sign in to comment.