At the moment the transaction fee is payed as the native token in the substrate node template. When I create a new asset_id(say BAT) a fungible asset using pallet_assets, How can I now pay the transaction fees using this BAT token?

  • This is the base currency if you have not otherwise added other assets. Have you added a pallet? Or created another instance of one outside balances?
    – Nuke
    Commented Jul 14, 2022 at 12:56
  • so say i've created a new fungible asset(BAT token) using pallet_assets, i want to be able to pay the transactions fees for this node using the created BAT token if user has the balance Commented Jul 14, 2022 at 12:59
  • also there is pallet_asset_tx_payment (github.com/paritytech/substrate/tree/polkadot-v0.9.19/frame/…). Should i be using this to solve this? ... If so, is there any examples that we can look at? Commented Jul 14, 2022 at 13:10
  • @rustyloaki are you able to change your tx_fee from native to asset(BAT token)? Commented Apr 14, 2023 at 7:55

2 Answers 2

  1. In order to do this you will need in your runtime the pallet_asset_tx_payment pallet. Here's an example of the configuration.
    (the pallet would need to be added into the construct_runtime! etc. See statemint as an example).

  2. Now that that type is available it needs to be added into the tuple that is the SignedExtra type like this. As you can see that then becomes part of the UncheckedExtrinsic type.

  3. Then on the client side when you construct the signed transaction the SignedExtra needs to be encoded too (eg. subxt).

  • 1
    On the polkadot-js front there's an issue raised to allow this to be specified on the front end: github.com/polkadot-js/apps/issues/7812
    – Squirrel
    Commented Jul 14, 2022 at 13:59
  • Have you ever done this ?? It also requires to edit UncheckedExtrinsic type inside the command_helper.rs file under node. There we have to call the from function with two arguments, balance and Option<AssetId> which you have skipped. Please provide some examples of the command_helper.rs file as well. Also can you tell how to encode SignedExtra on client side? Commented Jul 20, 2022 at 11:40
  • @Squirrel is it possible to contruct the SignedExtra which is needed by pallet_asset_tx_payment ? Commented Nov 30, 2022 at 7:04
  • This post may be helpful: substrate.stackexchange.com/questions/8063/…
    – Bruno
    Commented Apr 13, 2023 at 10:09
  • error[E0277]: the trait bound pallet_assets::Pallet<Runtime>: hidden_include::traits::fungible::Unbalanced<AccountId32>` is not satisfied. Getting this error, can someone face this error while configuring pallet_asset_tx_payment`
    – go11li
    Commented Apr 27, 2023 at 9:44

We do this at Encointer, the full code including a client that can pay in the custom asset can be found at https://github.com/encointer/encointer-node. I highlight the most important things here:


You need to include the pallet-asset-tx-payment: https://github.com/encointer/encointer-node/blob/6b5f32350874a099178115de09b163e2b2237e61/runtime/src/lib.rs#L467. We have defined our own OnChargeTransaction because we don't use the pallet-assets. You can just use the one that pallet-assets exposes.

You need to add it to the signed extension: https://github.com/encointer/encointer-node/blob/6b5f32350874a099178115de09b163e2b2237e61/runtime/src/lib.rs#L523.

This will add an Option<AssetId> to the signed extension. If it is Some in the extrinsic, it will use the defined asset as fee-payment token; otherwise it falls back to the native token.


In our encointer-client cli we use the substrate-api-client (subxt-alternative) library to connect to it: https://github.com/scs/substrate-api-client.

Here, we define the signed extension type in extrinsic format: https://github.com/encointer/encointer-node/blob/6b5f32350874a099178115de09b163e2b2237e61/client/encointer-api-client-extension/src/extrinsic_params.rs#L17. It says CommunityIdentifier here because we don't use the pallet-assets. You will put AssetId there.

At this point we define that we want to pay with the custom asset: https://github.com/encointer/encointer-node/blob/6b5f32350874a099178115de09b163e2b2237e61/client/src/main.rs#L331.

Polkadot-js/apps sidenote

The SignedExtension is not exposed in the metadata, hence you need to hardcode it. You need to manually add it to the polkadot-js/api type registry, see https://github.com/polkadot-js/apps/blob/c484456c12dbeeaccc701ec89d891e5e3f53a4cc/packages/apps-config/src/api/spec/encointer-para.ts#L247.

This polkadot-js/apps fix is needed because otherwise polkadot-js/apps is not able to correctly interpret blocks that contain an extrinsic paid in the non-native asset, i.e., where the asset-tx-payment signed extension was Some<AssetId>.

  • how can i add to substrate client in which file should i make changes? Commented Apr 13, 2023 at 7:02
  • You can use subxt as documented here.
    – Bruno
    Commented Apr 13, 2023 at 10:08

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.