> 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/identity-based-control-and-spender-compliance.md).

# Identity-based control and spender compliance

Tokens move when their holder moves them, and they also move on a holder's behalf: by the holder's own identity acting over its wallets, or by a third party the holder has authorized. This page covers both. The first is control that follows from identity. The second is where compliance has to look at one more party, the spender.

## Three ways a position moves

|                           | Who executes                                                | Authority comes from                         | Function           |
| ------------------------- | ----------------------------------------------------------- | -------------------------------------------- | ------------------ |
| **The holder moves it**   | The address that holds the tokens: an ONCHAINID or a wallet | Holding the tokens                           | `transfer`         |
| **The identity moves it** | The ONCHAINID that a wallet is linked to                    | The link between the wallet and the identity | `identityTransfer` |
| **A spender moves it**    | A third party                                               | An allowance given by the holder             | `transferFrom`     |

Every one of them passes the eligibility gate and the compliance gate. They differ in who is acting, and therefore in what else has to be checked.

## Control by the identity

In T-REX the identity is the center of command for the holdings that sit on the reference chain. A holder can link several wallets to one ONCHAINID, and the tokens in those wallets belong to a single owner. The link itself carries authority: the identity can move tokens out of any wallet linked to it.

`identityTransfer(from, to, amount)` does this.

* **The caller is the identity.** The token resolves `from` to its identity and requires the caller to be that identity. A key holder calling the token directly is just another caller. The identity is a smart account, so the call already carries its own authentication: one of its `ACTION` keys instructed it.
* **No allowance is involved.** Nothing is read from or written to the ERC-20 allowances. This is not an allowance the holder grants to the identity. It follows from the link.
* **The movement is an ordinary transfer.** It passes pause, freeze, eligibility of the recipient and the compliance rules, like `transfer`.
* **It leaves a distinct trace.** `IdentityTransfer(identity, from, to, amount)` follows the `Transfer` event, so an indexer can tell it from a transfer made by the wallet.

```mermaid
sequenceDiagram
    participant K as ACTION key
    participant ID as ONCHAINID
    participant T as Token
    participant REG as TREXRegistry

    K->>ID: instruct a transfer from a linked wallet
    ID->>T: identityTransfer(from, to, amount)
    T->>REG: identity(from)
    REG-->>T: the calling identity
    T->>T: pause, freeze, eligibility of the recipient, compliance
    T-->>ID: Transfer, IdentityTransfer
```

What this gives a holder:

* **One point of control.** A portfolio spread over several wallets is commanded from the identity, with the identity's keys.
* **Consolidation without the wallet's key.** Tokens can be moved from a linked wallet into the identity, or into another linked wallet, without a signature from the wallet. Such a movement is between two addresses of the same identity, so it changes no position and no distribution rule limits it.
* **A way out of a wallet that is no longer trusted.** A wallet that its owner has revoked still resolves to its identity for attribution. The identity can still move the tokens out of it, to an address that is eligible.

### What it does not reach

Control by the identity covers tokens on the reference chain. A position that has been delegated to a satellite is controlled on that chain, by whatever holds it there. The identity does not reach across chains to move it. Authority over a position lives where the position is active, and returns to the reference chain when the position is recalled.

### What it leaves unchanged

Plain allowances keep their standard ERC-20 meaning. `approve`, `transferFrom` and `permit` work as every tool expects. The identity's authority over its wallets is an addition, not a replacement.

## Spenders

On `transferFrom`, a third party executes a transfer of someone else's tokens. Real markets depend on this: a venue settling a trade, a custodian moving a client's position, a settlement contract exchanging two assets.

A compliance check that looks only at the sender and the recipient leaves a gap there. An intermediary could route a transfer in a way the rules are meant to prevent, through a party the Issuer would never accept as an operator. The protocol closes the gap by making the spender a subject of compliance.

