Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Custom Feehandler & Add destination to FeeReason #167

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ use parachains_common::{
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::xcm_sender::ExponentialPrice;
use snowbridge_router_primitives::inbound::GlobalConsensusEthereumConvertsFor;
use sp_runtime::traits::{AccountIdConversion, ConvertInto};
use sp_runtime::{
traits::{AccountIdConversion, ConvertInto},
SaturatedConversion,
};
use sp_std::marker::PhantomData;
use testnet_parachains_constants::rococo::snowbridge::{
EthereumNetwork, INBOUND_QUEUE_PALLET_INDEX,
Expand All @@ -60,15 +63,15 @@ use xcm_builder::{
AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry,
DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, ExporterFor, FrameTransactionalProcessor,
FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription,
InspectMessageQueues, IsConcrete, LocalMint, NetworkExportTableItem, NoChecking,
NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HandleFee,
HashedDescription, InspectMessageQueues, IsConcrete, LocalMint, NetworkExportTableItem,
NoChecking, NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, StartsWith,
StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
};
use xcm_executor::XcmExecutor;
use xcm_executor::{traits::FeeReason, XcmExecutor};

parameter_types! {
pub const TokenLocation: Location = Location::parent();
Expand Down Expand Up @@ -420,7 +423,15 @@ impl xcm_executor::Config for XcmConfig {
type AssetExchanger = ();
type FeeManager = XcmFeeManagerFromComponents<
WaivedLocations,
SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
(
SnowbridgeExportFee<
Balance,
bridging::to_ethereum::BridgeHubEthereumBaseFee,
TokenLocation,
bridging::to_ethereum::EthereumLocation,
>,
SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
),
>;
type MessageExporter = ();
type UniversalAliases =
Expand Down Expand Up @@ -536,6 +547,58 @@ impl<Bridges, Router: InspectMessageQueues, UniversalLocation> InspectMessageQue
}
}

pub struct SnowbridgeExportFee<Balance, ExportFeeBalance, FeeAssetLocation, EthereumLocation>(
PhantomData<(Balance, ExportFeeBalance, FeeAssetLocation, EthereumLocation)>,
);

impl<Balance, ExportFeeBalance, FeeAssetLocation, EthereumLocation> HandleFee
for SnowbridgeExportFee<Balance, ExportFeeBalance, FeeAssetLocation, EthereumLocation>
where
Balance: From<u128> + Into<u128>,
ExportFeeBalance: Get<Balance>,
FeeAssetLocation: Get<Location>,
EthereumLocation: Get<Location>,
{
fn handle_fee(
fees: xcm::prelude::Assets,
_context: Option<&XcmContext>,
reason: FeeReason,
) -> xcm::prelude::Assets {
// Check the reason to see if this export is for snowbridge.
if !matches!(reason, FeeReason::InitiateReserveWithdraw { destination }
if destination == EthereumLocation::get()
) || fees.len() != 1
{
return fees
}

let fee = fees.get(0);

if let Some(Asset { id: location, .. }) = fee {
if location.0 != FeeAssetLocation::get() {
return fees
}
}

let fee_amount: Option<u128> = if let Some(Asset { fun: Fungible(amount), .. }) = fee {
Some(amount.clone())
} else {
None
};

if fee_amount.is_none() {
return fees
}

let export_fee_balance = ExportFeeBalance::get();

let delivery_fee =
fee_amount.unwrap().saturating_sub(export_fee_balance.saturated_into::<u128>());

return Asset::from((FeeAssetLocation::get(), delivery_fee)).into()
}
}

/// The means for routing XCM messages which are not for local execution into the right message
/// queues.
pub type XcmRouter = WithUniqueTopic<(
Expand Down Expand Up @@ -735,6 +798,8 @@ pub mod bridging {
PalletInstance(INBOUND_QUEUE_PALLET_INDEX)
]
);
pub EthereumLocation: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get())]);


/// Set up exporters configuration.
/// `Option<Asset>` represents static "base fee" which is used for total delivery fee calculation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ benchmarks_instance_pallet! {

let (expected_fees_mode, expected_assets_in_holding) = T::DeliveryHelper::ensure_successful_delivery(
&sender_location,
&reserve,
FeeReason::InitiateReserveWithdraw,
&reserve.clone(),
FeeReason::InitiateReserveWithdraw{ destination:reserve.clone() },
);
let sender_account_balance_before = T::TransactAsset::balance(&sender_account);

Expand All @@ -175,7 +175,7 @@ benchmarks_instance_pallet! {
let instruction = Instruction::InitiateReserveWithdraw {
// Worst case is looking through all holdings for every asset explicitly - respecting the limit `MAX_ITEMS_IN_ASSETS`.
assets: Definite(holding.into_inner().into_iter().take(MAX_ITEMS_IN_ASSETS).collect::<Vec<_>>().into()),
reserve,
reserve: reserve.clone(),
xcm: Xcm(vec![])
};
let xcm = Xcm(vec![instruction]);
Expand Down
12 changes: 10 additions & 2 deletions polkadot/xcm/xcm-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,11 @@ impl<Config: config::Config> XcmExecutor<Config> {
message.extend(xcm.0.into_iter());
// put back transport_fee in holding register to be charged by XcmSender
self.holding.subsume_assets(transport_fee);
self.send(dest, Xcm(message), FeeReason::DepositReserveAsset)?;
self.send(
dest.clone(),
Xcm(message),
FeeReason::DepositReserveAsset { destination: dest },
)?;
Ok(())
});
if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() {
Expand All @@ -921,7 +925,11 @@ impl<Config: config::Config> XcmExecutor<Config> {
);
let mut message = vec![WithdrawAsset(assets), ClearOrigin];
message.extend(xcm.0.into_iter());
self.send(reserve, Xcm(message), FeeReason::InitiateReserveWithdraw)?;
self.send(
reserve.clone(),
Xcm(message),
FeeReason::InitiateReserveWithdraw { destination: reserve },
)?;
Ok(())
});
if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() {
Expand Down
4 changes: 2 additions & 2 deletions polkadot/xcm/xcm-executor/src/traits/fee_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ pub enum FeeReason {
/// When the `TransferReserveAsset` instruction is called.
TransferReserveAsset,
/// When the `DepositReserveAsset` instruction is called.
DepositReserveAsset,
DepositReserveAsset { destination: Location },
/// When the `InitiateReserveWithdraw` instruction is called.
InitiateReserveWithdraw,
InitiateReserveWithdraw { destination: Location },
/// When the `InitiateTeleport` instruction is called.
InitiateTeleport,
/// When the `QueryPallet` instruction is called.
Expand Down
Loading