|
| 1 | +--- |
| 2 | +title: "Govern with Timelocks" |
| 3 | +description: "Use OpenZeppelin timelocks to make Warp Route and chain governance safer" |
| 4 | +--- |
| 5 | + |
| 6 | +Hyperlane contracts are commonly `Ownable` because teams need a way to expand to new chains, enroll routers, update ISMs, change hooks, tune rate limits, pause routes, or transfer ownership. For production systems, direct ownership by a hot key or even a multisig can still be risky: if the owner path is compromised, an attacker can execute privileged changes immediately. |
| 7 | + |
| 8 | +A governance timelock puts a delay between proposing an owner action and executing it. This gives your team, integrators, and monitors time to inspect the action and cancel it before it takes effect. |
| 9 | + |
| 10 | +## Who should use this |
| 11 | + |
| 12 | +Use timelock governance if you operate: |
| 13 | + |
| 14 | +- A Warp Route with meaningful TVL. |
| 15 | +- A chain's Hyperlane Mailbox or core deployment. |
| 16 | +- A route integrated by external protocols, lending markets, or risk teams. |
| 17 | +- A multisig or ICA setup where signers are not expected to make urgent owner changes. |
| 18 | + |
| 19 | +Timelocks are especially useful when governance actions are important but rarely time-sensitive. |
| 20 | + |
| 21 | +## How OpenZeppelin timelocks work |
| 22 | + |
| 23 | +Hyperlane tooling uses OpenZeppelin's [`TimelockController`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/TimelockController.sol). The timelock contract becomes the owner of the governed contract. |
| 24 | + |
| 25 | +An owner action then has two phases: |
| 26 | + |
| 27 | +1. A proposer schedules the exact call on the timelock. |
| 28 | +2. After `minimumDelay`, anyone with executor rights can execute that exact call. |
| 29 | + |
| 30 | +The operation includes the target contract, calldata, ETH value, predecessor, salt, and delay. The timelock hashes these fields into an operation ID, so the executed transaction must match what was scheduled. |
| 31 | + |
| 32 | +## Roles |
| 33 | + |
| 34 | +| Role | What it can do | Recommended setup | |
| 35 | +|---|---|---| |
| 36 | +| `PROPOSER_ROLE` | Schedule operations | Governance Safe on the owner chain, or its ICA on remote chains | |
| 37 | +| `EXECUTOR_ROLE` | Execute ready operations | `address(0)` for permissionless execution | |
| 38 | +| `CANCELLER_ROLE` | Cancel pending operations | Operational vetoer, deployer key, security council, or governance-controlled address | |
| 39 | +| `TIMELOCK_ADMIN_ROLE` | Manage roles | Use carefully; avoid leaving this on a hot deployer key | |
| 40 | + |
| 41 | +Permissionless execution is usually desirable. Once a valid proposal has waited through the delay, anyone can execute it, so liveness does not depend on the proposer returning online. |
| 42 | + |
| 43 | +## Why it is safer |
| 44 | + |
| 45 | +Without a timelock, a compromised owner can immediately change sensitive configuration. For a Warp Route, that could mean replacing the ISM, changing ownership, altering limits, or weakening safety controls. |
| 46 | + |
| 47 | +With a timelock: |
| 48 | + |
| 49 | +- The malicious or mistaken action is visible before execution. |
| 50 | +- Watchers can decode and review the scheduled calldata. |
| 51 | +- A configured canceller can veto the operation. |
| 52 | +- Integrators get time to react before the change takes effect. |
| 53 | +- ICA-based governance is less brittle because a bad ICA message can schedule an action, but cannot execute it immediately. |
| 54 | + |
| 55 | +Timelocks do not replace good key management, good ISM design, or monitoring. They add an observation and cancellation window around owner actions. |
| 56 | + |
| 57 | +## Hyperlane setup |
| 58 | + |
| 59 | +A typical setup uses one governance Safe on an owner chain, usually Ethereum, and one timelock on each chain where contracts are governed. |
| 60 | + |
| 61 | +```mermaid |
| 62 | +flowchart LR |
| 63 | + subgraph OwnerChain["Owner chain, usually Ethereum"] |
| 64 | + Safe["Governance Safe"] |
| 65 | + OwnerTimelock["Owner-chain TimelockController"] |
| 66 | + OwnerContract["Governed contract"] |
| 67 | + end |
| 68 | +
|
| 69 | + subgraph RemoteChain["Remote EVM chain"] |
| 70 | + ICA["Interchain Account"] |
| 71 | + RemoteTimelock["Remote TimelockController"] |
| 72 | + RemoteContract["Governed contract"] |
| 73 | + end |
| 74 | +
|
| 75 | + Safe -->|"schedule directly"| OwnerTimelock |
| 76 | + OwnerTimelock -->|"owns and later executes"| OwnerContract |
| 77 | +
|
| 78 | + Safe -->|"send ICA message"| ICA |
| 79 | + ICA -->|"schedule"| RemoteTimelock |
| 80 | + RemoteTimelock -->|"owns and later executes"| RemoteContract |
| 81 | +
|
| 82 | + Canceller["Canceller / vetoer"] -. "cancel pending operation" .-> OwnerTimelock |
| 83 | + Canceller -. "cancel pending operation" .-> RemoteTimelock |
| 84 | + Executor["Anyone, after delay"] -. "execute ready operation" .-> OwnerTimelock |
| 85 | + Executor -. "execute ready operation" .-> RemoteTimelock |
| 86 | +``` |
| 87 | + |
| 88 | +On the owner chain: |
| 89 | + |
| 90 | +- The governed contract is owned by the timelock on that same chain. |
| 91 | +- The governance Safe has `PROPOSER_ROLE` on that timelock. |
| 92 | +- The Safe schedules actions directly on the timelock. |
| 93 | + |
| 94 | +On each remote EVM chain: |
| 95 | + |
| 96 | +- The governed contract is owned by a timelock on that remote chain. |
| 97 | +- The proposer is an Interchain Account (ICA) on that remote chain. |
| 98 | +- That ICA is controlled by the governance Safe on the owner chain. |
| 99 | +- The Safe sends an ICA message, and the ICA schedules the action on the remote timelock. |
| 100 | + |
| 101 | +The flow for a remote owner action is: |
| 102 | + |
| 103 | +1. The owner-chain Safe creates an ICA transaction. |
| 104 | +2. The ICA schedules the action on the remote chain's timelock. |
| 105 | +3. The action waits for the configured delay, which should be at least 1 day. |
| 106 | +4. If the proposal is bad, a canceller calls `cancel`. |
| 107 | +5. If the proposal is valid, anyone executes the queued operation after the delay. |
| 108 | + |
| 109 | +For Ethereum-local actions, the Safe can schedule directly on the Ethereum timelock without using an ICA. |
| 110 | + |
| 111 | +## Example |
| 112 | + |
| 113 | +Suppose a Warp Route on Base is owned by a Base timelock. The timelock has: |
| 114 | + |
| 115 | +- `PROPOSER_ROLE`: the Ethereum Safe's ICA on Base. |
| 116 | +- `EXECUTOR_ROLE`: `address(0)`. |
| 117 | +- `CANCELLER_ROLE`: an operational vetoer or security council address. |
| 118 | +- `minimumDelay`: at least `86400` seconds. |
| 119 | + |
| 120 | +To update the route ISM, the Ethereum Safe does not call the route directly. It sends an ICA call that schedules: |
| 121 | + |
| 122 | +```solidity |
| 123 | +warpRoute.setInterchainSecurityModule(newIsm); |
| 124 | +``` |
| 125 | + |
| 126 | +on the Base timelock. The call can only be executed after the delay, and only if it has not been cancelled. |
| 127 | + |
| 128 | +## Submitter strategy |
| 129 | + |
| 130 | +When you deploy or update your own Warp Route with the Hyperlane CLI, pass a submitter strategy so the CLI knows how to submit owner transactions. If your route is owned by a timelock, use a `timelockController` submitter strategy. |
| 131 | + |
| 132 | +The strategy wraps route updates in `scheduleBatch` and returns the later `executeBatch` transaction. This lets `warp apply` propose the update through the timelock instead of trying to call the owned contract directly. |
| 133 | + |
| 134 | +Example remote-chain strategy: |
| 135 | + |
| 136 | +```yaml |
| 137 | +base: |
| 138 | + submitter: |
| 139 | + type: timelockController |
| 140 | + chain: base |
| 141 | + timelockAddress: "0x..." |
| 142 | + proposerSubmitter: |
| 143 | + type: interchainAccount |
| 144 | + chain: ethereum |
| 145 | + destinationChain: base |
| 146 | + owner: "0x..." # Ethereum Safe |
| 147 | + internalSubmitter: |
| 148 | + type: gnosisSafeTxBuilder |
| 149 | + chain: ethereum |
| 150 | + safeAddress: "0x..." |
| 151 | + version: "1.0" |
| 152 | +``` |
| 153 | +
|
| 154 | +Example owner-chain strategy: |
| 155 | +
|
| 156 | +```yaml |
| 157 | +ethereum: |
| 158 | + submitter: |
| 159 | + type: timelockController |
| 160 | + chain: ethereum |
| 161 | + timelockAddress: "0x..." |
| 162 | + proposerSubmitter: |
| 163 | + type: gnosisSafeTxBuilder |
| 164 | + chain: ethereum |
| 165 | + safeAddress: "0x..." |
| 166 | + version: "1.0" |
| 167 | +``` |
| 168 | +
|
| 169 | +## What Hyperlane already provides |
| 170 | +
|
| 171 | +The Hyperlane monorepo includes: |
| 172 | +
|
| 173 | +- An OpenZeppelin `TimelockController` deployment wrapper. |
| 174 | +- SDK support for deploying and reading EVM timelocks. |
| 175 | +- Submitter support for `timelockController` strategies. |
| 176 | +- ICA submitter nesting, so a Safe can propose on remote timelocks through ICAs. |
| 177 | +- Scripts to list pending timelock operations and cancel them. |
| 178 | + |
| 179 | +Abacus Works and Regular governance configurations already use this pattern for many EVM chains: Ethereum uses a Safe-controlled timelock, and remote chains use ICA-proposed timelocks. |
| 180 | + |
| 181 | +## Operational guidance |
| 182 | + |
| 183 | +- Use a delay long enough for monitoring and human review. The minimum recommended delay is 1 day. |
| 184 | +- Keep execution permissionless unless you have a specific reason not to. |
| 185 | +- Give cancellation rights to parties that can respond quickly. |
| 186 | +- Monitor `CallScheduled`, `CallExecuted`, and `Cancelled` events on every timelock. |
| 187 | +- Document who can propose, who can cancel, and how emergency cancellation works. |
| 188 | +- Avoid using a timelock for actions that must execute immediately during an incident. |
| 189 | + |
| 190 | +For many teams, the recommended production owner is not a Safe directly, but a timelock whose proposer is the Safe or the Safe's ICA. |
0 commit comments