DeFi Security AllianceRequest an audit
Menu

EVM patterns

Governance Timelock Security: Readiness, Roles and Execution

An elapsed delay makes an operation eligible for further checks, while authority and dependencies still govern execution. Governance timelock security requires closing target bypasses and testing roles, predecessors and recovery paths.

Hourglass connected to a locked blue gate with a separate key, illustrating elapsed time and execution authority.

Key facts

Original state grid
60 constructed timestamp, executor and predecessor cases
Pre-call outcome
12 pass modeled gates; 48 reject before target execution
Ready subset
12 of 24 Ready cases reject, split equally between role and predecessor
Cancellation authority
Pinned source requires CANCELLER_ROLE
Limit
OpenZeppelin v5.4.0 source model, no EVM or target calls

Map the authority that the delay actually controls

A delay protects only the actions that must pass through it. Governance timelock security begins with the target's authority graph: which address can upgrade, move funds or change a critical parameter, and which route that address must use. A scheduled proposal does not constrain a second administrator who can call the same target directly.

A governance timelock separates scheduling an authorized operation from making it eligible for later execution. In OpenZeppelin's pinned TimelockController v5.4.0, proposer, executor, canceller and administrator permissions are distinct. Review the current role assignments rather than treating a deployment constructor's initial relationships as permanent.

The constructor grants its listed proposers both proposer and canceller roles. Later grants can separate them. The actual cancellation function requires CANCELLER_ROLE; a statement that any current proposer can cancel would be broader than the source establishes. This is one reason an authority review should trace function guards instead of copying a short API description.

Authority paths that decide whether a governance delay is effective
Actor or pathRequired reviewAcceptance condition
Target administratorAll direct privileged entrypointsProtected actions cannot bypass the intended delay
ProposerWho can schedule exact operationsScheduling matches the governance policy
CancellerWho can delete pending operationsCancellation power is explicitly approved
Role administratorWho can add or remove authorityRole changes follow the intended control path

OpenZeppelin's governance guidance places funds, ownership and access roles with the timelock that executes proposals. That is a deployment requirement to verify in the actual target graph. A Governor can coordinate proposals while a forgotten target owner still retains immediate authority. The governance interface and target permissions need to agree.

A nonzero bootstrap administrator is useful for initial configuration. In this source it can configure roles without waiting for the timelock. Record that power, its intended lifetime and the evidence of its eventual disposition. Merely publishing a delay value does not explain whether bootstrap authority still exists.

The DAO security audit guide addresses the broader voting and treasury system. This article focuses on the execution boundary after an operation has been scheduled. It uses a fixed source version and explicit state tests, rather than a recommendation that one delay duration suits every governance process.

Original execution gate grid

Method

We modeled the pinned source's executor authorization, operation readiness and predecessor conditions across a complete finite grid. The model stops before the target call. Its outcome means that the operation passed those pre-call gates, not that a governance transaction succeeded or that a deployment is safe.

Source
OpenZeppelin Contracts v5.4.0 TimelockController.sol, retrieved on .
Time fixtures
Fixed current time 1000 and stored timestamps 0, 1, 999, 1000 and 1001.
Role fixtures
Both open-role states and both caller-executor states.
Dependency fixtures
No predecessor, a predecessor not Done and a predecessor Done.
Population and exclusions
60 Cartesian cases; no exclusions. Equivalent authorization outcomes remain as distinct declared input cases.
Artifacts
seo/research/integration-boundaries-2026-10-11/support-storage-timelock/source-and-measurements.py and timelock-state-grid.json. Full rows remain in the repository, not public downloads.

Results

Pre-call gate outcomes in the complete model, measured
Operation stateCasesPre-call passes
Unset120
Done120
Waiting120
Ready2412

Across the full grid, 12 cases passed and 48 failed a modeled gate. Readiness alone was insufficient in half of the Ready subset: 6 Ready cases failed executor authorization and another 6 failed the predecessor condition. Those are counts within a constructed population, not governance failure rates.

The equality boundary matters. A nonsentinel timestamp equal to current time is Ready. Timestamp 1 is the implementation's Done sentinel, so it must not be interpreted as an unusually old due time. Timestamp 0 represents Unset. A test that treats every past timestamp alike has erased meaningful source states.

Limits

  • No EVM, target call, gas behavior or real governance deployment was tested.
  • The model covers only the declared time, role and predecessor inputs before execution.
  • Target failure and the source's after-call readiness check remain outside this grid. A passing row is not a successful transaction.

Our measured implication is narrow but useful: a status label that says Ready should not promise execution. An execution preview must also identify executor eligibility, predecessor completion and the target's own conditions. Preserve each observation separately so the operator can tell which dependency prevents progress.

