> 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-permissioned-token.md).

# The permissioned token

A T-REX token is, at its interface, an ERC-20 token: it has a name, a symbol, a supply and the standard transfer functions, so wallets, venues and tooling work with it without special knowledge. What distinguishes it is that its transfers are conditional. A position moves only if the recipient is eligible to hold the asset and the movement complies with the asset's rules. The token does not detect a bad transfer and unwind it. It declines to record one.

This page describes the `Token` contract on the reference chain: its surface, what it is wired to, its operations, and the rules that govern its configuration.

## What the token is wired to

```mermaid
flowchart LR
    T["Token"]
    T -->|"isVerified"| REG["TREXRegistry<br/>eligibility"]
    T -->|"canTransfer, canSpenderCall,<br/>then transferred, created, destroyed"| MC["ModularCompliance<br/>rules and positions"]
    T -.->|"onchainID"| OID["ONCHAINID of the token<br/>type ASSET"]
    AM["TREXAccessManager"] -.->|"authorizes privileged calls"| T
    T <-->|"cross-chain messages"| GW["ERC-7786 gateways"]
    TGR["TrustedGatewayRegistry"] -.->|"vets"| GW
```

| Link                     | Read with                  | What it is                                                                                                              |
| ------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Eligibility registry     | `identityRegistry()`       | The `TREXRegistry` the token asks whether a recipient may hold the asset.                                               |
| Compliance               | `compliance()`             | The `ModularCompliance` the token asks whether a movement is allowed, and tells when one has happened.                  |
| Token identity           | `onchainID()`              | The ONCHAINID of the token, of type `ASSET`.                                                                            |
| Authority                | `authority()`, `owner()`   | The `TREXAccessManager` that holds the roles. `owner()` returns the same address, for tooling that expects an owner.    |
| Trusted gateway registry | `trustedGatewayRegistry()` | The network's list of vetted cross-chain gateways. It is set at deployment and cannot be changed afterward by any role. |

## The ERC-20 surface

| Function                   | Behavior                                                                               |
| -------------------------- | -------------------------------------------------------------------------------------- |
| `name`, `symbol`           | Set at deployment. Changeable by the `TOKEN_MANAGER` role. Neither can be empty.       |
| `decimals`                 | Set at deployment, between 0 and 18. Fixed afterward.                                  |
| `totalSupply`              | The whole issuance, including positions active on satellite chains.                    |
| `balanceOf`                | What an address holds on the reference chain: free plus frozen.                        |
| `transfer`, `transferFrom` | Conditional. See below.                                                                |
| `approve`, `allowance`     | Standard.                                                                              |
| `permit`                   | ERC-2612: an approval given by signature.                                              |
| `batchTransfer`            | Several transfers from the caller in one transaction. Each one passes the same checks. |

## A conditional transfer

`transfer(to, amount)` runs these checks in order, and reverts at the first that fails.

1. The token is not paused.
2. Neither the sender's address nor the recipient's address is frozen.
3. The sender's free balance covers the amount.
4. The recipient is verified by the eligibility registry.
5. The compliance allows the movement.

Then the balances move and the compliance is told, so that it updates the positions of both identities.

`transferFrom` adds one check before the allowance is spent: the compliance is asked whether the caller, as spender, may execute this transfer.

What each gate verifies is described in [Eligibility and compliance: the two gates](/the-primary-register/eligibility-and-compliance-the-two-gates.md).

## Operations

### By holders

| Function                             | What it does                                                                                                                                     |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `transfer`, `batchTransfer`          | Moves tokens the caller holds.                                                                                                                   |
| `approve`, `permit`                  | Authorizes a spender.                                                                                                                            |
| `transferFrom`                       | A spender moves tokens within its allowance.                                                                                                     |
| `identityTransfer(from, to, amount)` | An identity moves tokens held in a wallet linked to it. The caller must be the identity the `from` wallet resolves to. No allowance is involved. |

No role is needed. An ONCHAINID that holds tokens itself uses `transfer` like any holder.

### By agents

Agent operations are the servicing operations of the register. Each is gated by its own role.

