1

I'm facing the FailedToTransactAsset error while trying to send assets from Statemint to another parachain.

So basically I have the following configuration:

Relay chain

Polkadot relay chain running with the runtime version 10000 and the latest chainspec with 2 validators: alice/bob

Parachains

Statemint(para id: 1000) - a local AssetHub parachain

Custom Parachain(para id: 2000) - a custom parachain that has asset registry and other stuff required for transferring incoming assets

Both parachains are connected between each other with the HRMP channel so I'm able to interact with the sovereign accounts on the relay chain(transferring assets as described here) for both parachains:

[
  [
    [
      {
        sender: 1,000
        recipient: 2,000
      }
    ]
    {
      maxCapacity: 8
      maxTotalSize: 8,192
      maxMessageSize: 1,048,576
      msgCount: 0
      totalSize: 0
      mqcHead: null
      senderDeposit: 0
      recipientDeposit: 0
    }
  ]
  [
    [
      {
        sender: 2,000
        recipient: 1,000
      }
    ]
    {
      maxCapacity: 8
      maxTotalSize: 8,192
      maxMessageSize: 1,048,576
      msgCount: 0
      totalSize: 0
      mqcHead: null
      senderDeposit: 0
      recipientDeposit: 0
    }
  ]
]

I've created a sufficient asset on the AssetHub chain and minted some tokens to Alice account:

enter image description here

I've also created an asset registry mapping for the asset above on custom parachain:

[
    [
      2,983
    ]
    {
      V3: {
        parents: 1
        interior: {
          X3: [
            {
              Parachain: 1,000
            }
            {
              PalletInstance: 50
            }
            {
              GeneralIndex: 1,983
            }
          ]
        }
      }
    }
  ]

Now I want to transfer some amount of assets to custom parachain using polkadotXcm limitedReserveTransferAssets function similar to the extrinsic used here to transfer assets from Polkadot AssetHub to Astar parachain:

[
  {
    name: "dest",
    type: "xcm:VersionedMultiLocation",
    type_name: "Box<VersionedMultiLocation>",
    value: {
      V3: {
        interior: {
          X1: {
            Parachain: 2006
          }
        },
        parents: 1
      }
    }
  },
  {
    name: "beneficiary",
    type: "xcm:VersionedMultiLocation",
    type_name: "Box<VersionedMultiLocation>",
    value: {
      V3: {
        interior: {
          X1: {
            AccountId32: {
              id: "0x0e26695a00e4a7c696ff136e636f70b3450acfed92f345822ae89b606fcd645d",
              network: null
            }
          }
        },
        parents: 0
      }
    }
  },
  {
    name: "assets",
    type: "xcm:VersionedMultiAssets",
    type_name: "Box<VersionedMultiAssets>",
    value: {
      V3: [
        {
          fun: {
            Fungible: "2200000"
          },
          id: {
            Concrete: {
              interior: {
                X2: {
                  col0: {
                    PalletInstance: 50
                  },
                  col1: {
                    GeneralIndex: "1984"
                  }
                }
              },
              parents: 0
            }
          }
        }
      ]
    }
  },
  {
    name: "fee_asset_item",
    type: "U32",
    type_name: "u32",
    value: 0
  },
  {
    name: "weight_limit",
    type: "xcm:v3:WeightLimit",
    type_name: "WeightLimit",
    value: {
      Unlimited: ""
    }
  }
]

After submitting transaction I'm getting the following error with no clue like what exactly has happened:

enter image description here

There are no details for the FailedToTransactAsset error. As far as I understand this is due to a conversion issue as per the source code. However there are 4 types of conversion errors that can happen and I'm not sure which one is in my particular case:

impl From<Error> for XcmError {
    fn from(e: Error) -> Self {
        use XcmError::FailedToTransactAsset;
        match e {
            Error::AssetNotHandled => XcmError::AssetNotFound,
            Error::AccountIdConversionFailed => FailedToTransactAsset("AccountIdConversionFailed"),
            Error::AmountToBalanceConversionFailed =>
                FailedToTransactAsset("AmountToBalanceConversionFailed"),
            Error::AssetIdConversionFailed => FailedToTransactAsset("AssetIdConversionFailed"),
            Error::InstanceConversionFailed => FailedToTransactAsset("InstanceConversionFailed"),
        }
    }
} 

Any help appreciated!


UPDATE

Here is the error from the logs while using -lxcm=trace arg:

2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::execute: [Parachain] !!! ERROR: FailedToTransactAsset("AccountIdConversionFailed")    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] result: Err(ExecutorError { index: 0, xcm_error: FailedToTransactAsset("AccountIdConversionFailed"), weight: <wasm:stripped> })    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] Execution errored at 0: FailedToTransactAsset("AccountIdConversionFailed") (original_origin: MultiLocation { parents: 0, interior: Here })

