pub trait Hooks<BlockNumber> {
    // Provided methods
    fn on_initialize(_n: BlockNumber) -> Weight { ... }
    fn on_finalize(_n: BlockNumber) { ... }
    fn on_idle(_n: BlockNumber, _remaining_weight: Weight) -> Weight { ... }
    fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter) { ... }
    fn on_runtime_upgrade() -> Weight { ... }
    fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError> { ... }
    fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> { ... }
    fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> { ... }
    fn offchain_worker(_n: BlockNumber) { ... }
    fn integrity_test() { ... }
Expand description

The pallet hooks trait. This is merely an umbrella trait for:


For all hooks, except OnIdle the order of execution is derived from how the pallets are ordered in crate::construct_runtime.


In short, the following diagram shows the flow of hooks in a pallet

graph LR Optional --> BeforeExtrinsics BeforeExtrinsics --> Extrinsics Extrinsics --> AfterExtrinsics subgraph Optional OnRuntimeUpgrade end subgraph BeforeExtrinsics OnInitialize end subgraph Extrinsics direction TB Inherent1 Inherent2 Extrinsic1 Extrinsic2 Inherent1 --> Inherent2 Inherent2 --> Extrinsic1 Extrinsic1 --> Extrinsic2 end subgraph AfterExtrinsics OnIdle OnFinalize OnIdle --> OnFinalize end
  • OnRuntimeUpgrade hooks are only executed when a code change is detected.
  • OnRuntimeUpgrade hooks are mandatorily executed at the very beginning of the block body, before any extrinsics are processed.
  • Inherents are always executed before any other other signed or unsigned extrinsics.
  • OnIdle hooks are executed after extrinsics if there is weight remaining in the block.
  • OnFinalize hooks are mandatorily executed after OnIdle.

OffchainWorker hooks are not part of this flow, because they are not part of the consensus/main block building logic. See OffchainWorker for more information.

To learn more about the execution of hooks see the FRAME Executive pallet which is in charge of dispatching extrinsics and calling hooks in the correct order.

Provided Methods§


fn on_initialize(_n: BlockNumber) -> Weight

Block initialization hook. This is called at the very beginning of block execution.

Must return the non-negotiable weight of both itself and whatever Hooks::on_finalize wishes to consume.


The weight returned by this is treated as DispatchClass::Mandatory, meaning that it MUST BE EXECUTED. If this is not the case, consider using Hooks::on_idle instead.

Try to keep any arbitrary execution deterministic and within minimal time complexity. For example, do not execute any unbounded iterations.

NOTE: This function is called BEFORE ANY extrinsic in a block is applied, including inherent extrinsics. Hence for instance, if you runtime includes pallet-timestamp, the timestamp is not yet up to date at this point.


fn on_finalize(_n: BlockNumber)

Block finalization hook. This is called at the very end of block execution.

Note that this has nothing to do with finality in the “consensus” sense.

Note that the non-negotiable weight for this has must have already been returned by Hooks::on_initialize. It usage alone is not permitted.

Similar to Hooks::on_initialize it should only be used when execution is absolutely necessary. In other cases, consider using Hooks::on_idle instead.


fn on_idle(_n: BlockNumber, _remaining_weight: Weight) -> Weight

Hook to consume a block’s idle time. This will run when the block is being finalized (before Hooks::on_finalize).

Given that all dispatchables are already executed and noted (and the weight for Hooks::on_finalize, which comes next, is also already accounted for via on_initialize), this hook consumes anything that is leftover.

Each pallet’s on_idle is chosen to be the first to execute in a round-robin fashion indexed by the block number.

Return the weight used, the caller will use this to calculate the remaining weight and then call the next pallet on_idle hook if there is still weight left.

Any implementation should always respect _remaining_weight and never consume (and therefore return) more than this amount.


fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter)

A hook to run logic after inherent application.

Is not guaranteed to execute in a block and should therefore only be used in no-deadline scenarios.


fn on_runtime_upgrade() -> Weight

Hook executed when a code change (aka. a “runtime upgrade”) is detected by the FRAME Executive pallet.

Be aware that this is called before Hooks::on_initialize of any pallet; therefore, a lot of the critical storage items such as block_number in system pallet might have not been set yet.

Similar to Hooks::on_initialize, any code in this block is mandatory and MUST execute. It is strongly recommended to dry-run the execution of these hooks using try-runtime-cli to ensure they will not produce and overweight block which can brick your chain. Use with care!

§Implementation Note: Standalone Migrations

Additional migrations can be created by directly implementing OnRuntimeUpgrade on structs and passing them to Executive. Or alternatively, by implementing UncheckedOnRuntimeUpgrade, passing it to crate::migrations::VersionedMigration, which already implements OnRuntimeUpgrade.

§Implementation Note: Pallet Versioning

Implementations of this hook are typically wrapped in crate::migrations::VersionedMigration to ensure the migration is executed exactly once and only when it is supposed to.

Alternatively, developers can manually implement version checks.

Failure to adequately check storage versions can result in accidental repetitive execution of the hook, which can be catastrophic.

§Implementation Note: Weight

Typically, implementations of this method are simple enough that weights can be calculated manually. However, if required, a benchmark can also be used.


fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError>

Execute the sanity checks of this pallet, per block.

It should focus on certain checks to ensure that the state is sensible. This is never executed in a consensus code-path, therefore it can consume as much weight as it needs.

This hook must not alter any storage.


fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError>

Execute some pre-checks prior to a runtime upgrade.

Return a Vec<u8> that can contain arbitrary encoded data (usually some pre-upgrade state), which will be passed to post_upgrade after upgrading for post-check. An empty vector should be returned if there is no such need.

This hook is never executed on-chain but instead used by testing tools.


fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError>

Execute some post-checks after a runtime upgrade.

The state parameter is the Vec<u8> returned by pre_upgrade before upgrading, which can be used for post-check. NOTE: if pre_upgrade is not implemented an empty vector will be passed in, in such case post_upgrade should ignore it.

This hook is never meant to be executed on-chain but is meant to be used by testing tools.


fn offchain_worker(_n: BlockNumber)

Implementing this function on a pallet allows you to perform long-running tasks that are dispatched as separate threads, and entirely independent of the main blockchain execution.

This function can freely read from the state, but any change it makes to the state is meaningless. Writes can be pushed back to the chain by submitting extrinsics from the offchain worker to the transaction pool. See pallet-example-offchain-worker for more details on this.

Moreover, the code in this function has access to a wider range of host functions in [sp-io], namely sp_io::offchain. This includes exotic operations such as HTTP calls that are not really possible in the rest of the runtime code.

The execution of this hook is entirely optional and is left at the discretion of the node-side software and its configuration. In a normal substrate-cli, look for the CLI flags related to offchain-workers to learn more.


fn integrity_test()

Check the integrity of this pallet’s configuration.

Any code located in this hook is placed in an auto-generated test, and generated as a part of crate::construct_runtime’s expansion. Look for a test case with a name along the lines of: __construct_runtime_integrity_test.

This hook is the location where the values/types provided to the Config trait of the pallet can be tested for correctness. For example, if two type Foo: Get<u32> and type Bar: Get<u32> where Foo::get() must always be greater than Bar::get(), such checks can be asserted upon here.

Note that this hook is executed in an externality environment, provided by sp_io::TestExternalities. This makes it possible to access the storage.

Object Safety§

This trait is not object safe.