1

I already read this post XCM cross-chain transfer error FailedToTransactAsset("InsufficientBalance")? , but nothing helped.

I get the following XCM logs (originates from Parachain 2001):

2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::origin_conversion: [Parachain] SovereignSignedViaLocation origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, kind: Superuser    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::origin_conversion: [Parachain] RelayChainAsNative origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, kind: Superuser    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::origin_conversion: [Parachain] SiblingParachainAsNative origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, kind: Superuser    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::origin_conversion: [Parachain] SignedAccountId32AsNative origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, kind: Superuser    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::convert_origin: [Parachain] could not convert: origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, kind: Superuser    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::weight: [Parachain] FixedWeightBounds message: Xcm([DescendOrigin(X1(AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] })), WithdrawAsset(MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000000) }])), BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000000) }, weight_limit: Unlimited }, LockAsset { asset: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000) }, unlocker: MultiLocation { parents: 1, interior: X2(Parachain(2000), AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] }) } }])    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, message: Xcm([DescendOrigin(X1(AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] })), WithdrawAsset(MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000000) }])), BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000000) }, weight_limit: Unlimited }, LockAsset { asset: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000) }, unlocker: MultiLocation { parents: 1, interior: X2(Parachain(2000), AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] }) } }]), weight_credit: <wasm:stripped>    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::barriers: [Parachain] TakeWeightCredit origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, instructions: [DescendOrigin(X1(AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] })), WithdrawAsset(MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000000) }])), BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000000) }, weight_limit: Unlimited }, LockAsset { asset: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000) }, unlocker: MultiLocation { parents: 1, interior: X2(Parachain(2000), AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] }) } }], max_weight: <wasm:stripped>, properties: Properties { weight_credit: <wasm:stripped>, message_id: None }    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::process: [Parachain] origin: Some(MultiLocation { parents: 1, interior: X1(Parachain(2000)) }), total_surplus/refunded: <wasm:stripped>/<wasm:stripped>, error_handler_weight: <wasm:stripped>    
2023-11-02 05:35:24.357 TRACE tokio-runtime-worker xcm::process_instruction: [Parachain] === DescendOrigin(X1(AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] }))    
2023-11-02 05:35:24.358 TRACE tokio-runtime-worker xcm::process_instruction: [Parachain] === WithdrawAsset(MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(GeneralKey { length: 2, data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }) }), fun: Fungible(10000000000000) }]))      
2023-11-02 05:35:24.359 TRACE tokio-runtime-worker xcm::execute: [Parachain] !!! ERROR: FailedToTransactAsset("InsufficientBalance")    
2023-11-02 05:35:24.359 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] result: Err(ExecutorError { index: 1, xcm_error: FailedToTransactAsset("InsufficientBalance"), weight: <wasm:stripped> })    
2023-11-02 05:35:24.359 TRACE tokio-runtime-worker xcm::weight: [Parachain] FixedRateOfFungible::refund_weight weight: <wasm:stripped>, context: XcmContext { origin: Some(MultiLocation { parents: 1, interior: X2(Parachain(2000), AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] }) }), message_id: [143, 158, 177, 103, 122, 233, 162, 35, 234, 11, 70, 43, 39, 79, 250, 6, 104, 7, 82, 112, 172, 195, 84, 137, 36, 29, 174, 18, 82, 246, 144, 80], topic: None }    
2023-11-02 05:35:24.359 TRACE tokio-runtime-worker xcm::weight: [Parachain] FixedRateOfFungible::refund_weight weight: <wasm:stripped>, context: XcmContext { origin: Some(MultiLocation { parents: 1, interior: X2(Parachain(2000), AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] }) }), message_id: [143, 158, 177, 103, 122, 233, 162, 35, 234, 11, 70, 43, 39, 79, 250, 6, 104, 7, 82, 112, 172, 195, 84, 137, 36, 29, 174, 18, 82, 246, 144, 80], topic: None }    
2023-11-02 05:35:24.359 TRACE tokio-runtime-worker xcm::weight: [Parachain] FixedRateOfFungible::refund_weight weight: <wasm:stripped>, context: XcmContext { origin: Some(MultiLocation { parents: 1, interior: X2(Parachain(2000), AccountId32 { network: None, id: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] }) }), message_id: [143, 158, 177, 103, 122, 233, 162, 35, 234, 11, 70, 43, 39, 79, 250, 6, 104, 7, 82, 112, 172, 195, 84, 137, 36, 29, 174, 18, 82, 246, 144, 80], topic: None }    
2023-11-02 05:35:24.359 TRACE tokio-runtime-worker xcm::weight: [Parachain] AssetRegistryTrader::refund_weight weight: <wasm:stripped>    
2023-11-02 05:35:24.359 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] Execution errored at 1: FailedToTransactAsset("InsufficientBalance") (original_origin: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }) 