Full Logs of the XCM:

2023-08-11 11:47:42.037 TRACE tokio-runtime-worker xcm::weight: [Parachain] WeightInfoBounds message: Xcm([TransferReserveAsset { assets: MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }]), dest: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, xcm: Xcm([]) }])    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::weight: [Parachain] WeightInfoBounds message: Xcm([ReserveAssetDeposited(MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }])), ClearOrigin, BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, weight_limit: Limited(<wasm:stripped>) }, DepositAsset { assets: Wild(AllCounted(1)), beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id: [112, 97, 114, 97, 208, 7, 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] }) } }])    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::weight: [Parachain] WeightInfoBounds message: Xcm([TransferReserveAsset { assets: MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }]), dest: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, xcm: Xcm([BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, weight_limit: Limited(<wasm:stripped>) }, DepositAsset { assets: Wild(AllCounted(1)), beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id: [112, 97, 114, 97, 208, 7, 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] }) } }]) }])    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::weight: [Parachain] WeightInfoBounds message: Xcm([TransferReserveAsset { assets: MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }]), dest: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, xcm: Xcm([BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, weight_limit: Limited(<wasm:stripped>) }, DepositAsset { assets: Wild(AllCounted(1)), beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id: [112, 97, 114, 97, 208, 7, 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] }) } }]) }])    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] origin: MultiLocation { parents: 0, interior: Here }, message: Xcm([TransferReserveAsset { assets: MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }]), dest: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, xcm: Xcm([BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, weight_limit: Limited(<wasm:stripped>) }, DepositAsset { assets: Wild(AllCounted(1)), beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id: [112, 97, 114, 97, 208, 7, 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] }) } }]) }]), weight_credit: <wasm:stripped>    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::barriers: [Parachain] TakeWeightCredit origin: MultiLocation { parents: 0, interior: Here }, instructions: [TransferReserveAsset { assets: MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }]), dest: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, xcm: Xcm([BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, weight_limit: Limited(<wasm:stripped>) }, DepositAsset { assets: Wild(AllCounted(1)), beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id: [112, 97, 114, 97, 208, 7, 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] }) } }]) }], max_weight: <wasm:stripped>, weight_credit: <wasm:stripped>    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::process: [Parachain] origin: Some(MultiLocation { parents: 0, interior: Here }), total_surplus/refunded: <wasm:stripped>/<wasm:stripped>, error_handler_weight: <wasm:stripped>    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::process_instruction: [Parachain] === TransferReserveAsset { assets: MultiAssets([MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }]), dest: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, xcm: Xcm([BuyExecution { fees: MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, weight_limit: Limited(<wasm:stripped>) }, DepositAsset { assets: Wild(AllCounted(1)), beneficiary: MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id: [112, 97, 114, 97, 208, 7, 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] }) } }]) }    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::currency_adapter: [Parachain] internal_transfer_asset asset: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, from: MultiLocation { parents: 0, interior: Here }, to: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::fungibles_adapter: [Parachain] internal_transfer_asset what: MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(1984)) }), fun: Fungible(2200000) }, from: MultiLocation { parents: 0, interior: Here }, to: MultiLocation { parents: 1, interior: X1(Parachain(2000)) }    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::execute: [Parachain] !!! ERROR: FailedToTransactAsset("AccountIdConversionFailed")    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] result: Err(ExecutorError { index: 0, xcm_error: FailedToTransactAsset("AccountIdConversionFailed"), weight: <wasm:stripped> })    
2023-08-11 11:47:42.038 TRACE tokio-runtime-worker xcm::execute_xcm_in_credit: [Parachain] Execution errored at 0: FailedToTransactAsset("AccountIdConversionFailed") (original_origin: MultiLocation { parents: 0, interior: Here })    

As I understand the problem can be either in the from or to accounts used in the transfer call. So how should I form the request to transfer-reserve tokens from AssetHub to my parachain?

3
  • Which chain is the error on? Aug 11 at 6:53
  • There is probably an issue with the asset's amount you are trying to transfer with regard to the total issuance and asset. We would need more info about the asset you created, (decimals, min_balance, etc). In any case, follow the recommendation below of adding -lxcm=trace. That will probably will give you the info you need to figure out the issue.
    – NachoPal
    Aug 11 at 7:34
  • @joepetrowski, thanks for the reply. It's about the local relay-parachain setup. I'm trying to start using stablecoin on my local parachain sending it from the Statemint(AssetHub) to my custom parachain and using the AssetHub as a reserve for the asset. Aug 11 at 7:39

2 Answers 2

2

If you are running in local I suppose you are using zombie-net. can you add xcm logs to your config. It will displays which FailedToTransactAsset it is:

  args = [ "-l=xcm=trace" ]

On AssetHub id = 1000 you should register asset location (with the same interior as you have done in 2000). In parachain 2000 you should register location (as you have already done) and also set assets units per second.

This is a plokadotjs script I did to register an asset id = 1 on two Astar parachains (and use XCM to transfer between chains). It will help understanding of the set-up:

const batchA = apiA.tx.utility.batchAll([
    apiA.tx.sudo.sudo(apiA.tx.assets.forceCreate(1, {Id: alice.address}, true, 1)),
    apiA.tx.sudo.sudo(apiA.tx.assets.forceSetMetadata(1, "TST", "Test Token", 0, false)),
    apiA.tx.assets.mint(1, {Id: alice.address}, 1000000n * DECIMALS),
    apiA.tx.sudo.sudo(apiA.tx.xcAssetConfig.registerAssetLocation(
        {
            V3: {
                parents: 0,
                interior: {
                    X1:
                        {GeneralIndex: 1},
                },
            },
        },
        1
    )),
]);
await sendTransaction(batchA, alice);

const batchB = apiB.tx.utility.batchAll([
    // Parcahin A soverign account
    apiB.tx.balances.transferKeepAlive("5Ec4AhPUwPeyTFyuhGuBbD224mY85LKLMSqSSo33JYWCazU4", 1000n * DECIMALS),
    // Fund Parcahin A sovereign account to create token. At least should have mint rights
    apiB.tx.sudo.sudo(apiB.tx.assets.forceCreate(1, "5Ec4AhPUwPeyTFyuhGuBbD224mY85LKLMSqSSo33JYWCazU4", true, 1)),
    apiB.tx.sudo.sudo(apiB.tx.assets.forceSetMetadata(1, "TST", "Test Token", 0, false)),
    apiB.tx.sudo.sudo(apiB.tx.xcAssetConfig.registerAssetLocation(
        {
            V3: {
                parents: 1,
                interior: {
                    X2: [
                        {Parachain: 2000},
                        {GeneralIndex: 1},
                    ],
                },
            },
        },
        1
    )),
    apiB.tx.sudo.sudo(apiB.tx.xcAssetConfig.setAssetUnitsPerSecond(
        {
            V3: {
                parents: 1,
                interior: {
                    X2: [
                        {Parachain: 2000},
                        {GeneralIndex: 1},
                    ],
                },
            },
        },
        1
    )),
]);

await sendTransaction(batchB, alice);
5
  • thanks for the reply. There is no ability to register asset location in parachain 1000 since it is a statemint(asset hub) parachain and there is no such pallet as far as I understand. The idea is to send stablecoin from the AssetHub to my parachain and use the AssetHub as a reserve for the asset. Btw, neither -lxcm=trace nor -l=xcm=trace arguments didn't help for both parachain and relay chain - there is simply nothing in the logs unfortunately. Aug 11 at 7:37
  • How are you adding the log flag? You should add it to AssetHub collator and you should get some logs
    – NachoPal
    Aug 11 at 8:31
  • @NachoPal, my bad) - was adding the argument to the relay chain config. So here is the error: [Parachain] !!! ERROR: FailedToTransactAsset("AccountIdConversionFailed") So as I understand the problem can be either in the from or to accounts used in the transfer call. So how should I form the request to send reserve tokens from AssetHub to my parachain. I'm using this call as an example: assethub-polkadot.subscan.io/extrinsic/… Aug 11 at 8:58
  • We need to see the actual XCM that the executor is trying to process. You should be able to get it from the logs also.
    – NachoPal
    Aug 11 at 9:24
  • @NachoPal added xcm logs in the updated section of the question. Aug 11 at 9:29
0

In my particular case it was a problem with calling the polkadotXcm extrinsic via sudo call.

Switching to calling the polkadotXcm --> limitedReserveTransferAssets(dest, beneficiary, assets, feeAssetItem, weightLimit) extrinsic directly via Alice account did the trick.

However, in general, the AccountIdConversionFailed is a bit confusing.

2
  • It would be interesting if you could add your configs for AssetTransactor and OriginConverter of your chians :) Aug 14 at 14:39
  • 1
    @AlejandroMartínez, nothing special, actually. I’ve been using asset hub configuration from cumulus github repo. Here it is - github.com/paritytech/cumulus/blob/… Aug 15 at 7:41

Your Answer

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

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