Skip to content
Merged
Changes from 59 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
ac5726d
timelock first steps
JereSalo Dec 16, 2025
5e341dd
improve some stuff and add comments
JereSalo Dec 16, 2025
6138e29
add one more comment about security council
JereSalo Dec 16, 2025
a2b631c
Deploy timelock contract and make it compile (not tested)
JereSalo Dec 16, 2025
06429f5
remove comments
JereSalo Dec 16, 2025
75968ed
commit and verify batches to Timelock instead of OnChainProposer
JereSalo Dec 16, 2025
ea206cb
add pause and unpause functions
JereSalo Dec 17, 2025
4e2ab15
change mindelay to 30 seconds for testing
JereSalo Dec 17, 2025
d390d97
add emergency execution for security council
JereSalo Dec 17, 2025
6516788
remove initialization of bridge address and transfer of ownership
JereSalo Dec 17, 2025
3545409
run cargo fmt
JereSalo Dec 17, 2025
6a41d67
fix solidity lint in Timelock
JereSalo Dec 17, 2025
ad29f8a
use onlySelf modifier instead
JereSalo Dec 18, 2025
af1f5d7
merge main
JereSalo Dec 18, 2025
8a8df36
rename error in based contract
JereSalo Dec 18, 2025
a5c12c7
require timelock address to be set if it's not based
JereSalo Dec 18, 2025
9e740c4
make tiny changes
JereSalo Dec 18, 2025
f697e23
deploy timelock only on non-based
JereSalo Dec 18, 2025
e4dd641
improve comments in timelock contract
JereSalo Dec 18, 2025
43589a8
add comments to Timelock contract
JereSalo Dec 18, 2025
1e6c0b2
rename owner to governance
JereSalo Dec 18, 2025
89bc0ba
Merge branch 'main' into timelock_l2
JereSalo Dec 18, 2025
1369951
disable initialize function from TimelockControllerUpgradeable
JereSalo Dec 18, 2025
a16cd29
Merge branch 'timelock_l2' of github.com:lambdaclass/ethrex into time…
JereSalo Dec 18, 2025
7edc1e0
Make Timelock inherit IOnChainProposer
JereSalo Dec 18, 2025
f68872f
let security council upgrade vks
JereSalo Dec 18, 2025
aa731cf
add timelock docs (first draft)
JereSalo Dec 18, 2025
90d7add
try fix timelock bug
JereSalo Dec 19, 2025
21a4d5d
add Clone
JereSalo Dec 19, 2025
f8bce2a
run cargo fmt
JereSalo Dec 19, 2025
fa3c723
make tdx contract point to the timelock and this one implements autho…
JereSalo Dec 19, 2025
3e6b14b
cargo fmt
JereSalo Dec 19, 2025
4442465
Add authorizedSequencerAddresses to interface and implement it as del…
JereSalo Dec 19, 2025
f3b40dd
rename owner to timelock_owner
JereSalo Dec 19, 2025
da63fe6
tidy and improve Timelock contract, create interface
JereSalo Dec 19, 2025
1c33ced
use proper errors in timelock
JereSalo Dec 19, 2025
2681bb2
use let some instead
JereSalo Dec 19, 2025
a56ece8
Keep track of the nonce after deploying
JereSalo Dec 19, 2025
5d8747b
deprecate variable in comment
JereSalo Dec 19, 2025
97f99c0
remove invalid override
JereSalo Dec 19, 2025
0bde3eb
add comment to ocp initialize
JereSalo Dec 19, 2025
d35c56b
Revert "Keep track of the nonce after deploying"
JereSalo Dec 19, 2025
790111f
Merge branch 'main' into timelock_l2
JereSalo Dec 20, 2025
f6e02d7
rename authorizedSequencerAddresses to isSequencer
JereSalo Dec 22, 2025
0b63415
move errors to timelock interface
JereSalo Dec 22, 2025
a02e8e5
ci(l2): fix TDX CI for timelock PR (#5698)
JereSalo Dec 22, 2025
44344bc
add notice
JereSalo Dec 23, 2025
73b8c1c
add address check for bridge
JereSalo Dec 23, 2025
c6fab46
merge main
JereSalo Dec 23, 2025
36282af
add comment in proof sender and verifier
JereSalo Dec 23, 2025
ec97946
fix stack too deep OnChainProposer
JereSalo Dec 23, 2025
eefbc73
add dev to comment in OCP
JereSalo Dec 23, 2025
16b54cc
remove auxiliary initializers
JereSalo Dec 23, 2025
c9bb9b9
Merge branch 'main' into timelock_l2
ManuelBilbao Jan 5, 2026
f8d4fa4
add upgrades docs
JereSalo Jan 5, 2026
6443ff9
Unify migrations and upgrades and correct READMe and SUMMARY accordingly
JereSalo Jan 5, 2026
fbba982
Merge branch 'timelock_l2' into add_timelock_docs
ManuelBilbao Jan 6, 2026
0ce1de2
Merge branch 'main' into add_timelock_docs
ManuelBilbao Jan 6, 2026
cde3994
grammar fixes and small corrections
JereSalo Jan 6, 2026
335b24b
Make changes based on copilot suggestions
JereSalo Jan 6, 2026
f399583
Update docs/l2/fundamentals/timelock.md
JereSalo Jan 6, 2026
5ffd8bf
Update docs/l2/fundamentals/timelock.md
JereSalo Jan 6, 2026
90626af
Merge branch 'main' into add_timelock_docs
ManuelBilbao Jan 6, 2026
0fe7353
Merge branch 'main' into add_timelock_docs
ManuelBilbao Jan 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions docs/l2/fundamentals/timelock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Timelock Contract

The Timelock contract gates access to the OnChainProposer (OCP) contract. One can only make changes in the OCP by interacting first with the Timelock, which manages permissions based on roles assigned to different users.

## Timelock Roles

- Sequencers: Can commit and verify batches.
- Governance: Can schedule and execute operations, respecting a delay. In practice this could be the role of a DAO, though it depends on the implementation.
- Security Council: Can bypass the minimum delay for executing any operation that the Timelock can execute.

**Sequencers** will send `commitBatch`, `verifyBatch`, and `verifyBatchesAligned` to the Timelock, and the Timelock will execute the operations in the `OnChainProposer`. Eventually there will be Timelock logic, and there will be a time window between commitment and proof verification for security reasons.

The **Governance** is able to schedule important operations like contract upgrades respecting the minimum time window for the L2 participants to exit in case of undesired updates. Not only can they make changes in the logic of the OnChainProposer, but they can also update the Timelock itself.

The **Security Council** is designed as a powerful entity that can execute anything within the Timelock or OnChainProposer without delay. We call it security council because its actions are limitless, as they can upgrade any of the contracts whenever they want, so ideally it should be a multisig composed of many diverse members, and they should be able to take action only if 75% of them agree. Ideally, in a more mature rollup the Security Council would have less permissions and would only need to act upon bugs detected on-chain if such a mechanism exists.
We call this mechanism of executing without delay the `emergencyExecute`.


## Basic Functionalities

These are the things that we can do with the Timelock:
- Schedule: `schedule(...)` and `scheduleBatch(...)`
- Execute: `execute(...)` and `executeBatch(...)`
- Cancel: `cancel(bytes32 id)`
- Update Delay: `updateDelay(uint256 newDelay)`

When an operation is **scheduled** it can be **canceled** or, after the established delay, it can be **executed** by the Governor.
The delay can be updated, always respecting the current delay to do so.

It also has a few utility functions:
- `getMinDelay()`: current minimum delay for new schedules.
- `hashOperation(...)`, `hashOperationBatch(...)`: pure helpers to compute ids.
- `getTimestamp(id)`, `getOperationState(id)`, `isOperation*`: query operation status.

Remember that `Timelock` is `AccessControl` and `UUPSUpgradeable`, so it will inherit their behavior as well.

## Important Remarks

### Operation ID collision

Every scheduled operation is identified by a 32-byte **operation id**. This ID is determined by hashing fields like the target address, value transferred, data, predecessor, and salt.
Two operations with the same fields will result in the same ID. That's why, if we want to schedule the same operation more than once, we should probably use a salt.
Example: If for some reason we want to schedule the pause of the OnChainProposer and we use salt zero, the next time we schedule that same operation we'll have to change the salt (assuming no predecessor was specified) in order for the id to be different.

### Cancelling a scheduled operation

`cancel(bytes32 id)` requires the operation id. You typically get it by:

1. Reading it from the `CallScheduled(id, ...)` event emitted by `schedule`/`scheduleBatch`, or
2. Computing it yourself (off-chain), or
3. Calling `hashOperation(...)` / `hashOperationBatch(...)` on-chain to compute it.

Note that:
- `hashOperation(...) = keccak256(abi.encode(target, value, data, predecessor, salt))`
- `hashOperationBatch(...) = keccak256(abi.encode(targets, values, payloads, predecessor, salt))`
Loading