My setup is the following:

  • local rococo relaychain
  • parachain 2000
  • parachain 2001

I send the following encoded call data XCM message from parachain 2000 to parachain 2001 as the well-known Alice account as a normal signed origin:

0x490003010100451f030c000400000106020001000000000000000000000000000000000000000000000000000000000000000b00a0724e18091300000106020001000000000000000000000000000000000000000000000000000000000000000b00a0724e1809002700000106020001000000000000000000000000000000000000000000000000000000000000000700e40b5402010200411f0100d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d

enter image description here

I funded the sovereign account of para id 2000 and 2001 and the sibling account of parachain id 2000 and 2001 on the rococo-local relaychain.

I am currently trying out the LockAsset functionality and what I noticed is that the well known Alice account is different on the receiving chain after sending it through XCM. It is: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125], which translates to 0x003593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da200 (using substrate utilities https://www.shawntabrizi.com/substrate-js-utilities/ represented as account id 5C4ymnPah145YenQ6EAUCrt6ZssKz15hVuLMGNVxNKhDtrP2 on para 2001). Although the Alice account has the account id 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, which should be 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d in hex ([0,212,53,147,199,21,253,211,28,97,20,26,189,4,169,159,214,130,44,133,88,133,76,205,227,154,86,132,231,165,109,162,125] u8 byte array).

So my inner question is: Which account has to be funded with how much of what curreny to fix the InsufficientBalance error?

Side fact: I am using the following XCM configuration:

Here is the full version: https://pastebin.com/7242tXkA

pub const MY_KEY: &[u8] = &[0, 1];

    pub const NoneNetwork: Option<NetworkId> = None;

...

pub fn vec_to_fixed_array<const S: usize>(src: Vec<u8>) -> [u8; S] {
    let mut dest = [0; S];
    let len = min(src.len(), S);
    dest[..len].copy_from_slice(&src.as_slice()[..len]);

    dest
}

pub fn general_key(data: &[u8]) -> Junction {
    GeneralKey {
        length: data.len().min(32) as u8,
        data: vec_to_fixed_array(data.to_vec()),
    }
}
...

/// Means for transacting assets on this chain.
pub type MultiAssetTransactor = MultiCurrencyAdapter<
    // All known Assets will be processed by the following MultiCurrency implementation.
    Currencies,
    // Any unknown Assets will be processed by the following UnknownAsset implementation.
    (),
    // This means that this adapter should handle any token that `AssetConvert` can convert
    // using Currencies and UnknownTokens in all other cases.
    IsNativeConcrete<AssetId, AssetConvert>,
    // Our chain's account ID type (we can't get away without mentioning it explicitly).
    AccountId,
    // Convert an XCM `MultiLocation` into a local account id.
    LocationToAccountId,
    // The AssetId that corresponds to the native currency.
    AssetId,
    // Struct that provides functions to convert `Asset` <=> `MultiLocation`.
    AssetConvert,
    // In case of deposit failure, known assets will be placed in treasury.
    DepositToAlternative<RootAccount, Currencies, AssetId, AccountId, Balance>,
>;

...

/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
/// `Transact` in order to determine the dispatch Origin.
pub type LocationToAccountId = (
    // The parent (Relay-chain) origin converts to the default `AccountId`.
    ParentIsPreset<AccountId>,
    // Sibling parachain origins convert to AccountId via the `ParaId::into`.
    SiblingParachainConvertsVia<polkadot_parachain_primitives::primitives::Sibling, AccountId>,
    // If we receive a MultiLocation of type AccountKey20, just generate a native account
    AccountId32Aliases<NoneNetwork, AccountId>,
    // Generate remote accounts according to polkadot standards
    staging_xcm_builder::HashedDescription<
        AccountId,
        staging_xcm_builder::DescribeFamily<staging_xcm_builder::DescribeAllTerminal>,
    >,
);

...


/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
/// biases the kind of local `Origin` it will become.
pub type XcmOriginToTransactDispatchOrigin = (
    // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
    // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
    // foreign chains who want to have a local sovereign account on this chain which they control.
    SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
    // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
    // recognised.
    RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
    // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
    // recognised.
    SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
    // Native signed account converter; this just converts an `AccountId32` origin into a normal
    // `RuntimeOrigin::Signed` origin of the same 32-byte value.
    SignedAccountId32AsNative<NoneNetwork, RuntimeOrigin>,
    // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
    XcmPassthrough<RuntimeOrigin>,
);

...

/// Convert an incoming `MultiLocation` into a `Asset` if possible.
/// Here we need to know the canonical representation of all the tokens we handle in order to
/// correctly convert their `MultiLocation` representation into our internal `Asset` type.
impl Convert<MultiLocation, Option<AssetId>> for AssetConvert {
    fn convert(location: MultiLocation) -> Option<AssetId> {
        if location == MultiLocation::parent() {
            return Some(1u32);
        }

        match location {
            MultiLocation {
                parents: 0,
                interior: X1(GeneralKey { data, length }),
            } => {
                let key = &data[..data.len().min(length as usize)];
                if key == MY_KEY {
                    return Some(0u32);
                }

                None
            }
            MultiLocation {
                parents: 1,
                interior: X2(Parachain(para_id), GeneralKey { data, length }),
            } => {
                let key = &data[..data.len().min(length as usize)];
                if para_id == u32::from(ParachainInfo::parachain_id()) && key == MY_KEY {
                    return Some(0u32);
                }

                AssetRegistry::location_to_asset_id(location)
            }
            _ => AssetRegistry::location_to_asset_id(location),
        }
    }
}

enter image description here

0x76f80ba707bc6d37e0a1403c995b3cba9d424ed6ab87262b0e9a30d5dc5822c5

I am already figuring this out for 3 days.. It does not make any sense and I would really love some help now.

Thanks!

2 Answers 2

2
  1. Maybe you should pass 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125 to the substrate utils, the result is 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d, it's Alice
  2. This location conversion was failed. AccountId32Aliases got None when withdraw_asset who is {parents: 1, ...}, so it want transfer from None address, failed. Why parents:1? WithComputedOrigin change the origin.

My test log

xcm::currency_adapter: [Parachain] withdraw_asset what: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X1(PalletInstance(5)) }), fun: Fungible(1000000000000000000) }, who: MultiLocation { parents: 1, interior: X2(Parachain(2105), AccountKey20 { network: Some(Rococo), key: [192, 240, 244, 171, 50, 76, 70, 229, 93, 2, 208, 3, 51, 67, 180, 190, 138, 85, 83, 45] }) }

