Skip to content

Commit db7ed6d

Browse files
committed
Swaps for XCM delivery fees (#5131)
# Context Fees can already be paid in other assets locally thanks to the Trader implementations we have. This doesn't work when sending messages because delivery fees go through a different mechanism altogether. The idea is to fix this leveraging the `AssetExchanger` config item that's able to turn the asset the user wants to pay fees in into the asset the router expects for delivery fees. # Main addition An adapter was needed to use `pallet-asset-conversion` for exchanging assets in XCM. This was created in #5130. The XCM executor was modified to use `AssetExchanger` (when available) to swap assets to pay for delivery fees. ## Limitations We can only pay for delivery fees in different assets in intermediate hops. We can't pay in different assets locally. The first hop will always need the native token of the chain (or whatever is specified in the `XcmRouter`). This is a byproduct of using the `BuyExecution` instruction to know which asset should be used for delivery fee payment. Since this instruction is not present when executing an XCM locally, we are left with this limitation. To illustrate this limitation, I'll show two scenarios. All chains involved have pools. ### Scenario 1 Parachain A --> Parachain B Here, parachain A can use any asset in a pool with its native asset to pay for local execution fees. However, as of now we can't use those for local delivery fees. This means transfers from A to B need some amount of A's native token to pay for delivery fees. ### Scenario 2 Parachain A --> Parachain C --> Parachain B Here, Parachain C's remote delivery fees can be paid with any asset in a pool with its native asset. This allows a reserve asset transfer between A and B with C as the reserve to only need A's native token at the starting hop. After that, it could all be pool assets. ## Future work The fact that delivery fees go through a totally different mechanism results in a lot of bugs and pain points. Unfortunately, this is not so easy to solve in a backwards compatible manner. Delivery fees will be integrated into the language in future XCM versions, following polkadot-fellows/xcm-format#53. Old PR: #4375.
1 parent 16e9c0f commit db7ed6d

File tree

1 file changed

+10
-1
lines changed
  • polkadot/xcm/xcm-executor/src

1 file changed

+10
-1
lines changed

polkadot/xcm/xcm-executor/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub struct XcmExecutor<Config: config::Config> {
9090
/// Stores the current message's weight.
9191
message_weight: Weight,
9292
_config: PhantomData<Config>,
93+
assetClaimer: Option<Location>,
9394
}
9495

9596
#[cfg(any(test, feature = "runtime-benchmarks"))]
@@ -357,7 +358,11 @@ impl<Config: config::Config> XcmExecutor<Config> {
357358
original_origin = ?self.original_origin,
358359
"Trapping assets in holding register",
359360
);
360-
let effective_origin = self.context.origin.as_ref().unwrap_or(&self.original_origin);
361+
let effective_orgin = if let Some(assetClaimer) = self.assetClaimer {
362+
assetClaimer.as_ref().unwrap_or(&self.original_origin)
363+
} else {
364+
self.context.origin.as_ref().unwrap_or(&self.original_origin)
365+
};
361366
let trap_weight =
362367
Config::AssetTrap::drop_assets(effective_origin, self.holding, &self.context);
363368
weight_used.saturating_accrue(trap_weight);
@@ -1065,6 +1070,10 @@ impl<Config: config::Config> XcmExecutor<Config> {
10651070
self.error = None;
10661071
Ok(())
10671072
},
1073+
SetAssetClaimer { location } => {
1074+
self.assetClaimer = Some(location);
1075+
Ok(())
1076+
},
10681077
ClaimAsset { assets, ticket } => {
10691078
let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?;
10701079
self.ensure_can_subsume_assets(assets.len())?;

0 commit comments

Comments
 (0)