I was looking at removing some extrinsics from my pallet and wanted to know the safe way of going about it.

  • Can/should I reuse the call_index?
  • How will historic transaction data be impacted?

Anything else I need to watch out for?


  • have you made any custom pallet or are trying to remove an extrinsic from an existing pallet? Commented Jun 19, 2023 at 6:22
  • I am thinking about removing an existing extrinsic from an existing pallet and do an upgrade.
    – Nahu
    Commented Jun 19, 2023 at 8:35

1 Answer 1


Each call receives an index depending on its position in the Call Enum of a pallet. One could as well explicitly assign a concrete index to a call, for instance:


#[pallet::weight(<T as Config>::WeightInfo::register_fast_unstake())]
pub fn register_fast_unstake(origin: OriginFor<T>) -> DispatchResult {

This index will be, among other things, used to properly encode the call.

By explicitly assigning indices to each call you are shielding your calls against getting another index after a runtime upgrade where one other call has been removed, reorganising the indices for all the following calls in this pallet's Call Enum.

Similarly this happens as well with pallets in construct_runtime!, where we can also assign explicit indices for them.

My advise would be that in this runtime upgrade you are about to make, assign explicit indices to your calls too in case you are not doing that already so that when removing a certain call it doesn't mess with the rest of indices.

After the upgrade clients encoding non existing calls will just get an error back, but if the rest of them kept the same index and its pallet did too, those call encodings should work fine.

  • So if I am removing the last extrinsic and add a new one later (in future upgrades) I should somehow make sure I don't accidentally re-use the same index i removed in the past? Example: I removed call_index 3 today and 6 months later I add a new extrinsic to the pallet.
    – Nahu
    Commented Jun 19, 2023 at 9:59
  • Check how transfer ext is being offboarded from pallet-balances, giving some time for clients to upgrade - github.com/paritytech/substrate/blob/… Commented Jun 19, 2023 at 10:18
  • There is nothing preventing you to reuse a certain extrinsic that was used in the past, but giving users some time to update on their side is a very healthy practice, I would say. Commented Jun 19, 2023 at 10:20
  • Thanks it makes perfect sense to me. Just to clarify, in this example #[pallet::call_index(7)] should never be used again for anything right? I.e. After this extrinsic is removed, if someone adds a totally different extrinsic with the same index it will break things?
    – Nahu
    Commented Jun 19, 2023 at 10:35
  • 1
    So, nothing will break in case you reuse an old index, is just that users of your runtime that are unaware of the change will be encoding a call that either will fail, or will end up in an unexpected behaviour. Example: They will be encoding call 3 thinking that it is fn hello_world(), but instead this index is now fn foo(). Nothing breaks on the runtime side, but as long as they are not aware of this change, they'll be making the wrong call, most probably. Commented Jun 19, 2023 at 11:50

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.