current, we have multi assets support, and use fee_item asset as reserve
|
let (transfer_kind, dest, reserve, recipient) = Self::transfer_kind(&fee, &dest)?; |
i.e. if currencies=vec![(CurrencyId::R, 100), (CurrencyId::B, 450)], and fee_item=0, reserve=Parent, because fee asset is R, then xcm sent to Relaychain likes:
origin: MultiLocation { parents: 0, interior: X1(Parachain(1)) },
message: Xcm([
WithdrawAsset(MultiAssets([
MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: Here }), fun: Fungible(100) },
MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(Parachain(2), GeneralKey([66])) }), fun: Fungible(450) }])), // 🔥
ClearOrigin,
BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: Here }), fun: Fungible(50) }, weight_limit: Limited(40) },
DepositReserveAsset {
assets: Wild(All), max_assets: 2,
dest: MultiLocation { parents: 0, interior: X1(Parachain(2)) },
xcm: Xcm([
BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), fun: Fungible(50) }, weight_limit: Limited(40) },
DepositAsset { assets: Wild(All), max_assets: 2, beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: Any, id: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }) } }]) }
]), weight_limit: 18446744073709551615, weight_credit: 0
this will error when execute second WithdrawAsset because relaychain doesn't have (0, Parachain(2), GeneralKey(B)) asset.
if currencies=vec![(CurrencyId::R, 100), (CurrencyId::B, 450)], and fee_item=1, reserve=(1,Parachain(2)), because fee asset is B, then xcm send to Sibling Parachain(2) likes:
origin: MultiLocation { parents: 0, interior: X1(Parachain(1)) },
message: Xcm([
WithdrawAsset(MultiAssets([
MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey([66])) }), fun: Fungible(450) }, // sibling_a_account should have enougn B token
MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), fun: Fungible(100) }])), // sibling_a_account also should have enough R token
ClearOrigin,
BuyExecution {
fees: MultiAsset {
id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey([66])) }), fun: Fungible(450) // ⬅️
}, weight_limit: Limited(40) },
DepositAsset {
assets: Wild(All), max_assets: 2,
beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: Any, id: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }) }
}
]), weight_limit: 6148914691236517205, weight_credit: 0
this can sucess if we open gate here(if not, there'll be DistinctReserveForAssetAndFee error):
|
ensure!( |
|
fee.reserve() == asset.reserve(), |
|
Error::<T>::DistinctReserveForAssetAndFee |
|
); |
and the xcm above use (0, GeneralKey(B)) as fee, although this is what the fee_item exactly wanted.
but in some cases we want use sibling parachain as reserve chain, and also use relaychain asset as fee.
i.e. transfer RMRK from Karura to Statemine, we use KSM as fee. the xcm on recipient parachain should be like:
message: Xcm([
WithdrawAsset(MultiAssets([
MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey([66])) }), fun: Fungible(450) }, // sibling_a_account should have enougn B token
MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), fun: Fungible(100) }])), // sibling_a_account also should have enough R token
ClearOrigin,
BuyExecution {
fees: MultiAsset {
id: Concrete(MultiLocation { parents: 1, interior: Here }), fun: Fungible(50) // ⬅️
}, weight_limit: Limited(40) },
DepositAsset {
assets: Wild(All), max_assets: 2,
beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: Any, id: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }) }
}
])
PS: in the case of transfer RMRK from Karura to Statemine, if we transfer only RMRK, in the Statemine side, as trader not matched, xcm executed in Statemine will failed, and throw TooExpsensive error. so we must use KSM as fee, because Statemine only support KSM as fee for now.
https://github.com/paritytech/cumulus/blob/86f76c5619c64d1300315612695ad4b4fcd0f562/polkadot-parachains/statemine/src/lib.rs#L557
current, we have multi assets support, and use
fee_itemasset as reserveopen-runtime-module-library/xtokens/src/lib.rs
Line 590 in 4a66b29
i.e. if
currencies=vec![(CurrencyId::R, 100), (CurrencyId::B, 450)], and fee_item=0, reserve=Parent, because fee asset is R, then xcm sent to Relaychain likes:this will error when execute second WithdrawAsset because relaychain doesn't have
(0, Parachain(2), GeneralKey(B))asset.if currencies=
vec![(CurrencyId::R, 100), (CurrencyId::B, 450)], and fee_item=1, reserve=(1,Parachain(2)), because fee asset is B, then xcm send to Sibling Parachain(2) likes:this can sucess if we open gate here(if not, there'll be
DistinctReserveForAssetAndFeeerror):open-runtime-module-library/xtokens/src/lib.rs
Lines 584 to 587 in 4a66b29
and the xcm above use
(0, GeneralKey(B))as fee, although this is what the fee_item exactly wanted.but in some cases we want use sibling parachain as reserve chain, and also use relaychain asset as fee.
i.e. transfer RMRK from Karura to Statemine, we use KSM as fee. the xcm on recipient parachain should be like:
PS: in the case of transfer RMRK from Karura to Statemine, if we transfer only RMRK, in the Statemine side, as trader not matched, xcm executed in Statemine will failed, and throw TooExpsensive error. so we must use KSM as fee, because Statemine only support KSM as fee for now.
https://github.com/paritytech/cumulus/blob/86f76c5619c64d1300315612695ad4b4fcd0f562/polkadot-parachains/statemine/src/lib.rs#L557