-
Notifications
You must be signed in to change notification settings - Fork 732
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
pallet-xcm: add new extrinsic for asset transfers using explicit XCM transfer types #3695
pallet-xcm: add new extrinsic for asset transfers using explicit XCM transfer types #3695
Conversation
Add `transfer_assets_using_reserve()` for transferring assets from local chain to destination chain using an explicit reserve location (typically local Asset Hub). By default, an asset's reserve is its origin chain. But sometimes we may want to explicitly use another chain as reserve (as long as allowed by runtime `IsReserve` filter). This is very helpful for transferring assets with multiple configured reserves (such as Asset Hub ForeignAssets), when the transfer strictly depends on the used reserve. E.g. For transferring Foreign Assets over a bridge, Asset Hub must be used as the reserve location.
…ge using local asset hub as reserve
Just to double check. This two reserves issue happens because a token is teleported between two locations, right? It's not because a token is reserved transferred somewhere and then reserved transferred again from that main reserve into some sort of secondary reserve. |
It is the former. Teleporting assets between chains requires the same level of trust as allowing those chains to act as reserves for said asset. With teleports, it is conceptually the same asset on both chains, unlike reserve-based transfers where the real asset stays put within its borders while outside the borders (i.e. destination chain) a derivative asset is used to represent it. This PR adds utility function for reserve-based transfers (not teleports) of a given asset, but using one of the assets secondary reserve locations (any other chain where it can be teleported to/from). I added some example scenarios to the PR description for more clarity. |
…sfer-using-explicit-reserve
…sfer-using-explicit-reserve
1e971b8
Hey @acatangiu, one scenario that is currently not covered by the Moonbeam only has the relay chain as DOT reserve, and we can't have AH because then we would have 2 reserve chains for 1 asset, which could create many new problems with SA's balances. So, ideally, we could have a way in which we do something like:
The main problem with the approach above is the Mainly because we have new assets being created in AH, and they are not sufficient assets, meaning that to send them back, users need to pay with either USDC/USDT. XTokens allowed for such an approach in which 1 XCM is sent to the Relay Chain to send DOT to Parachains SA account in AH while another XCM was sent to AH to withdraw DOT to buy execution to transfer the token. However, this approach relied on the first XCM message executing successfully, so teams would usually have a DOT buffer in AH SA. |
That is correct, and I don't believe
This is the same problem HydraDX and other parachains too are probably facing. The problem is not limited to DOT. The problem ultimately comes from having both reserve-based transfers as well as teleports allowed in our ecosystem. Once you allow a teleport between two chains, then both of those should be able to act as reserves, otherwise the teleport doesn't make sense. E.g.: parachain assets registered as ForeignAssets on AH and teleported there. The "owner" parachain will want to allow AH to act as a reserve for them, and expose their asset to all the other chains/bridges/CEXs/etc that are already integrated with AH.
Exactly! Ultimately, parachains need "some buffer" in AH SA anyway. I am hoping that with some smarter way of keeping SAs balanced, this problem will go away and workarounds like sending multiple XCMs and waiting for them to happen in a certain sequence will not be needed anymore. The silver lining here is that the problem is very generic and asset/chain agnostic, and we can decide on some mechanism to auto-balance these SAs, that every chain can use. |
The main issue is SA management. It would then require users to go through undesirable routes to get their assets where they want to (for example, SA in Polkadot has 100 DOT, and in AH, it has 20 DOT, and a user wants to get 40 DOT in Polkadot). This creates bad UX. What about creating a call in which you can route XCM and assets through another chain? I guess the application of this is too specific. And could we do something similar to what xTokens is doing, but just from a UI point of view? |
In practice, liquidity should be much larger, and with some periodic automated balancing mechanism this should never happen (unless the user is some whale moving a lot of liquidity at once). A somewhat smarter rebalancer: component be deployed on target chains that tracks SA balance and requests liquidity from owner chain if it falls below a threshold, thus triggering rebalancing on-demand.
Could be done, but don't know of a way to do it generically, chain/asset agnostic - and without a generic mechanism I strongly recommend against it as it will not scale. We will fragment the ecosystem even further with tokens and chains having custom workarounds and special gotchas. There is also an efficiency disadvantage (not really important, but worth mentioning): at the end of the day this is also an automated SA rebalancing mechanism, it just happens on every transfer regardless of need (with the user paying for two extra XCMs each time: to 1. signal the main reserve to 2. send liquidity to secondary reserve). |
This pull request has been mentioned on Polkadot Forum. There might be relevant details there: https://forum.polkadot.network/t/managing-sas-on-multiple-reserve-chains-for-same-asset/7538/1 |
I created a forum topic to get more visibility and ideas on the problem: https://forum.polkadot.network/t/managing-sas-on-multiple-reserve-chains-for-same-asset/7538 |
I raised this issue a year ago paritytech/cumulus#2398 |
Apparently it takes more than raising an issue to solve an ecosystem-wide problem :) Please join the discussion on the forum, help me engage all the parachains, and collectively decide on a solution. I can commit to implement whatever we, the ecosystem, decide is necessary, if help is required from Parity. |
…estination (#4260) Change `transfer_assets_using_type()` to not assume `DepositAssets` as the intended use of the assets on the destination. Instead provides the caller with the ability to specify custom XCM that be executed on `dest` chain as the last step of the transfer, thus allowing custom usecases for the transferred assets. E.g. some are used/swapped/etc there, while some are sent further to yet another chain. Note: this is a follow-up on #3695, bringing in an API change for `transfer_assets_using_type()`. This is ok as the previous version has not been yet released. Thus, its first release will include the new API proposed by this PR. This allows usecases such as: https://forum.polkadot.network/t/managing-sas-on-multiple-reserve-chains-for-same-asset/7538/4 BTW: all this pallet-xcm asset transfers code will be massively reduced once we have polkadot-fellows/xcm-format#54 --------- Signed-off-by: Adrian Catangiu <[email protected]>
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 |
…h#3695) Add `transfer_assets_using_type_and_then()` for transferring assets from local chain to destination chain using explicit XCM transfer types: - `TransferType::LocalReserve`: transfer assets to sovereign account of destination chain and forward a notification XCM to `dest` to mint and deposit reserve-based assets to `beneficiary`. - `TransferType::DestinationReserve`: burn local assets and forward a notification to `dest` chain to withdraw the reserve assets from this chain's sovereign account and deposit them to `beneficiary`. - `TransferType::RemoteReserve(reserve)`: burn local assets, forward XCM to `reserve` chain to move reserves from this chain's SA to `dest` chain's SA, and forward another XCM to `dest` to mint and deposit reserve-based assets to `beneficiary`. Typically the remote `reserve` is Asset Hub. - `TransferType::Teleport`: burn local assets and forward XCM to `dest` chain to mint/teleport assets and deposit them to `beneficiary`. By default, an asset's reserve is its origin chain. But sometimes we may want to explicitly use another chain as reserve (as long as allowed by runtime `IsReserve` filter). This is very helpful for transferring assets with multiple configured reserves (such as Asset Hub ForeignAssets), when the transfer strictly depends on the used reserve. E.g. For transferring Foreign Assets over a bridge, Asset Hub must be used as the reserve location. ERC20-tokenX is registered on AssetHub as a ForeignAsset by the Polkadot<>Ethereum bridge (Snowbridge). Its asset_id is something like `(parents:2, (GlobalConsensus(Ethereum), Address(tokenX_contract)))`. Its _original_ reserve is Ethereum (only we can't use Ethereum as a reserve in local transfers); but, since tokenX is also registered on AssetHub as a ForeignAsset, we can use AssetHub as a reserve. With this PR we can transfer tokenX from ParaA to ParaB while using AssetHub as a reserve. AssetA created on ParaA but also registered as foreign asset on Asset Hub. Can use AssetHub as a reserve. And all of the above can be done while still controlling transfer type for `fees` so mixing assets in same transfer is supported. Provides the caller with the ability to specify custom XCM that be executed on `dest` chain as the last step of the transfer, thus allowing custom usecases for the transferred assets. E.g. some are used/swapped/etc there, while some are sent further to yet another chain. This allows usecases such as: https://forum.polkadot.network/t/managing-sas-on-multiple-reserve-chains-for-same-asset/7538/4 Signed-off-by: Adrian Catangiu <[email protected]>
…h#3695) Add `transfer_assets_using_type_and_then()` for transferring assets from local chain to destination chain using explicit XCM transfer types: - `TransferType::LocalReserve`: transfer assets to sovereign account of destination chain and forward a notification XCM to `dest` to mint and deposit reserve-based assets to `beneficiary`. - `TransferType::DestinationReserve`: burn local assets and forward a notification to `dest` chain to withdraw the reserve assets from this chain's sovereign account and deposit them to `beneficiary`. - `TransferType::RemoteReserve(reserve)`: burn local assets, forward XCM to `reserve` chain to move reserves from this chain's SA to `dest` chain's SA, and forward another XCM to `dest` to mint and deposit reserve-based assets to `beneficiary`. Typically the remote `reserve` is Asset Hub. - `TransferType::Teleport`: burn local assets and forward XCM to `dest` chain to mint/teleport assets and deposit them to `beneficiary`. By default, an asset's reserve is its origin chain. But sometimes we may want to explicitly use another chain as reserve (as long as allowed by runtime `IsReserve` filter). This is very helpful for transferring assets with multiple configured reserves (such as Asset Hub ForeignAssets), when the transfer strictly depends on the used reserve. E.g. For transferring Foreign Assets over a bridge, Asset Hub must be used as the reserve location. ERC20-tokenX is registered on AssetHub as a ForeignAsset by the Polkadot<>Ethereum bridge (Snowbridge). Its asset_id is something like `(parents:2, (GlobalConsensus(Ethereum), Address(tokenX_contract)))`. Its _original_ reserve is Ethereum (only we can't use Ethereum as a reserve in local transfers); but, since tokenX is also registered on AssetHub as a ForeignAsset, we can use AssetHub as a reserve. With this PR we can transfer tokenX from ParaA to ParaB while using AssetHub as a reserve. AssetA created on ParaA but also registered as foreign asset on Asset Hub. Can use AssetHub as a reserve. And all of the above can be done while still controlling transfer type for `fees` so mixing assets in same transfer is supported. Provides the caller with the ability to specify custom XCM that be executed on `dest` chain as the last step of the transfer, thus allowing custom usecases for the transferred assets. E.g. some are used/swapped/etc there, while some are sent further to yet another chain. This allows usecases such as: https://forum.polkadot.network/t/managing-sas-on-multiple-reserve-chains-for-same-asset/7538/4 Signed-off-by: Adrian Catangiu <[email protected]>
…4462) Add `transfer_assets_using_type_and_then()` for transferring assets from local chain to destination chain using explicit XCM transfer types: - `TransferType::LocalReserve`: transfer assets to sovereign account of destination chain and forward a notification XCM to `dest` to mint and deposit reserve-based assets to `beneficiary`. - `TransferType::DestinationReserve`: burn local assets and forward a notification to `dest` chain to withdraw the reserve assets from this chain's sovereign account and deposit them to `beneficiary`. - `TransferType::RemoteReserve(reserve)`: burn local assets, forward XCM to `reserve` chain to move reserves from this chain's SA to `dest` chain's SA, and forward another XCM to `dest` to mint and deposit reserve-based assets to `beneficiary`. Typically the remote `reserve` is Asset Hub. - `TransferType::Teleport`: burn local assets and forward XCM to `dest` chain to mint/teleport assets and deposit them to `beneficiary`. By default, an asset's reserve is its origin chain. But sometimes we may want to explicitly use another chain as reserve (as long as allowed by runtime `IsReserve` filter). This is very helpful for transferring assets with multiple configured reserves (such as Asset Hub ForeignAssets), when the transfer strictly depends on the used reserve. E.g. For transferring Foreign Assets over a bridge, Asset Hub must be used as the reserve location. ERC20-tokenX is registered on AssetHub as a ForeignAsset by the Polkadot<>Ethereum bridge (Snowbridge). Its asset_id is something like `(parents:2, (GlobalConsensus(Ethereum), Address(tokenX_contract)))`. Its _original_ reserve is Ethereum (only we can't use Ethereum as a reserve in local transfers); but, since tokenX is also registered on AssetHub as a ForeignAsset, we can use AssetHub as a reserve. With this PR we can transfer tokenX from ParaA to ParaB while using AssetHub as a reserve. AssetA created on ParaA but also registered as foreign asset on Asset Hub. Can use AssetHub as a reserve. And all of the above can be done while still controlling transfer type for `fees` so mixing assets in same transfer is supported. Provides the caller with the ability to specify custom XCM that be executed on `dest` chain as the last step of the transfer, thus allowing custom usecases for the transferred assets. E.g. some are used/swapped/etc there, while some are sent further to yet another chain. This allows usecases such as: https://forum.polkadot.network/t/managing-sas-on-multiple-reserve-chains-for-same-asset/7538/4 Signed-off-by: Adrian Catangiu <[email protected]>
This pull request has been mentioned on Polkadot Forum. There might be relevant details there: https://forum.polkadot.network/t/rfc-xcm-asset-transfer-program-builder/8528/1 |
Description
Add
transfer_assets_using()
for transferring assets from local chain to destination chain using explicit XCM transfer types such as:TransferType::LocalReserve
: transfer assets to sovereign account of destination chain and forward a notification XCM todest
to mint and deposit reserve-based assets tobeneficiary
.TransferType::DestinationReserve
: burn local assets and forward a notification todest
chain to withdraw the reserve assets from this chain's sovereign account and deposit them tobeneficiary
.TransferType::RemoteReserve(reserve)
: burn local assets, forward XCM toreserve
chain to move reserves from this chain's SA todest
chain's SA, and forward another XCM todest
to mint and deposit reserve-based assets tobeneficiary
. Typically the remotereserve
is Asset Hub.TransferType::Teleport
: burn local assets and forward XCM todest
chain to mint/teleport assets and deposit them tobeneficiary
.By default, an asset's reserve is its origin chain. But sometimes we may want to explicitly use another chain as reserve (as long as allowed by runtime
IsReserve
filter).This is very helpful for transferring assets with multiple configured reserves (such as Asset Hub ForeignAssets), when the transfer strictly depends on the used reserve.
E.g. For transferring Foreign Assets over a bridge, Asset Hub must be used as the reserve location.
Example usage scenarios
Transfer bridged ethereum ERC20-tokenX between ecosystem parachains.
ERC20-tokenX is registered on AssetHub as a ForeignAsset by the Polkadot<>Ethereum bridge (Snowbridge). Its asset_id is something like
(parents:2, (GlobalConsensus(Ethereum), Address(tokenX_contract)))
. Its original reserve is Ethereum (only we can't use Ethereum as a reserve in local transfers); but, since tokenX is also registered on AssetHub as a ForeignAsset, we can use AssetHub as a reserve.With this PR we can transfer tokenX from ParaA to ParaB while using AssetHub as a reserve.
Transfer AssetHub ForeignAssets between parachains
AssetA created on ParaA but also registered as foreign asset on Asset Hub. Can use AssetHub as a reserve.
And all of the above can be done while still controlling transfer type for
fees
so mixing assets in same transfer is supported.Tests
Added integration tests for showcasing:
Later Edit: NOTE:
This PR has a followup PR that slightly changes the name and API: #4260