```mermaid
flowchart TB
    S["A spender calls transferFrom(from, to, amount)"] --> Q{"Is a SPENDER module bound?"}
    Q -- "no" --> OK["Spender accepted"]
    Q -- "yes" --> M{"Does every SPENDER module<br/>accept this spender?"}
    M -- "no" --> X["Reverts with SpenderNotAllowed<br/>The allowance is untouched"]
    M -- "yes" --> OK
    OK --> A["Allowance is spent"]
    A --> G["Pause, freeze, eligibility of the recipient, compliance rules"]
```

* **The spender is checked first.** Before the allowance is spent, the token asks the compliance whether this caller may execute this transfer.
* **Every `SPENDER` module must agree.** One refusal is enough.
* **The transfer itself is still checked.** A spender that is accepted does not exempt the movement from the two gates.
* **A direct transfer has no spender.** `transfer` and `identityTransfer` never reach this check. The identity of the holder is not a third party.

A spender policy can look at the whole movement, not only at the spender: a module receives the sender, the recipient, the amount and the spender together.

### The spender policies that ship

| Module                      | The spender is accepted when                                                                                  | Suits                                                                     |
| --------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `SpenderVerificationModule` | Its address is eligible for the asset: it resolves to an identity that satisfies the asset's required claims. | An asset whose intermediaries must meet the same standard as its holders. |
| `SpenderWhitelistModule`    | It is on a list of operators that the Issuer maintains.                                                       | An asset whose Issuer names its venues and operators one by one.          |

| The Issuer wants                                    | Configuration               |
| --------------------------------------------------- | --------------------------- |
| Any spender a holder approves                       | No `SPENDER` module         |
| Only spenders that are themselves eligible          | `SpenderVerificationModule` |
| Only operators it has named                         | `SpenderWhitelistModule`    |
| Operators it has named, which must also be eligible | Both                        |

`SpenderWhitelistModule` starts with an empty list and refuses every spender until one is listed. It is bound together with its first entries, so that `transferFrom` is never blocked for everyone. See [Modular compliance](/token-and-register/modular-compliance.md).

### What a venue needs

A venue is a contract, and it takes part under its own identity: an ONCHAINID of type `SMART_CONTRACT`, bound to the contract, with the claims the asset requires. What it needs from the asset depends on what it does with the tokens.

| The venue                                                               | It is     | The asset checks                                                                                                               |
| ----------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Moves tokens for holders with `transferFrom`, and never holds them      | A spender | The spender policy: its eligibility, its presence on the Issuer's list, or both                                                |
| Holds tokens in escrow, for example between an order and its settlement | A holder  | Eligibility and the compliance rules, as for any holder. And the spender policy, when it also pulls tokens with `transferFrom` |

The contracts of [DINO](/appstore/dino.md), listed in the [T-REX AppStore](/appstore.md), are an example of such a venue.

### Spenders on satellite chains

The same policy covers executions on satellites. A cross-chain validation can name a spender: the party allowed to execute the transfer on the satellite on the sender's behalf. No module runs on a satellite, so the spender is judged when the validation is issued, on the reference chain, by the same `SPENDER` modules. A validation that names a refused spender is not issued.

A spender is identified by an interoperable address, so one list or one eligibility check covers operators on the reference chain and on every satellite.

## Summary

|                              | `transfer`          | `identityTransfer`                 | `transferFrom`     |
| ---------------------------- | ------------------- | ---------------------------------- | ------------------ |
| Executed by                  | The holding address | The identity of the holding wallet | A third party      |
| Allowance                    | Not used            | Not used                           | Required and spent |
| Spender policy               | Not applied         | Not applied                        | Applied            |
| Eligibility of the recipient | Checked             | Checked                            | Checked            |
| Compliance rules             | Checked             | Checked                            | Checked            |
| Distinct event               |                     | `IdentityTransfer`                 |                    |


---

# 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/identity-based-control-and-spender-compliance.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.
