> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phylax.systems/llms.txt
> Use this file to discover all available pages before exploring further.

# Timelock Verification

> Make sure that a timelock has been correctly triggered for governance actions

## When to Use This Pattern

Ensures timelocks are correctly triggered for governance actions, enforcing delays between proposal and execution to allow community review. Critical for DeFi lending protocols, DEX protocols, yield aggregators, cross-chain bridges, and DAOs that use timelocks to prevent flash loan attacks, allow security review periods, and protect against governance attacks.

Timelocks provide a buffer against malicious governance actions - without proper enforcement, changes could be executed immediately.

## What This Pattern Checks

Verifies timelock integrity by comparing timelock state and parameters before and after transactions:

* `_preTx()` / `_postTx()` with Reshiram snapshot reads: Compare timelock state before and after transaction
* `registerTxEndTrigger()`: Monitor changes to timelock storage slot
* Ensures timelock delay is within acceptable bounds (1 day to 2 weeks)
* Confirms timelock activation follows proper procedures

The assertion performs both pre/post state comparison and parameter validation to ensure governance changes follow proper timelock procedures.

For more information about cheatcodes, see the [Cheatcodes Documentation](/credible/cheatcodes-reference).

## Assertion Pattern

```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {Assertion} from "credible-std/Assertion.sol";
import {AssertionSpec} from "credible-std/SpecRecorder.sol";
import {PhEvm} from "credible-std/PhEvm.sol";

contract TimelockVerificationAssertion is Assertion {
    bytes32 internal constant TIMELOCK_DELAY_SLOT = bytes32(uint256(0));
    bytes32 internal constant TIMELOCK_ACTIVE_SLOT = bytes32(uint256(1));

    constructor() {
        registerAssertionSpec(AssertionSpec.Reshiram);
    }

    function triggers() external view override {
        registerTxEndTrigger(this.assertionTimelock.selector);
    }

    /// @notice Checks that an activated timelock uses a bounded delay.
    function assertionTimelock() external view {
        address adopter = ph.getAssertionAdopter();
        PhEvm.ForkId memory preFork = _preTx();
        PhEvm.ForkId memory postFork = _postTx();

        bool preActive = uint256(ph.loadStateAt(adopter, TIMELOCK_ACTIVE_SLOT, preFork)) != 0;
        if (preActive) {
            return;
        }

        bool postActive = uint256(ph.loadStateAt(adopter, TIMELOCK_ACTIVE_SLOT, postFork)) != 0;
        if (postActive) {
            uint256 delay = uint256(ph.loadStateAt(adopter, TIMELOCK_DELAY_SLOT, postFork));

            require(delay >= 1 days && delay <= 2 weeks, "Timelock parameters invalid");
        }
    }
}
```

<Note>Full examples and mock protocol code are available in [credible-std](https://github.com/phylaxsystems/credible-std/tree/master/examples/assertions-book).</Note>

## Related Patterns

* [Owner Change](/assertions-book/assertions/ass05-ownership-change)
* [Implementation Address Change](/assertions-book/assertions/ass01-impl-addr-change)
