> 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/token-and-register/the-compliance-ledger.md).

# The compliance ledger

The token knows balances per address. An investor holds tokens at several addresses, on the reference chain and on satellites, and every rule about the distribution of an asset asks about the investor, not about one address. The compliance therefore keeps its own ledger: what each identity owns in total, and what is promised to it and from it by movements that have not settled. Compliance modules read these numbers. They do not rebuild them.

## What the ledger keeps

| Read                     | Meaning                                                                                                                                  |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `positionOf(identity)`   | What the identity owns in total: free, frozen and bridged, over its own address and every wallet linked to it, revoked wallets included. |
| `pendingInOf(identity)`  | What open cross-chain validations promise to the identity.                                                                               |
| `pendingOutOf(identity)` | What open cross-chain validations promise out of the identity.                                                                           |
| `ownerOf(address)`       | The identity under which the tokens of an address on the reference chain are counted.                                                    |
| `positionGap()`          | The difference between the supply and the sum of all positions. Zero in normal operation.                                                |

All are functions of the `ModularCompliance`, declared in `IComplianceLedger`. Nothing outside the compliance writes them.

One number of the same family is kept by the token, next to the balance it reserves against: `reservedOf(wallet)`, what open validations may still draw from one satellite wallet.

## How it is kept

The ledger is updated from the calls the token already makes to its compliance after every movement. No one calls anything extra.

```mermaid
flowchart LR
    M["A movement is recorded by the token"] --> R["The compliance resolves<br/>the identity of each side"]
    R --> Q{"Same identity<br/>on both sides?"}
    Q -- "yes" --> N["No position changes"]
    Q -- "no" --> P["Sender's position down<br/>Recipient's position up"]
    N --> T["TRACKER modules are told"]
    P --> T
```

| Movement                                         | Effect on positions                                                                        |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| Mint                                             | The recipient's identity goes up.                                                          |
| Burn                                             | The holder's identity goes down.                                                           |
| Transfer, forced transfer                        | The sender's identity goes down, the recipient's goes up.                                  |
| Transfer between two addresses of one identity   | None.                                                                                      |
| Recovery of a lost wallet                        | None. The position stays with the same identity.                                           |
| Delegation-out, recall                           | None. The position changes place, not owner.                                               |
| Settlement of a transfer executed on a satellite | The sender's identity goes down, the recipient's goes up, by the amount that was executed. |

The rule behind the table: a position moves when ownership moves, and only then.

## Pending amounts

A transfer on a satellite is authorized before it is executed and recorded after. During that time the position has not moved, but the rules must already count the movement, or two transfers authorized at the same moment could jointly breach a limit.

When a validation is issued, the compliance adds its maximum amount to `pendingOutOf` of the sender's identity and to `pendingInOf` of the recipient's identity. When the validation settles or is discarded, both are released.

| A rule that                            | Reads                                         |
| -------------------------------------- | --------------------------------------------- |
| Caps what an identity may acquire      | `positionOf` + `pendingInOf` of the recipient |
| Requires an identity to keep a minimum | `positionOf` - `pendingOutOf` of the sender   |

The maximum amount of the validation is used, because it is the worst case for any rule that adds amounts up. A movement between two addresses of one identity reserves nothing: relocating one's own tokens never uses up one's own room.

## The ledger and the supply

The ledger satisfies one equation at all times:

`sum of all positions + positionGap = totalSupply`

`positionGap` is zero as long as every address that holds tokens resolves to the identity that owns them. That is the normal state, and the protocol is built to keep it:

* An investor cannot break it. A wallet keeps resolving to its identity after its owner revokes it.
* A circulating token cannot change its registry or its compliance.

## Following the registry

One actor can change what an address resolves to while it holds tokens: a Registry Agent, by changing or deleting the local registration of that address. The ledger keeps up on its own.

* **It remembers.** For each address on the reference chain, the ledger records the identity it last credited, readable with `ownerOf`.
* **It follows a change.** When an agent registers the address under another identity, the next movement through that address first moves the address's whole balance from the old identity to the new one, then counts the movement. The event `WalletOwnerChanged` records it.
* **It keeps the last owner.** When an agent deletes the registration and nothing else names the address, the remembered identity still answers. The position does not disappear.

## The gap, and how it is closed

Two situations leave an amount that the ledger cannot attribute.

| Situation                                                                                                                                                                      | What the ledger does                                                          | Event                |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- | -------------------- |
| Tokens land on an address that the ledger has never credited and that resolves to no identity. This is only possible when the eligibility checks of the registry are disabled. | Counts the amount in the gap, positive.                                       | `PositionUnresolved` |
| Tokens leave an address whose identity holds less in the ledger than the amount, after a registration was changed.                                                             | Takes what it can from the position and counts the rest in the gap, negative. | `PositionUnderflow`  |

Neither reverts. The cause lies in the registry, not in the movement, and blocking a burn or a forced transfer would make the repair harder.

The `OWNER` of the compliance closes a gap with `fixPosition(from, to, amount)`. A zero address on one side stands for the gap: from zero to an identity gives unattributed tokens their owner, and from an identity to zero removes a stale amount. The event `PositionFixed` records it.

## Why the compliance follows its token

The numbers are right because the compliance has seen every movement since the first mint of the token. There is no step that would seed a new compliance with existing positions.

For that reason, once a token has supply, its compliance cannot be replaced and cannot be bound to another token. The compliance of a circulating token is upgraded in place, and its rules change through its modules.

## Who reads the ledger

| Reader                                          | What it reads                 | For                                                                          |
| ----------------------------------------------- | ----------------------------- | ---------------------------------------------------------------------------- |
| A `RULE` module                                 | Positions and pending amounts | Deciding the largest amount a movement may carry                             |
| The compliance itself                           | Pending amounts               | Issuing and settling cross-chain validations                                 |
| An application running a distribution or a vote | `positionOf`                  | Reaching each holder's whole position, wherever it is active                 |
| An Issuer, a transfer agent, a regulator        | `positionOf`, `positionGap`   | The list of holders by identity, and the check that it adds up to the supply |

The balances of the token remain the record of where tokens are. The ledger is the same record grouped by owner.


---

# 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/token-and-register/the-compliance-ledger.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.
