I am trying to define the Era of a mortal transaction in two ways :


Meaning I am not using the mortal function and I have to input the correct values for Periodand Phase myself which are the parameters of the variant Mortal. As mentioned also in this SE answer, Period and Phase have to be hex in SCALE format. So I can double check that I am inputting the right values by using also these substrate js utilities where the last option helps me convert "u8 Array to Hex" and vice versa.

The question in this case is : for the Phase argument how do I know what is the correct value to input (so I can then scale format it accordingly) ?

From the definition and the example it seems to me that the value of phase depends on the value of period but still is not quite clear to me how I can calculate it if I have to input it manually.

Not Manually

Meaning I am using the mortal function. In this case, the arguments I need to pass are period and current. When using this, I do not have to worry about the value of phase since it is calculated here based on the two aforementioned arguments.

However, the question in this case is : How do I know which are the correct values for period and current?

Thank you so much for any feedback on this one!

1 Answer 1


Just some general points about transaction mortality from my digging and understanding so far:

  • The goal of mortality is to define when a transaction is valid from (must be some recent block hash/number) and roughly how many blocks it'll be valid for until it expires and can no longer be added to a block.
  • There are two parts to mortality; first, the Era (Mortal or Immortal; the Mortal variant containing a "phase" and "period" value), and second the "mortality checkpoint" (the block hash of the first block that the transaction is valid from).
  • The Era is encoded into a compact 1 or 2 byte representation (for immortal or mortal respectively) and is a part of the "signed extra" details of the extrinsic. This compact encoding is important to save space in a block.
  • The "mortality checkpoint" hash is a part of the signer payload; ie it's not a part of the extrinsic details, but the node must be able to reproduce it to verify the signature. The node uses the "phase" value to work out which block hash should be a part of the signer payload for verification.

With that in mind, let's get to the questions:

Not Manually

The Era::mortal function takes two arguments, period and current (both u64s).

  • current is the block number that you'd like the transaction to be valid from. This block number must point to the same block as the block hash provided in the "mortality checkpoint" signer payload argument. Probably it should be some recent block (ie fetching the latest finalized block for instance and using that block hash/number seems like a good default approach).
  • period is the number of blocks after this block that the transaction will be valid for. It should be a power of 2 in the range [4,65536] (the Era::mortal function will make this be the case if the value you provide is not already). The reason for this rounding-to-power-of-two is, I think, so that it can be compressed (along with the internal "phase" value) into just 2 bytes.

These two values are what you really care about when defining mortality; from which block is the tx valid from and after which block does it expire.


If you're not using the Era::manual(..) function (eg because an equivalent is not available in the language you're using), personally my approach would be to copy the logic of it out into your own function. Take care to also copy the logic for how the Era is SCALE encoded and decoded, if that's not handled for you (see here).

Internally, the Era::Mortal stores a period and phase as u64s, and when being SCALE encoded or decoded, it mangles these into just 2 bytes.

  • period has already been described above.
  • phase is a value that a validator can use to work out which block hash it should expect in the signer payload in order to produce an identical signature to that which was given with the tx. See Era::mortal() for how it's calculated.

The spec goes into more detail about the mortality phase and period: https://spec.polkadot.network/id-extrinsics#id-mortality

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.