# How to estimate the timestamp of a future block in Substrate?

I have some expiry time in `block` number which I need to deem some storage values expired after that block number, however in the UX I want to present this value as an estimated datetime. So to be able to do this I believe I need to read the timestamp of the current block and then have an estimation of the time that it takes to generate a block (block_time) and then calculate a timespan as block_count*block_time.

Is this the best way to estimate the timestamp of a future block?!

If yes, what is the best way to get an estimation of the `block_time` (time that it takes to generate a block)?!

The answer here is highly dependent on the block production algorithm used. You'd need different logic for each algorithm.

If you are aware of an existing block X and want to predict the timestamp of a block X+k, the basic way of doing this is with the formula `average_block_time*k + timestamp(X)`. Finding the timestamp can be done by reading the storage of the `Timestamp` pallet - specifically, the `Now` storage item. Or you can extract something specific like a BABE slot from the block's header and extract a timestamp that way. Neither is perfectly accurate, and neither is better than the other. Timestamps in blockchains aren't objective, and usually slightly inaccurate.

Finding the average block time in BABE can't be done by querying storage, so it's best to just hardcode it per chain or emulate the logic of `fn slot_duration`

• You can query the average block time in BABE through the Runtime Constants. Mar 23, 2022 at 5:34
• Just for complete: For parachains, the future block time will be harder to estimate. For example, the expected block time for parachains on Kusama is 12s, but the actual average block time is ~20s. This heavily depends on the performance of the relay chain. Mar 23, 2022 at 6:19

To add to Rob and Shawn's post... The expected blocktime above is really focussed on chains with `babe`, so it makes 100% sense in the context of the relay chains and production chains using Babe.

However, there are outliers and in some cases chains with different setups. So for instance in the apps UI, it tries to cater for a whole host of chains -

Walking through it -

1. When babe is in-use, use the `babe.expectedBlockTime`
2. For Kulupu (POW), use `difficulty.targetBlockTime`
3. For subspace, use `subspace.expectedBlockTime`
4. For others, use `timestamp.minimumPeriod * 2`, however
• Some chains have it as 50% of expected time
• Some chains don't and use this internally only, in those cases you need to make some assumptions, e.g. is it possibly a parachain
1. If all else fails and nothing can be found, well, the above applies defaults (may not be applicable to all)

The above is most probably not perfect and quite possibly missing some cases and/or is ripe for enhancement in the cases where things cannot be found.

To add to Rob's post, in the context of User Experience, the best you can do is give a user an estimate which is updated block to block.

Most logic on the blockchain is measured out in blocks.

Unfortunately, no consensus system that I know of can provide perfectly accurate time between blocks. Instead, the network has mechanisms to encourage block production within an average window, but can always allow for some error from that average window from block to block.

For example, in Ethereum and Bitcoin, the block difficulty is adjusted to account for having blocks produced at a specific average interval, however lucky (or unlucky) mining could lead to short or long blocks.

For Substrate / Polkadot, we allow for block producers to miss their slot, which can lead to longer time between blocks.

So, if presenting a user with an estimate of how much time before some event on chain happens, I would do the following:

1. Get the timestamp of the last block produced from the `Timestamp` pallet.

2. Calculate the estimated future time as a best effort.

`time_at_last_block + average_block_time * number_of_blocks`

3. Listen for a new block to be produced, and repeat this process.

This means that a user may see a countdown time go higher after going down, but practically speaking, this is an accurate representation of what is happening on chain.

You can query the `average_block_time` from the BABE constants: