> For the complete documentation index, see [llms.txt](https://docs.trilobyte.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trilobyte.finance/technical-documentation/timelock-contract.md).

# Timelock Contract

OpenZeppelin Timelock Controller (Stellar Contracts v0.7.2) for governance delay on critical protocol actions.

**Source:** `contracts/timelock/`

## Overview

The Timelock enforces a **minimum delay** on governance operations. Critical protocol changes (fee updates, asset whitelisting, contract upgrades) must be scheduled, wait for the delay to pass, and then be executed. This gives protocol participants time to review and react.

{% hint style="warning" %}
**Delays are measured in LEDGERS, not seconds.** OZ Timelock v0.7 measures `min_delay` and per-operation `delay` in ledger-sequence units (\~5 s/ledger). A 1-day delay is therefore \~17 280 ledgers, not `86400`.
{% endhint %}

## Operation Lifecycle

```
Unset → Waiting → Ready → Done
```

| State       | Description                                           |
| ----------- | ----------------------------------------------------- |
| **Unset**   | Operation doesn't exist yet                           |
| **Waiting** | Scheduled, waiting for the delay (in ledgers) to pass |
| **Ready**   | Delay has passed, can be executed                     |
| **Done**    | Successfully executed                                 |

## Roles

| Role          | Description                                                                                                                |
| ------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Proposer**  | Can schedule new operations with a delay. **Proposers are also automatically granted the Canceller role** at construction. |
| **Executor**  | Can execute operations once they are ready. **If no executors are configured, anyone can execute** ready operations.       |
| **Canceller** | Can cancel pending operations before execution                                                                             |
| **Admin**     | Can manage roles and update the minimum delay. By default the contract is its own admin (self-administered).               |

## Functions

| Function                                                                                                 | Role       | Description                                                                                              |
| -------------------------------------------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------- |
| `schedule_op(target, function, args, predecessor, salt, delay, proposer)`                                | Proposer   | Schedule an operation; returns the operation id (hash). `delay` is in ledgers and must be ≥ `min_delay`. |
| `execute_op(target, function, args, predecessor, salt, executor)`                                        | Executor\* | Execute a ready operation (external targets). \*Anyone if no executors configured.                       |
| `cancel_op(operation_id, canceller)`                                                                     | Canceller  | Cancel a pending operation.                                                                              |
| `update_delay(new_delay)`                                                                                | Admin      | Update the minimum delay (self-administered → goes through the timelock).                                |
| `get_min_delay()`                                                                                        | —          | Current minimum delay (ledgers).                                                                         |
| `hash_operation(...)`                                                                                    | —          | Compute an operation's id.                                                                               |
| `get_operation_state(id)`                                                                                | —          | Returns the `OperationState`.                                                                            |
| `operation_exists(id)` / `is_operation_pending(id)` / `is_operation_ready(id)` / `is_operation_done(id)` | —          | State predicates.                                                                                        |

The Timelock also exposes the OZ `AccessControl` interface (`grant_role`, `revoke_role`, `has_role`, …).

## Integration with Globals

The Timelock is set as the **admin** of the Globals contract during deployment (via the two-step `transfer_admin_role` / `accept_admin_transfer`). This means:

* All admin-gated functions on Globals (`whitelist_asset`, `set_factory`, `upgrade`, etc.) require Timelock authorisation
* To change such a parameter, a Proposer schedules the operation, waits for the delay (in ledgers), then an Executor executes it
* This prevents instant, unilateral changes to critical protocol parameters

{% hint style="info" %}
`ops_adm`-gated functions on Globals (fees, settings, pool-manager approval, delinquency) are **not** routed through the Timelock — they are gated by the operations-admin role directly.
{% endhint %}

## Self-Administered

The Timelock is deployed **self-administered** (admin `None` → the contract is its own admin):

* No single external address can bypass the time delay
* The Timelock's own settings (minimum delay, roles) can only be changed through the Timelock itself, via the `CustomAccountInterface` self-admin path
* This creates a fully decentralised governance loop

## Deployment

```
__constructor(min_delay, proposers, executors, admin: None)
```

* `min_delay` — Minimum number of **ledgers** between scheduling and execution
* `proposers` — Addresses that can schedule operations (also granted the canceller role)
* `executors` — Addresses that can execute ready operations (empty ⇒ anyone can execute)
* `admin: None` — Self-administered (no external admin)

{% hint style="warning" %}
Upgrading the timelock WASM changes the operation storage key, so any operations scheduled under a prior version are dropped. Drain in-flight operations before upgrading a live timelock.
{% endhint %}

## Test Coverage

14 tests covering:

* Operation lifecycle (schedule → ready → execute)
* Cancellation before execution
* Delay enforcement (in ledgers)
* Role-based access control (incl. proposer-auto-canceller and open-execution-when-no-executors)
* Integration with the Globals contract (scheduling admin-gated operations)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.trilobyte.finance/technical-documentation/timelock-contract.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
