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

Commit

Permalink
Revamp xcm executor to add destination to FeeReason
Browse files Browse the repository at this point in the history
  • Loading branch information
yrong committed Jul 31, 2024
1 parent a5a384c commit 0cae888
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 13 deletions.
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

0 comments on commit 0cae888

Please sign in to comment.