Follow an operation through its states

An operation identifier commits to the exact execution content. A single operation hashes the target, native value, calldata, predecessor and salt. A batch commits corresponding arrays along with predecessor and salt. An interface that displays a proposal title without decoding those fields has not exposed the actual queued action.

Scheduling requires proposer authority and a delay no shorter than the current minimum. It records a due timestamp from the scheduling block and supplied delay. The source rejects an already registered operation identifier. A salt distinguishes otherwise identical content, but it does not remove the need to verify the target or calldata.

Readiness is one stage in an authorized executionA scheduled operation waits until its due time. Ready state permits further checks for executor authority and predecessor completion. The operation reaches Done only after the target path and the post-call readiness check succeed.WaitingReadyExecution checks then DoneCancellation can return a pending ID to Unset
The due time opens a gate; completion requires the remaining authorized execution path.
Waiting
A registered operation has a due timestamp beyond the current block time.
Ready
The due boundary has arrived, while execution dependencies still need to pass.
Done
The pinned source has completed the target path and marked the identifier with its completion sentinel.
Unset
No registered timestamp exists, including after an authorized cancellation deletes it.

OpenZeppelin's implementation checks readiness again after the target calls. That check is meaningful because the target path can interact with operation state. The finite pre-call grid does not simulate such interactions. Preserve this distinction when converting a source-derived model into application tests: a passing initial condition is only the beginning of execution.

An operation can remain Ready for reasons unrelated to a defect in the timer. Its executor may be unavailable, its predecessor may not be Done or its target may reject current state. Observability should classify those situations. Automatically rescheduling or changing authority to clear a Ready label can alter the governance decision.

Use exact payload reconstruction for the review window. A proposal's plain-language explanation should match decoded target calls and native values. If an operation depends on an earlier one, show that relationship explicitly. The predecessor field proves a dependency was committed, but reviewers still need to assess whether the preceding operation produces the state the target expects.

Separate cancellation from emergency recovery

Cancellation deletes the timestamp of a pending operation. In this source, pending includes Waiting and Ready, while completed and unset operations cannot be canceled through that path. Deleting the record returns the identifier to Unset, after which an authorized rescheduling starts a new timer. The old elapsed delay does not become reusable credit.

Emergency recovery may require a different target authority. A guardian capable of pausing one action is not automatically capable of canceling its queued governance payload. Conversely, a canceller can disrupt an approved operation without owning the target. Record these capabilities by function and actor, then decide whether their scope fits the governance policy.

Recovery controls and their distinct consequences
ControlState or authority changedReview question
Cancel a pending IDIts scheduled timestamp is deletedWho holds canceller authority?
Pause the targetApplication-specific operations may be blockedWhich calls remain possible?
Change a roleScheduling or execution authority changesDoes the role administrator bypass delay?
Change minimum delayFuture scheduling uses a different minimumWas the timelock self-call properly approved?

Updating the minimum delay requires the timelock itself as caller. The source describes the new minimum as applying to future operations. Do not claim that changing it rewrites every queued operation's due timestamp. Review the exact scheduled records and the self-call that changes future policy.

Open executor authority is implemented by granting the executor role to address(0). This permits anyone to submit a qualifying execution; it does not authorize anyone to schedule arbitrary content. It can reduce dependence on a particular executor, while the target and operation gates still determine what can happen. Make that deployment choice explicit instead of labeling it universally safe or unsafe.

The governance guide warns that additional proposers can bypass the intended governance process and additional cancellers can disrupt approved proposals. This is a capability argument, not a claim that every extra role holder is malicious. Identify why the authority exists, what evidence governs its use and how it can be removed under the intended policy.

Our emergency pause guide examines the application side of recovery. A timelock review should connect to that plan without collapsing pause, cancellation, upgrade and role administration into one emergency permission. Each route has its own effect and potential bypass.

Rehearse execution and dependent operations

Begin with an operation that should succeed in an isolated test. Advance time to just before its due boundary, then exactly to it, preserving the caller and predecessor assumptions. Assert both the expected state and the reason for rejection. A target call that always reverts would make a readiness test look successful for the wrong reason.

  1. Pin the timelock implementation, target code and current role configuration. Identify the exact operation fields and reconstructed identifier.
  2. Schedule with the approved delay, then verify the stored timestamp and Waiting state.
  3. Test execution before the due boundary with a valid executor and completed dependencies. Confirm the timer is the failing gate.
  4. At the due boundary, test both permitted and unpermitted executors, including the configured open-role case.
  5. Hold a committed predecessor incomplete, then complete it through its authorized path and retry the unchanged dependent operation.
  6. Exercise the target's success and failure paths. Assert the operation record and target state after each outcome.