You cannot let someone claiming to be Alice from parachain X use the Alice account in parachain Y. That would put your chain at risk, as parachain X can claim to be a descended origin of any account.

Track here https://github.com/paritytech/polkadot-sdk/issues/2130

5
  • I tried this again. Unfortunately, this doesn't work. So the account is funded with that balance and more already.
    – Chralt
    Nov 2, 2023 at 6:03
  • Could you provide your repo?
    – Guantong
    Nov 2, 2023 at 6:50
  • Unfortunately I won't post the repo (because it's in private stealth mode for multiple reasons), but I will post my full xcm configuration: pastebin.com/7242tXkA
    – Chralt
    Nov 2, 2023 at 7:28
  • However, I am 100% sure that the pallet-balances emits this error. So I can exclude the case of oml-tokens emitting this error. It can still be orml-currencies (Currencies), though.
    – Chralt
    Nov 2, 2023 at 9:27
  • @Chralt Follow here: github.com/paritytech/polkadot-sdk/issues/2130
    – Guantong
    Nov 2, 2023 at 10:13
1

You cannot let someone claiming to be Alice from parachain X use the Alice account in parachain Y. That would put your chain at risk, as parachain X can claim to be a descended origin of any account. And that is what Account32Aliases prevents by checking that parents is 0 (i.e., in order to use Alice account in parachain Y the message should have been originated in parachain Y).

You can use the convertor HashedDescription, which will hash the descended multilocation and give you a fresh new account that Alice from parachain X will be able to control in parachain Y

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.