A timelock is the contract that holds the powers a governance vote can exercise and refuses to apply a passed proposal until a fixed delay has run. The governor counts the votes; the timelock holds the keys and the clock. The delay is there so that anyone who disagrees with the outcome can read the queued calldata and get out before it lands.
The delay protects users, not the protocol. It does not stop a bad proposal from passing. What it does is put a published, machine-readable description of exactly what is about to happen between the vote and the change, plus time to act on it.
The governor decides, the timelock owns
In the reference architecture the governor runs the vote and queues the winning call somewhere else. OpenZeppelin states the ownership rule flatly: with a timelock extension in place, proposals are executed by the external timelock contract, so it is the timelock that has to hold the assets being governed.1 The governor holds no funds.
That split is the point. OpenZeppelin describes TimelockController as a module that, set as the owner of an Ownable contract, enforces a delay on all owner-only maintenance operations, giving users of the controlled contract time to exit before a potentially dangerous operation is applied.1 If your governor owns the treasury directly and a timelock sits beside it as decoration, you have the delay without the protection. Check which address holds the admin keys before you trust the diagram.
The delay is a window with two edges
Compound's Timelock.sol is the implementation most protocols forked, and its constants are worth reading rather than paraphrasing. GRACE_PERIOD is 14 days, MINIMUM_DELAY is 2 days, MAXIMUM_DELAY is 30 days. Queuing sets an execution timestamp at least one delay out, and execution reverts below that timestamp or above it by more than the grace period, with the message that the transaction is stale.2
So the delay is not a floor with open sky above it. A passed proposal nobody executes inside those 14 days dies and goes back through the vote. That is an operations failure rather than a security one, and it catches teams who treat the vote as the finish line. Somebody owns execution. Write it down next to who owns proposing.
Scroll to see the full diagram
Roles are the part that gets misconfigured
OpenZeppelin's TimelockController splits one admin into three roles. PROPOSER_ROLE schedules operations, EXECUTOR_ROLE executes them once due, CANCELLER_ROLE kills a scheduled operation before it lands. The constructor grants CANCELLER_ROLE to every address it grants PROPOSER_ROLE, so the two sets are identical unless you change them after deployment.3
Two consequences follow. Executor can be granted to the zero address, making execution permissionless, so anyone can push a due operation through and no single operator can quietly sit on it. And updateDelay only accepts a call from the timelock itself, so shortening the delay is a proposal that has to serve the current delay first.3 A timelock that can shorten its own delay on demand is not a timelock.
OpenZeppelin's own docs flag the risk in stacking proposers: because proposers have a say over every operation, they can cancel operations they disagree with, including one that would remove them.1 Redundancy on that role is not free.
What the delay does not do
We went looking for a documented case in which a delay window was the recorded mechanism that let a community spot and cancel a malicious proposal, with a proposal identifier attached. We did not find one. Every source describing this benefit describes it as design intent.
That gap matters because a delay only works if somebody is watching the queue. Publishing calldata to an audience of nobody is not a control. With no monitoring on scheduled operations and no standing channel that reaches holders inside the delay, the mechanism is present in the contract and absent in practice.
Choosing the number
The delay should be at least as long as it takes your slowest relevant party to notice a queued change and act. For a lending market that means the largest borrower unwinding a position, not a Discord message getting read. Two days is the floor in the widely forked implementation.2 Across the projects we have worked on, one flat delay for every action is usually the wrong shape: a parameter tweak and an implementation swap do not carry the same blast radius.
Then connect it back to the business. A long delay is a promise that users can leave before you change the rules on them, and that promise is worth something to the counterparties deciding whether to put size in your protocol. A short delay says you expect to move faster than your users can react. Pick deliberately, publish the reasoning, and treat any emergency path around the delay as a governance surface of its own.
Common questions
What is a timelock in a smart contract?
It is a contract that holds administrative powers and refuses to execute a scheduled call until a fixed delay has elapsed. In DAO governance the timelock owns the assets and contracts being governed, and the governor contract is granted the right to schedule operations on it.1 Between scheduling and execution the exact call is public on chain, which is the window in which holders can react.
How long should a governance timelock be?
Long enough for your slowest affected party to notice and act. The widely forked Compound implementation sets a minimum of 2 days and a maximum of 30, with a 14-day window to execute before the call goes stale.2 In our experience a single flat delay across every action is the wrong shape, because a parameter tweak and an implementation swap do not carry comparable risk.
Can a timelock be bypassed?
Only if the design allows it. Changing the delay on OpenZeppelin's TimelockController requires a call from the timelock itself, so a shorter delay has to serve the current delay first.3 The real bypasses are architectural: an emergency execution path that skips the queue, or an admin key that still holds the powers the timelock was supposed to own. Both are worth checking on chain rather than in documentation.
See Tokenomics Audit for how this applies in practice.
Sources
- Contracts 4.x API: Governance (Governor and TimelockController)
OpenZeppelin, 2023
Source for the rule that the timelock has to hold the assets being governed, the exit-window rationale for the delay, and the warning that multiple proposers can cancel operations they disagree with. - Timelock.sol, Compound Protocol
Compound Finance, GitHub, 2020
Read 3 August 2026. GRACE_PERIOD 14 days, MINIMUM_DELAY 2 days, MAXIMUM_DELAY 30 days. executeTransaction reverts below eta and above eta plus the grace period. - TimelockController.sol, OpenZeppelin Contracts
OpenZeppelin, GitHub, 2026
Read 3 August 2026. PROPOSER_ROLE, EXECUTOR_ROLE and CANCELLER_ROLE; the constructor grants CANCELLER_ROLE to every proposer; executors may include the zero address for open execution; updateDelay reverts unless the caller is the timelock itself.
Last reviewed 2026-08
Related terms
Know the terms but not sure how they apply to your project? That is what an engagement is for. We design, document, and stress-test the whole token economy inside the Tokenomics Data Room.
100+ projects advised. Complete tokenomics in 4 to 6 weeks.