> For the complete documentation index, see [llms.txt](https://docs.t-rex.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.t-rex.network/cross-chain-the-distributed-register/the-dual-state-lifecycle.md).

# The dual-state lifecycle

Separating authorization from execution creates a gap. Between the moment the reference chain authorizes a transfer and the moment it learns that the satellite executed it, the register and the satellite hold different views. The protocol manages that gap explicitly, by advancing two kinds of state at two different times, so that no inconsistent or non-compliant state ever exists.

This page follows a validation from issuance to its end. What the gap means for finality is covered in [Technical finality and legal finality](/the-primary-register/technical-finality-and-legal-finality.md).

## Two tracks

|                        | Compliance track                             | Ownership track                               |
| ---------------------- | -------------------------------------------- | --------------------------------------------- |
| **What it records**    | That a movement is authorized and may happen | That a movement has happened                  |
| **Advances**           | At issuance                                  | At settlement                                 |
| **Kind of commitment** | Soft: a reservation, which can be released   | Hard: a change of owner                       |
| **Read with**          | `pendingInOf`, `pendingOutOf`, `reservedOf`  | `positionOf`, `bridgedBalanceOf`, `balanceOf` |

Compliance is reserved early, so that the rules stay sound under concurrency. Ownership moves late, so that the register records only what has occurred.

```mermaid
flowchart TB
    I["Validation issued"] --> C1["Compliance track:<br/>amount reserved, counted by every rule"]
    I --> O1["Ownership track:<br/>unchanged"]
    C1 --> E{"Executed on the satellite<br/>and reported?"}
    O1 --> E
    E -- "yes" --> C2["Reservation released"]
    E -- "yes" --> O2["Ownership moves,<br/>for the executed amount"]
    E -- "never" --> C3["Reservation released<br/>by the keeper"]
    E -- "never" --> O3["Unchanged: nothing to undo"]
```

### Why the reservation is needed

An asset caps its holders at 100 identities and has 99. Two buyers, neither of them a holder yet, are each the recipient of a transfer on a satellite, requested at the same moment.

* **Without a reservation**, both requests see 99 holders and both are authorized. Both execute. The asset has 101 holders.
* **With it**, the first validation counts its recipient as a holder from the moment it is issued. The second request sees the limit reached and is refused.

Neither transfer has executed when the second request is refused. The rule already holds.

## The states of a validation

```mermaid
stateDiagram-v2
    [*] --> Pending: issued
    Pending --> Settled: the only chain involved reports
    Pending --> AwaitingMint: the sending chain reports first
    Pending --> AwaitingBurn: the receiving chain reports first
    AwaitingMint --> Settled: the receiving chain reports
    AwaitingBurn --> Settled: the sending chain reports
    Pending --> Discarded: discarded by the keeper
    Discarded --> LateReconciled: reported after the discard
    AwaitingMint --> Resolved: resolved by the keeper
    AwaitingBurn --> Resolved: resolved by the keeper
    Settled --> [*]
    LateReconciled --> [*]
    Resolved --> [*]
```

| Status                                           | Meaning                                                                                                                                    |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `Pending`                                        | Issued. The amount is reserved. No settlement has arrived.                                                                                 |
| `AwaitingMint`                                   | Transfer between two satellites: the sending chain reported its burn. The amount is held in transit. The receiving chain has not reported. |
| `AwaitingBurn`                                   | Transfer between two satellites: the receiving chain reported its mint. The sending chain has not reported.                                |
| `Settled`                                        | Every expected report arrived. Ownership moved. Nothing is reserved.                                                                       |
| `Expired`                                        | `Pending` and past the release time. This status is computed when read. It is never stored.                                                |
| `Discarded`                                      | The keeper gave up on it and released the reservation.                                                                                     |
| `DiscardedAwaitingMint`, `DiscardedAwaitingBurn` | Discarded, then one of two reports arrived late. The other is still owed.                                                                  |
| `LateReconciled`                                 | Every report arrived after the discard. The movement was applied anyway.                                                                   |
| `Resolved`                                       | The keeper gave up on a transfer between two satellites of which only one report ever arrived.                                             |

`statusOf(validationId)` returns the status. `validationOf(validationId)` returns the full record.

### What is reserved in each state

| Status                                               | Pending amounts of the two identities | Reservation on the sending wallet | Amount in transit |
| ---------------------------------------------------- | ------------------------------------- | --------------------------------- | ----------------- |
| `Pending`, `Expired`                                 | Reserved                              | Reserved                          | None              |
| `AwaitingMint`                                       | Reserved                              | Replaced by the amount in transit | Held              |
| `AwaitingBurn`                                       | Reserved                              | Reserved                          | None              |
| `DiscardedAwaitingMint`                              | Released                              | Released                          | Held              |
| `DiscardedAwaitingBurn`                              | Released                              | Released                          | None              |
| `Settled`, `Discarded`, `LateReconciled`, `Resolved` | Released                              | Released                          | None              |

What is reserved is derived from the status, not stored next to it. The two cannot disagree, and a reservation is released exactly once.

## Two deadlines

```mermaid
flowchart LR
    T0["Issued"] -->|"validity window"| T1["expiry"]
    T1 -->|"reconciliation window"| T2["releaseAt"]
    T2 -->|"same window again"| T3["A stuck transfer between<br/>two satellites can be resolved"]
```

| Deadline    | Enforced by         | Meaning                                                                                  |
| ----------- | ------------------- | ---------------------------------------------------------------------------------------- |
| `expiry`    | The satellite       | The transfer must execute strictly before it.                                            |
| `releaseAt` | The reference chain | `expiry` plus the reconciliation window. Until then, the reservation cannot be released. |

The reconciliation window is set per satellite. It covers the worst case for that chain to finalize a transaction and for its notification to arrive. The reference chain does not give up on a validation at its expiry. It waits one window longer. A transfer that executed just before its expiry is therefore settled before the reference chain would consider releasing its reservation. A genuine execution never races a rollback.

The window is governed configuration, set conservatively for each satellite by the `COMPLIANCE_MANAGER`.

## Settlement

When a settlement notification arrives, the register checks it against the validation it issued. The checks have three possible outcomes.

| Check                                                                                                      | If it fails                                                        |
| ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| The message comes through a gateway the network trusts, and through the gateway the validation went out by | The message is rejected.                                           |
| Its author is the asset's T-REX Lite on that chain                                                         | The message is rejected.                                           |
| The wallets and the origin chain are those of the validation                                               | The delivery reverts. The message can be delivered again.          |
| The amount is inside the issued range                                                                      | The delivery reverts.                                              |
| For the second of two reports: the amount equals the first                                                 | The delivery reverts.                                              |
| The validation was issued, and this report was not already applied                                         | Nothing is applied and the token pauses itself. See "Emergencies". |

When every check passes and the movement is complete, the register does four things in one transaction: it releases the reservation, moves the positions of the two identities by the executed amount, updates the token's bridged ledger, and tells the tracker modules.

A settlement is accepted for a `Pending` validation whatever the clock says. Until the keeper has discarded it, an expired validation still settles normally.

### Transfers between two satellites

Two chains cannot act atomically. The sending chain destroys the tokens on its side first, and sends a proof of the burn to the receiving chain, which creates them on its side. Each reports its own half to the reference chain. The two reports travel separately, so the register accepts them in either order.

* **The burn arrives first.** It proves the tokens are gone from the sender's wallet. The register takes the amount out of that wallet's bridged position and holds it in transit. The sender's identity still owns it. Status `AwaitingMint`.
* **The mint arrives first.** Nothing moves yet. Status `AwaitingBurn`.
* **The second report arrives.** It must carry the same amount. The register applies the whole movement at once. Status `Settled`.

Once one report has arrived, the validation can no longer be discarded. One satellite has executed its half, irreversibly.

## When nothing arrives

A validation that is never executed must release its reservation, or it would block others indefinitely.

Release is never automatic. Past `releaseAt`, the status reads `Expired`, and the reservation stays in place until the Validation Keeper calls `discardExpiredValidations` for it. The discard releases the reservation, and issuance continues as if the validation had never existed. Nothing is undone on the ownership track, because nothing had moved.

The keeper is a restricted role, by design. Discarding is what turns a slow settlement into a late one, and a late settlement can stop a chain from issuing. That power is not given to everyone. The T-REX Network operates the keeper, and an Issuer grants it the `VALIDATION_KEEPER` role for its asset.

## When a settlement arrives late

A settlement can arrive after its validation was discarded: the satellite executed in time, and the notification took longer than the window.

The register applies it, always, even when the result breaches a rule of the asset. The execution on the satellite is final, and nothing on the reference chain can undo it. Refusing the settlement would make the register wrong, and satellites could not rely on finality if the reference chain could reject what they executed. A state that breaches a rule is resolved by the Issuer of the asset, not by rejecting the settlement.

| The register                                                        | Why                                                                       |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Applies the movement, status `LateReconciled`                       | The record must reflect what happened.                                    |
| Emits `LateReconciliation`                                          | Every late settlement is visible.                                         |
| Checks whether the executed amount exceeds what the rules allow now | The reservation was released, so other movements may have used the room.  |
| Pauses the issuance of validations for that chain, if it does       | No further transfer is authorized there until someone has looked into it. |

A late settlement that breaches nothing does not pause the chain. Late delivery is easy to cause, and pausing on it alone would let anyone stop a satellite. The `COMPLIANCE_MANAGER` lifts the pause once the exception is resolved.

## When half a transfer is stuck

A transfer between two satellites can stay with one report forever, if the other chain never reports. The keeper resolves it with `resolveStuckValidation`, after a second reconciliation window past `releaseAt`, so that a report that is merely slow still arrives as a late reconciliation.

| The report that arrived | What the resolution does                                                                                                                                                                                                 |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| The burn                | The amount held in transit returns to the wallet it was burned from. Whatever is still reserved is released.                                                                                                             |
| The mint                | Nothing on the reference chain can be returned. The burn happened, since the receiving chain minted against its proof, and its report is missing. The sending chain is paused for issuance, and the Issuer investigates. |

The status becomes `Resolved`. A report that arrives after that is treated as an emergency.

A resolution closes the validation on the register. It does not change what the satellites executed. The Issuer establishes what happened on each satellite and brings the register and the satellites back in line.

## Emergencies

Two situations mean that a trusted gateway delivered something the protocol cannot account for.

* A settlement for a validation that was never issued.
* A settlement whose report was already applied, or whose validation was already resolved.

Neither is applied. The compliance emits `ReplayedSettlement` and the token pauses itself. Every movement between holders stops until an agent has investigated and lifted the pause. While the token is paused, settlements are not applied: their delivery reverts and they remain deliverable.

## What can stop, and who restarts it

| What stops                                | Triggered by                                                                                                       | Lifted by                                      |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------- |
| Issuance of validations for one satellite | A late settlement that breaches a rule. A stuck transfer of which only the mint arrived. The `COMPLIANCE_MANAGER`. | `COMPLIANCE_MANAGER`, with `setIssuancePaused` |
| The whole token                           | A replayed or unknown settlement. The `AGENT_PAUSER`.                                                              | `AGENT_PAUSER`, with `unpause`                 |
| One validation                            | The keeper's discard, after `releaseAt`                                                                            | Nothing. The holder requests a new validation. |


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.t-rex.network/cross-chain-the-distributed-register/the-dual-state-lifecycle.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