| Function                                                        | Role                     | What it does                                                                                      |
| --------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------- |
| `mint(to, amount)`                                              | `AGENT_MINTER`           | Creates tokens for an eligible recipient, within the rules. Issuance.                             |
| `burn(from, amount)`                                            | `AGENT_BURNER`           | Destroys tokens held by an address. Redemption. Frozen tokens are released as needed.             |
| `freezePartialTokens(address, amount)`, `unfreezePartialTokens` | `AGENT_PARTIAL_FREEZER`  | Immobilizes, or releases, part of what an address holds.                                          |
| `setAddressFrozen(address, frozen)`                             | `AGENT_ADDRESS_FREEZER`  | Blocks, or unblocks, an address entirely: it neither sends nor receives.                          |
| `forcedTransfer(from, to, amount)`                              | `AGENT_FORCED_TRANSFER`  | Moves tokens without the holder, to an eligible recipient. Overrides freezes.                     |
| `recoveryAddress(lostWallet, newWallet, identity)`              | `AGENT_RECOVERY_ADDRESS` | Moves the whole balance of a lost wallet, with its freezes, to a new wallet of the same identity. |
| `pause`, `unpause`                                              | `AGENT_PAUSER`           | Halts, or resumes, every movement between holders.                                                |

Every function except `recoveryAddress`, `pause` and `unpause` has a batch variant, gated by the same role.

### Configuration

| Function               | Role               | Rule                                                                                    |
| ---------------------- | ------------------ | --------------------------------------------------------------------------------------- |
| `setName`, `setSymbol` | `TOKEN_MANAGER`    | Not empty. Changing the name invalidates permit signatures that have not been used yet. |
| `setOnchainID`         | `IDENTITY_MANAGER` | Sets the identity of the token.                                                         |
| `setIdentityRegistry`  | `IDENTITY_MANAGER` | Only while the token has no supply.                                                     |
| `setCompliance`        | `IDENTITY_MANAGER` | Only while the token has no supply.                                                     |
| `setRoute`, `setPeer`  | `IDENTITY_MANAGER` | Opens the asset on a satellite chain.                                                   |

Roles are described in [Actors and roles](/start-here/actors-and-roles.md).

## Two kinds of freeze

|               | Freezing an address                         | Freezing an amount                                                                                 |
| ------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| **Effect**    | The address cannot send and cannot receive. | The amount cannot be sent. The rest of the balance moves normally, and the address still receives. |
| **Read with** | `isFrozen(address)`                         | `getFrozenTokens(address)`                                                                         |
| **Limit**     |                                             | The frozen amount never exceeds the balance.                                                       |

Frozen tokens are still owned by their holder and still counted in `balanceOf` and in the identity's position. A burn, a forced transfer or a recovery releases exactly the frozen amount it needs, so an agent never has to unfreeze before acting.

## The pause

A paused token records no movement between holders: no transfer, no forced transfer, no recovery, no settlement of a transfer executed on a satellite. Mints and burns remain possible.

* **A token is deployed paused.** The Issuer configures it, mints the initial positions if it wants to, and lifts the pause when the asset opens.
* **The pause is also the incident halt.** Because it stops agent movements too, an incident under investigation settles nothing. If the cross-chain layer delivers something the register cannot account for, the token pauses itself.

## The registry and the compliance follow the token

Once a token has supply, its eligibility registry and its compliance cannot be replaced. Both setters revert.

* **The compliance has counted every movement since the first mint.** It holds the position of every identity. A new compliance would start every holder at zero, and every rule that reads positions would be wrong from the first transfer.
* **The registry attributes every position.** A registry that resolved addresses differently would leave positions under identities that no address resolves to.

A circulating token changes through what it has: its compliance is upgraded in place or reconfigured through its modules, and its registry is reconfigured through its topics, its trusted issuers and its registrations.

Before the first mint, a replacement must implement the expected interface, be governed by the same AccessManager as the token, and, for a compliance, not be bound to another token.

## Supply and decimals

`totalSupply` counts the whole issuance of the asset, wherever it is active. It changes on a mint or a burn and on nothing else. Moving a position to a satellite chain or back does not change it. The part that sits on the reference chain is `totalSupply() - totalBridged()`. The balance model is described under The balance model.

## Events

The token emits the ERC-20 and ERC-3643 events: `Transfer`, `Approval`, `Paused`, `Unpaused`, `AddressFrozen`, `TokensFrozen`, `TokensUnfrozen`, `RecoverySuccess`, `UpdatedTokenInformation`, `IdentityRegistryAdded`, `ComplianceAdded`.

Two T-REX events let an indexer tell a holder's transfer from the other kinds:

| Event                                          | Follows the `Transfer` of                                      |
| ---------------------------------------------- | -------------------------------------------------------------- |
| `ForcedTransfer(agent)`                        | Every forced transfer, naming the agent that executed it.      |
| `IdentityTransfer(identity, from, to, amount)` | Every transfer ordered by an identity from one of its wallets. |


---

# 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-permissioned-token.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.
