-
Notifications
You must be signed in to change notification settings - Fork 378
support asset transfer from/to sibling chain #806
Conversation
Thanks for your PR! Unfortunately, this is not the right place to add a new item to configure XCM. I believe the right place would be to add it in Polkadot's repository, under xcm/xcm-builder. Aside from that, I'm not quite sure what this PR is trying to solve. Can you please elaborate the background of your problem and why your solution would solve it? I don't understand anything about this need for a |
@KiChjang The requirement is simple, we would like to transfer asset issued in statemine (e.g:usdt) to our chain and then transfer it back. With this pr and some adaptor logic in our chain I can achive that. The Btw, with and wrap xcm as following to transfer asset back |
So if I'm hearing you correctly, you're saying that the If so, then there may need to be a bit more thought into how the MultiLocation of a reserve chain asset should be represented. Right now you have |
Exactly
seems you want to add
Agree |
@yrong If for whatever reason, Moreover, it's very not obvious what a |
When I set up the asset XCM integration I figured that we need a unique asset identifier within Statemint, so I used the @yrong My question to you is: What keeps you from just sending a Edit: Context is that the |
@apopiak some clarification here bifrost-io/bifrost#420 (comment) |
Alright, seems like the reanchoring logic in the executor means we should merge (something like) this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the contribution from my side as well, btw. 🙏
Here are the adjustments I'd like to see:
-
Please move this into parachains-common. (Statemint and Statemine will have to use the same.)
-
This also should have a few tests:
- matching the local prefix
- matching the remote prefix
- the failure cases
-
Please add docs
-
Also you skipped the prefix checking from the original here:
https://github.com/paritytech/polkadot/blob/55872676fae63399eb111a60ba27cb735cbaead6/xcm/xcm-builder/src/fungibles_adapter.rs#L41-L46
You should be able to usematch_and_split
instead, though: https://github.com/paritytech/polkadot/blob/cc24fb87b702db6510d08c689e442b6be384d798/xcm/src/v1/multilocation.rs#L249 -
We should probably also add (something like) this to the xcm-builder as @KiChjang suggests. (Would be great if you could open that PR as well to upstream this.)
80f010b
to
82eae51
Compare
@apopiak some refact per your request list. For the xcm-builder upstream refact I would like to do later and we're looking forward this pr merged into |
Added a basic description. Feel free to expand it. |
I'd like someone else to also have a look before merging this. |
Why is this against 0.9.13? Surely it should be going into master? |
@@ -113,6 +114,44 @@ impl<T: Get<MultiLocation>> FilterAssetLocation for AssetsFrom<T> { | |||
} | |||
} | |||
|
|||
/// Converter struct with two main usage scenarios: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation needs improvement. This is incomprehensible at present.
/// - with `reverse_ref` to convert a numeric asset ID (must be `TryFrom/TryInto<u128>`) into a `GeneralIndex` junction | ||
/// 2. Transfer asset back from other para-chain to local | ||
/// - with `convert_ref` to convert multilocation struct `(1,X2(ParaChain(para_id),GeneralIndex(general_index))` to a numeric asset ID | ||
pub struct AsPrefixedGeneralIndexFromLocalOrRemote< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong place for this - it should be in xcm-builder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remain yet to be convinced that this is needed or even a good idea.
@@ -481,7 +483,7 @@ pub type FungiblesTransactor = FungiblesAdapter< | |||
ConvertedConcreteAssetId< | |||
AssetId, | |||
Balance, | |||
AsPrefixedGeneralIndex<Local, AssetId, JustTry>, | |||
AsPrefixedGeneralIndexFromLocalOrRemote<Local, Remote, AssetId, JustTry>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No alterations to Statemint's XCM right now. Stuff like this is EXTREMELY dangerous to change and must a) be completely understood by me; and b) be in place in Kusama for some time prior.
&remote_asset_location, | ||
) | ||
.unwrap_or(u32::default()); | ||
assert_eq!(asset_id, 42); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously I have tried to summarize your problem as the following:
if I'm hearing you correctly, you're saying that the
GeneralIndex
is used to specify which one of the many assets in statemine that you want to transfer to the destination chain via reserve transfers? In other words, your flow is exactly the same asInititateReserveWithdraw
, but with the ability to specify an asset that is not KSM, correct?
But this unit test seems to indicate that you're doing something more -- you're trying to represent a remote asset containing a GeneralIndex
locally as a GeneralIndex
as well, e.g. a ../Parachain(1000)/GeneralIndex(42)
gets converted and represented as ./GeneralIndex(42)
. Is this what you are trying to do?
If so, then this is absolutely not the right thing to do. Assets should always have ONE canonical MultiLocation
to represent it, and as such, an asset located at ../Parachain(1000)/GeneralIndex(42)
MUST be interpreted as a different asset from an asset located at ./GeneralIndex(42)
. If the intention is to mint a derivative asset of the one located at ../Parachain(1000)/GeneralIndex(42)
, then it is the AssetTransactor
logic of your chain that needs to change, and not the XCM configuration, and definitely not the MultiLocation
of the reserve asset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pondering a bit more into this, I think what you are trying to solve is the reanchoring issue, in which case, this is an operation that should have been done by the XCM sender, and not the recipient, i.e. when sending an asset containing a AssetId
of ../Parachain(1000)/GeneralIndex(42)
to ../Parachain(1000)
, the XCM executor should have reanchored this AssetId
to ./GeneralIndex(42)
on the sender's chain. Did this not happen when you're testing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KiChjang @apopiak I do not think we can achive that without hack in cumulus, let us put more details here:
- transfer asset from statemine to our chain with
TransferReserveAsset
since Local
defined here original asset sent from statemine should be represented as ./GeneralIndex(42)
and after the reanchor logic you mentioned above asset will be converted to ../Parachain(1000)/GeneralIndex(42)
and in our chain we should add some adaptor logic to handle this
- transfer asset back from our chain to statemine with
InitiateReserveWithdraw
I agree with
Assets should always have ONE canonical MultiLocation to represent
so I think from the perspective of our chain statemine asset should always reprensented as ../Parachain(1000)/GeneralIndex(42)
but after the reanchor logic here we can not convert it back to ./GeneralIndex(42)
anyway so statemine will not understand without hack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of observations:
- What you interact on your local chain should always be
./GeneralIndex(42)
and not../Parachain(1000)/GeneralIndex(42)
, i.e. you interact with the derivative asset and never the reserve asset. Therefore when you do a reserve asset transfer, you will first execute aWithdrawAsset(GeneralIndex(42))
and you will get someGeneralIndex(42)
stored in your chain's holding register. - The next step in the process is
InitiateReserveWithdraw
, which takes the derivative asset in the holding register and sends it back to Statemine. Before that happens though, what should happen on your location chain is that it should burn and convert the derivative asset (i.e.GeneralIndex(42)
) to the reserve asset (i.e.../Parachain(1000)/GeneralIndex(42)
). - The receiver should never be responsible for converting between derivative asset IDs and reserve asset IDs. Doing so would mean that all derivative assets should "register" themselves on the reserve chain, which is absolutely not the direction we want to head towards.
I've looked into the code for the XCM executor now and it does seem like there's no way to burn and convert a derivative asset back to its reserve asset during the execution of InitiateReserveWithdraw
, and I think that is the crux of the issue here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you interact on your local chain should always be
./GeneralIndex(42)
and not../Parachain(1000)/GeneralIndex(42)
i.e. you interact with the derivative asset and never the reserve asset.
No, I do think we should use reserve asset rather than derivative asset here. except for statemine we need to talk to other parachains like Acala and as you mentioned before only the GeneralIndex is too abstract. How to differ the same reprensentation ./GeneralIndex(42)
in acala and statemine but with different meaning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That could easily be solved if you prepend an ExchangeAsset instruction before you execute InitiateReserveWithdraw, and in ExchangeAsset, your custom XCM executor will convert your derivative asset back to the reserve asset.
@KiChjang I really do not know this primitive and will try, thanks for your suggestion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KiChjang
seems ExchangeAsset you mentioned not implemented yet, is it in some feature branch? And I would like to know if there is any other solution or implementation other parachain team already solved as you mentioned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is purposefully not implemented; as I said, we do not provide any opinionated approaches as to how a chain should manage their bookkeeping of their reserve assets. Any chain that wants to execute ExchangeAsset
will have to provide their own implementation. I'm not as familiar as to how other parachain teams in the ecosystem solves this problem, however, but I would think that any parachain that has onboarded to Kusama and has dealt with reserve assets would have come up with a solution dealing with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood. we can implement this to do some asset convert logic from sender side. But I would assume at last we still need InitiateReserveWithdraw
primitive to send asset back to statemine,right? From what I've tested after the renchor logic in InitiateReserveWithdraw here asset will still be converted to ../Parachain(1000)/GeneralIndex(42)
no matter what it previously is. And this format can not be recognized by statemine without hack which only knows ./GeneralIndex(42)
.Correct me if I'm wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, the reanchoring logic is what we're in the middle of investigating as well. However, in the context of this PR, your changes will unfortunately not be the correct fix. We will provide an update in #827 as soon as we have any more details to share.
As I mention here, the primitives in the XCM builder expect that the derivative asset (on your chain, which represented ownership of the reserve assets on Statemint) should generally be represented in XCM as the same conceptual location as the reserve asset. So, generally this will mean it is Reanchoring should ensure that the former If you believe there is an issuer with the reanchoring, then I'll just need a failing test to demonstrate this. So far I have not seen one. You will likely want to have an instance of the None of this should require alterations to Statemint. |
Ok, I believe I figured it out. There is indeed a subtle issue with the reanchoring logic, specifically it gives a correct non-canonical destination value. Basically, it sends a I'll put in something to simplify it and stuff should work. |
paritytech/polkadot#4470 should fix things |
@gavofyork @KiChjang seems this fix will break current behavior how we bifrost(2001) communicate with acala(2000) and other parachains, breaking test cases as following:
maybe @xlc can add some comments here also |
Yes. This test is very much incorrect. The From parachain #2001's point of view (where we begin):
From parachain #2000's point of view (where we reanchor to): So the reanchoring should take the ancestry of the location where we begin (1), the destination (relative to where we begin) (2) and the asset (also relatively to where we begin) (4). From these three pieces of information, it is able to tell us how the destination would refer to the same asset (8). |
Closing since this is definitely not the right fix. Please move any further discussion to paritytech/polkadot#4470 or #833. |
This PR adds the
AsPrefixedGeneralIndexFromLocalOrRemote
conversion type to allow accepting assets that were moved to another chain via reserve based transfers back onto Statemint (and friends).