Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support different assets for delivery fees #4375

Closed
wants to merge 52 commits into from

Conversation

franciscoaguirre
Copy link
Contributor

@franciscoaguirre franciscoaguirre commented May 3, 2024

Separated the PR in two: #5130 and #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 alltogether.
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 for AssetExchanger to work with pallet-asset-conversion was added to xcm-builder: FungiblesPoolAdapter.
This was set as AssetExchanger in the XCM configuration of both asset-hub-rococo and asset-hub-westend.

The XCM executor was modified to use this exchanger to swap assets to pay for delivery fees.

How it works

In order to pay delivery fees with different assets, you need to add some type as the AssetExchanger in your XCM executor.
The new adapter, FungiblesPoolAdapter, allows an easy interface to connect with anything that implements the SwapCredit and QuoteExchangePrice traits. Currently, they are implemented by pallet-asset-conversion.

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 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 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 this RFC.

Dear reviewer

  • Most of the changes are in the XCM executor: polkadot/xcm/xcm-executor/src/lib.rs.
  • The new adapter is in polkadot/xcm/xcm-builder/src/asset_exchange.rs.
  • The asset hub runtimes have been updated with a new PoolAssetsExchanger type:
    • Westend: cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs
    • Rococo: cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs
  • The tests live in cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs

@muharem muharem self-requested a review May 8, 2024 11:34
@Polkadot-Forum
Copy link

This pull request has been mentioned on Polkadot Forum. There might be relevant details there:

https://forum.polkadot.network/t/xcm-user-and-developer-experience-improvements/4511/21

@command-bot
Copy link

command-bot bot commented May 22, 2024

Here's a link to docs

Copy link
Contributor

@muharem muharem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we disable the FeeManager for our runtime setups and try to account a transport weights in Weigher. Even if we cannot do it properly, may be some reasonable constants would be enough.
For local execution the transport fee will be included in extrinsics' weights, and for the remote execution a user will pay with BuyExecution for transport fee as well.
To avoid a double payment with jit_withdraw fee mode, we will need to disable it via config (here we also can provide some info for dependent teams).

After reading the weights payment model in the xcm pallet and the executor, I do not see a good way to make it work with various assets through the FeeManager without breaking the APIs. With the new xcm version we can have a better solution.

polkadot/xcm/xcm-executor/src/traits/fee_manager.rs Outdated Show resolved Hide resolved
polkadot/xcm/xcm-executor/src/lib.rs Outdated Show resolved Hide resolved
polkadot/xcm/xcm-executor/src/lib.rs Outdated Show resolved Hide resolved
polkadot/xcm/pallet-xcm/src/lib.rs Outdated Show resolved Hide resolved
polkadot/xcm/pallet-xcm/src/lib.rs Outdated Show resolved Hide resolved
polkadot/xcm/pallet-xcm/src/lib.rs Outdated Show resolved Hide resolved
polkadot/xcm/xcm-executor/src/lib.rs Outdated Show resolved Hide resolved
polkadot/xcm/xcm-executor/src/lib.rs Outdated Show resolved Hide resolved
acatangiu added a commit to acatangiu/polkadot-sdk that referenced this pull request Jun 28, 2024
…set hub

Send bridged WNDs: Penpal Rococo -> AH Rococo -> AH Westend
Send bridged ROCs: Penpal Westend -> AH Westend -> AH Rococo

The tests send both ROCs and WNDs, for each direction the native asset is only
used to pay for the transport fees on the local AssetHub, and are not sent over
the bridge.

Including the native asset won't be necessary anymore once we get paritytech#4375.

Signed-off-by: Adrian Catangiu <[email protected]>
acatangiu added a commit to acatangiu/polkadot-sdk that referenced this pull request Jul 1, 2024
…set hub

Send bridged WNDs: Penpal Rococo -> AH Rococo -> AH Westend
Send bridged ROCs: Penpal Westend -> AH Westend -> AH Rococo

