Skip to content

support using KSM as fee(cases: transfer back asset to Statemine) #698

@zqhxuyuan

Description

@zqhxuyuan

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions