> ## Documentation Index
> Fetch the complete documentation index at: https://phylaxsystems-docs-project-incidents.mintlify.site/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

## Use Case & Applications

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.

## Explanation

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

* `forkPreTx()` / `forkPostTx()`: Compare timelock state before and after transaction
* `registerStorageChangeTrigger()`: 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).

## Code Example

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

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

contract TimelockVerificationAssertion is Assertion {
    function triggers() external view override {
        // Register trigger for changes to the timelock storage slot
        registerStorageChangeTrigger(this.assertionTimelock.selector, bytes32(uint256(0)));
    }

    // Verify that a timelock is working as expected after some governance action
    function assertionTimelock() external {
        // Get the assertion adopter address
        IGovernance adopter = IGovernance(ph.getAssertionAdopter());

        // Get pre-state timelock information
        ph.forkPreTx();
        bool preActive = adopter.timelockActive();

        // If timelock was already active, no need to check further
        if (preActive) {
            return;
        }

        // Get post-state timelock information
        ph.forkPostTx();

        // If timelock is now active, verify all parameters
        if (adopter.timelockActive()) {
            // Verify timelock delay is within acceptable bounds
            bool minDelayCorrect = adopter.timelockDelay() >= 1 days;
            bool maxDelayCorrect = adopter.timelockDelay() <= 2 weeks;

            // Require all parameters to be correct
            require(minDelayCorrect && maxDelayCorrect, "Timelock parameters invalid");
        }
    }
}

interface IGovernance {
    struct Timelock {
        uint256 timelockDelay;
        bool isActive;
    }

    function timelockActive() external view returns (bool);
    function timelockDelay() external view returns (uint256);
    function activateTimelock() external;
    function setTimelock(uint256 _delay) external;
}
```

<Note>Full examples with tests available in the [Phylax Assertion Examples Repository](https://github.com/phylaxsystems/assertion-examples/blob/main/assertions/).</Note>

## Related Assertions

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