The tests send both ROCs and WNDs, for each direction the native asset is only
used to pay for the transport fees on the local AssetHub, and are not sent over
the bridge.

Including the native asset won't be necessary anymore once we get paritytech#4375.

Signed-off-by: Adrian Catangiu <[email protected]>
@yrong
Copy link
Contributor

yrong commented Jul 18, 2024

@franciscoaguirre Cool, thanks for the effort!

One question for the use case transfering WETH from AH back to Ethereum(AH --> BH --> Ethereum), currently the delivery fee is configured on AH here in native token(i.e. DOT).

So with this PR is that possible to config it in WETH while still allow end user to pay in DOT?

We can only pay for delivery fees in different assets in intermediate hops

Does your comment above means it's not possible?

@franciscoaguirre
Copy link
Contributor Author

@yrong Given how the bridge works, BridgeHub doesn't charge the delivery fee, AssetHub does. This means it wouldn't work because of the limitation unfortunately

@yrong
Copy link
Contributor

yrong commented Jul 19, 2024

Given how the bridge works, BridgeHub doesn't charge the delivery fee, AssetHub does. This means it wouldn't work because of the limitation unfortunately

No worry. In our new design won't need a static delivery fee config anymore, as Adrian suggested we will use the low level pallet-xcm::execute for a custom xcm(e.g. including the ExchangeAsset for the internal swap).

@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
Job name: test-linux-stable 1/3
Logs: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6765227

@franciscoaguirre
Copy link
Contributor Author

Closing in favor of #5130 and #5131

@franciscoaguirre franciscoaguirre deleted the different-assets-delivery-fees branch July 26, 2024 09:05
TarekkMA pushed a commit to moonbeam-foundation/polkadot-sdk that referenced this pull request Aug 2, 2024
…set hub (paritytech#4870)

- Send bridged WNDs: Penpal Rococo -> AH Rococo -> AH Westend
- Send bridged ROCs: Penpal Westend -> AH Westend -> AH Rococo

The tests send both ROCs and WNDs, for each direction the native asset
is only used to pay for the transport fees on the local AssetHub, and
are not sent over the bridge.

Including the native asset won't be necessary anymore once we get paritytech#4375.

---------

Signed-off-by: Adrian Catangiu <[email protected]>
Co-authored-by: command-bot <>
github-merge-queue bot pushed a commit that referenced this pull request Aug 2, 2024
Added a new adapter to xcm-builder, the `SingleAssetExchangeAdapter`.
This adapter makes it easy to use `pallet-asset-conversion` for
configuring the `AssetExchanger` XCM config item.

I also took the liberty of adding a new function to the `AssetExchange`
trait, with the following signature:

```rust
fn quote_exchange_price(give: &Assets, want: &Assets, maximal: bool) -> Option<Assets>;
```

The signature is meant to be fairly symmetric to that of
`exchange_asset`.
The way they interact can be seen in the doc comment for it in the
`AssetExchange` trait.

This is a breaking change but is needed for
#5131.
Another idea is to create a new trait for this but that would require
setting it in the XCM config which is also breaking.

Old PR: #4375.

---------

Co-authored-by: Adrian Catangiu <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Sep 2, 2024
# 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.
x3c41a added a commit that referenced this pull request Sep 4, 2024
# 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.
sfffaaa pushed a commit to peaqnetwork/polkadot-sdk that referenced this pull request Dec 27, 2024
…set hub (paritytech#4870)

- Send bridged WNDs: Penpal Rococo -> AH Rococo -> AH Westend
- Send bridged ROCs: Penpal Westend -> AH Westend -> AH Rococo

The tests send both ROCs and WNDs, for each direction the native asset
is only used to pay for the transport fees on the local AssetHub, and
are not sent over the bridge.

Including the native asset won't be necessary anymore once we get paritytech#4375.

---------

Signed-off-by: Adrian Catangiu <[email protected]>
Co-authored-by: command-bot <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T6-XCM This PR/Issue is related to XCM.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants