Use Case

Many DeFi protocols use timelocks to delay the execution of governance actions. It is important to make sure that timelocks are working as expected. Similarly it’s important to make sure that the admin is the same as the pre-state admin. This is useful since admins usually have additional privileges and could be used to manipulate the protocol.

Explanation

This assertion makes sure that the timelock has been correctly triggered for governance actions. It also check that the admin is the same as the pre-state admin.

Code Example

// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

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

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

    function timelock() external view returns (Timelock memory);
}

// Verify that a timelock is working as expected after some governance action
contract TimelockVerification is Assertion {
    IGovernance governance = IGovernance(address(0xbeef));

    function fnSelectors() external pure override returns (bytes4[] memory assertions) {
        assertions = new bytes4[](1);
        assertions[0] = this.assertionTimelock.selector;
    }

    // This assertion checks that if a timelock is activated that it's within the correct parameters
    // and that the admin is the same as the pre-state admin
    // revert if the timelock is not active or if the timelock delay is not within the correct parameters
    function assertionTimelock() external {
        address preAdmin = governance.timelock().admin;
        ph.forkPreState();
        if (governance.timelock().isActive) {
            return; // Timelock is already active prior to the transaction, so we don't need to check anything
        }

        ph.forkPostState();

        if (governance.timelock().isActive) {
            bool minDelayCorrect = governance.timelock().timelockDelay >= 1 days; // Choose whatever fits your protocol
            bool maxDelayCorrect = governance.timelock().timelockDelay <= 2 weeks; // Choose whatever fits your protocol
            bool adminCorrect = governance.timelock().admin == preAdmin;
            require(
                minDelayCorrect && maxDelayCorrect && adminCorrect,
                "Timelock is not active after the transaction, so there's nothing to check"
            );
        } 
    }
}