Batch operations need value and array checks as well as target behavior. The pinned scheduling path rejects mismatched target, value and payload array lengths. The governance API describes a batch operation's calls as atomic. Application tests should still inspect which target failed and verify the resulting state, rather than report only that the wrapper reverted.

A dependency graph can become an availability problem even when every individual authorization is correct. If a predecessor is canceled, the dependent operation still commits to that identifier. Its execution cannot simply assume the predecessor is complete. Decide whether the intended recovery is to reschedule the prerequisite, replace the dependent operation or change the business decision through governance.

Time-based tests should use the chain's block timestamp boundary without implying that a wall-clock alarm executes the transaction. A due operation still needs a submitted transaction and its remaining conditions. Operational documentation should name the executor or public execution route and the monitoring responsibility.

Track privileged target routes outside the rehearsed proposal. Testing the queued upgrade does not establish that a second upgrader has no direct path. Compare the rehearsal packet with the target's authority graph. A bypass found there is a deployment-scope issue even if the timer implementation itself behaves exactly as documented.

For a review engagement, the security firm directory and Pharos Production member profile support provider selection. Supply the timelock, target and Governor together where their relationship determines authority. A timer-only code review cannot establish the surrounding governance closure.

Keep the governance decision reproducible

The acceptance record should preserve the operation identifier, decoded payload, scheduling evidence, due timestamp, predecessor and observed role grants. Include the target permissions that make the delay binding. List recovery actors and the exact capabilities they retain. These records answer different questions and should not be replaced with a screenshot of the proposal page.

Keep proposal approval separate from execution success. A passed vote can coexist with an unexecutable target call; a Ready operation can coexist with an unavailable executor. An operational status needs enough detail for the accountable actor to resolve the actual dependency without silently weakening authorization.

Review the record when role holders, target implementations or governance extensions change. The constructor's initial grants no longer establish current permissions after later role transactions. Reconstruct the current configuration at an identified block and preserve unknown reads as missing evidence.

Role removal also has distinct paths. The pinned access-control source requires administrator authority for revocation, while renunciation requires confirmation of the caller's own address. Rehearse the intended removal transaction and verify membership afterward. A plan saying that an actor will give up authority should identify which function that actor can actually use and which remaining administrator can restore it.

Our measured boundary is that 12 of 24 Ready cases failed modeled authorization or predecessor checks. It demonstrates why readiness cannot be an execution guarantee. The final release decision needs source-specific target tests and a closed authority graph, with the remaining liveness assumptions assigned to named operators.

Reconstructing the current role population requires a defined method. The pinned base AccessControl implementation does not enumerate all role members on-chain. Its documentation directs users toward event evidence for that task. Build a candidate actor set from RoleGranted and RoleRevoked events from deployment through the selected block, then verify those candidates with hasRole at the same block.

Check getRoleAdmin as well as membership. An actor with role-administration authority can change the future population even if it currently holds no proposer or executor role. Include the bootstrap administrator, the timelock itself and the zero address used for an open executor grant. These are distinct authority relationships, not one list of transaction signers.

Incomplete event history is missing evidence. A provider that omits early ranges, a constructor configuration that was never reviewed or an incomplete candidate address list cannot support a statement that no additional role holders exist. Preserve the coverage boundaries and compare reconstructed events with current queries before issuing a role-closure conclusion.

The observation method should identify the block hash and chain along with the contract. Role activity after that block is a new state, not a contradiction of a properly bounded earlier record. The monitoring owner should know which grants, revocations or administrator changes trigger renewed review. A static screenshot cannot carry that change policy.

Finally, a complete timelock role population does not close the target authority graph. Repeat the privileged-route inventory for the target, proxy administrator and any governance extension that can change access. An accurate timelock record can coexist with an unreviewed direct target owner. The final evidence packet must connect the records before it claims that the delay binds the protected action.

Frequently asked questions

Does a timelock require a Governor contract?

No. The cited implementation can be used with or without a Governor. Its scheduling and execution permissions still need an explicitly approved authority arrangement.

Does the minimum delay choose a safe voting period?

It constrains scheduling in the timelock implementation. Voting duration and proposal policy belong to the surrounding governance design and require their own rationale.

Can monitoring a proposal replace reviewing its decoded payload?

Monitoring can report state changes and alert an operator. It does not establish that the queued target, value and calldata implement the approved decision.

Comments

0

    Leave a comment

    Share a question or observation about this article.

    10 to 3,000 characters.