> 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/guides/agents/06.-register-an-investor-for-an-asset.md).

# 06. Register an investor for an asset

Registering an investor attributes an address to an identity for one asset. It is a local registration, made by an agent of the Issuer in the asset's own registry. Most holders do not need it: an investor that links its wallets to its ONCHAINID, or holds in the ONCHAINID itself, is recognized by every asset without any registration. An agent registers an address that cannot link itself and has to hold the asset: a custody account, a contract that cannot sign, an omnibus wallet.

## At a glance

|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Triggered by**  | Registry Agent                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| **Actors**        | Registry Agent, Issuer, Investor, Platform                                                                                                                                                                                                                                                                                                                                                                                                         |
| **Contracts**     | `TREXRegistry`, `IdentityRegistryStorage`, `IdentityFactory` (read only)                                                                                                                                                                                                                                                                                                                                                                           |
| **Preconditions** | The token suite is deployed and commissioned (see [01](/guides/issuer/01.-deploy-a-token-suite.md) and [25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md)); the caller holds `AGENT` in the asset's domain; the Investor has an ONCHAINID (see [02](/guides/identity/02.-deploy-an-onchainid.md)); the address has no local registration yet; the Issuer has verified, under its own process, that the address belongs to the Investor |
| **Result**        | For this asset, and for every asset that shares its identity storage, the address resolves to the Investor's identity                                                                                                                                                                                                                                                                                                                              |

## Actors and roles

| Actor          | Role in this flow                                                                                           | What they hold                                               |
| -------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| Registry Agent | Submits the registration. Typically the same operator as the Token Agent.                                   | `AGENT` on the `TREXRegistry`                                |
| Issuer         | Decides that the address is to be attributed to the Investor for its asset. Does not transact in this flow. | Its own verification of who controls the address             |
| Investor       | Is the subject of the registration. Does not transact.                                                      | An ONCHAINID                                                 |
| Platform       | Runs the reads and submits with the Registry Agent's key.                                                   | The Registry Agent's signing key, or a key authorized for it |

## Sequence

```mermaid
sequenceDiagram
    participant Platform
    participant Agent as Registry Agent
    participant Registry as TREXRegistry
    participant IRS as IdentityRegistryStorage

    Platform->>Registry: isLocallyRegistered(address), identity(address) (read)
    Platform->>Agent: checks passed, submit
    Agent->>Registry: registerIdentity(address, identity, country)
    Registry->>Registry: caller holds AGENT
    Registry->>IRS: addIdentityToStorage(address, identity, country)
    IRS->>IRS: registry holds IRS_WRITER
    IRS->>IRS: address and identity not zero, address not already registered
    IRS-->>Platform: IdentityStored(address, identity)
    opt the address is linked globally to another identity
        IRS-->>Platform: IdentityOverridden(address, globalIdentity, identity)
    end
    Registry-->>Platform: IdentityRegistered(address, identity)
    Platform->>Registry: isVerified(address) (read)
```

## Step by step

### Step 1. Check the address

**Who:** Platform, on behalf of the Registry Agent

**Call:** Off-chain, using read calls

**Before the call:** The Issuer has established that the address belongs to the Investor.

**What happens:** The Platform reads `TREXRegistry.isLocallyRegistered(address)`, which must be false. It reads `TREXRegistry.identity(address)` to see what the address resolves to before the registration. If it already returns the Investor's identity, the address is linked globally and no registration is needed. If it returns another identity, the registration overrides the global link for this asset: the Platform reports it to the Issuer before going further. It reads `IdentityFactory.identityTypeOf(identity)`, which is not zero for an identity the factory created. It also reads `Token.balanceOf(address)`: registering an address that already holds tokens changes the identity those tokens are attributed to.

**What changes:** Nothing on-chain.

### Step 2. Register the address

**Who:** Registry Agent (`AGENT`)

**Call:** `TREXRegistry.registerIdentity(userAddress, identity, country)`

**Before the call:** Step 1 passed. The `country` argument is required by the standard interface and is ignored. Pass zero.

**What the contract checks:**

1. The caller holds `AGENT` in the asset's domain. Otherwise the call reverts with `AccessManagedUnauthorized`.
2. The identity storage accepts the registry as a writer: the registry holds `IRS_WRITER` in the storage's domain, which commissioning grants. Otherwise `AccessManagedUnauthorized`, naming the registry.
3. Neither the address nor the identity is zero. Otherwise `ZeroAddress`.
4. The address has no local registration in the storage. Otherwise `AddressAlreadyStored`.

The contract does not check that the identity was created by the `IdentityFactory`, that it holds any claim, or that the address is controlled by its owner. Those are the Issuer's responsibility. The recommendation is to register only identities created by the `IdentityFactory`: an identity from another source is unlikely to be accepted elsewhere in the ecosystem.

**What changes:** The storage records the address under the identity and emits `IdentityStored(address, identity)`. When the address is linked globally to a different identity, it also emits `IdentityOverridden(address, globalIdentity, localIdentity)`. The registry emits `IdentityRegistered(address, identity)`. From now on, for this asset, the address resolves to the registered identity.

### Step 3. Confirm the effect

**Who:** Platform

**Call:** Off-chain, using read calls

**Before the call:** Step 2 is confirmed.

**What happens:** The Platform reads `TREXRegistry.identity(address)`, which returns the registered identity, and `TREXRegistry.isVerified(address)`, which is true only if that identity holds a valid claim from a trusted Claim Issuer for every required topic.

**What changes:** Nothing on-chain.

## State after the flow

* `TREXRegistry.isLocallyRegistered(address)` is true, and `TREXRegistry.contains(address)` is true.
* `TREXRegistry.identity(address)` returns the registered identity, whatever the global identity registry says for that address.
* The registration applies to every asset whose registry is bound to the same `IdentityRegistryStorage`.
* `TREXRegistry.isVerified(address)` reflects the claims of the registered identity. The registration has given no eligibility by itself.
* Nothing changed in the `IdentityFactory`. The address is not linked to the identity for any other Issuer's asset.
* If the address held tokens, the compliance attributes them to the registered identity from the next movement through that address.

## Failure modes

| Symptom                                                                                | Cause                                                                                                                                                                 | Fix                                                                                                                                                                                                     |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Reverts with `AccessManagedUnauthorized`                                               | The caller does not hold `AGENT` in the asset's domain (step 2, check 1)                                                                                              | Grant the role: [25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md)                                                                                                                          |
| Reverts with `AccessManagedUnauthorized`, naming the registry                          | The registry does not hold `IRS_WRITER` on the identity storage: the suite is not commissioned, or the storage is shared and sits in another domain (step 2, check 2) | Commission the suite: [25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md)                                                                                                                    |
| Reverts with `ZeroAddress`                                                             | The address or the identity is zero (step 2, check 3)                                                                                                                 | Pass both                                                                                                                                                                                               |
| Reverts with `AddressAlreadyStored`                                                    | The address already has a local registration (step 2, check 4)                                                                                                        | To change it, use [17](/guides/agents/17.-update-an-investors-registration.md)                                                                                                                          |
| The address is registered and still cannot receive                                     | The registered identity lacks a valid claim for a required topic                                                                                                      | Registration is attribution. Eligibility comes from claims: [05](/guides/claim-issuer/05.-issue-a-claim-to-an-investor.md)                                                                              |
| The address is registered and still cannot receive, with valid claims                  | The address is a wallet its owner revoked in the global identity registry. A local registration does not reinstate it                                                 | Use another address                                                                                                                                                                                     |
| A registration made for one asset appears on another                                   | Both registries are bound to the same identity storage                                                                                                                | Intended for an Issuer's assets that share a storage. Use separate storages to separate them                                                                                                            |
| The registration succeeded and the address is not recognized by another Issuer's asset | A local registration is local to one storage                                                                                                                          | The other Issuer's agent registers the address in its own storage. An address that can link itself is linked globally by its owner instead: [07](/guides/identity/07.-link-a-wallet-to-an-onchainid.md) |
| An `IdentityOverridden` event was emitted                                              | The address is linked globally to a different identity than the one registered                                                                                        | Check that the override is intended. If not, remove it: [18](/guides/agents/18.-remove-an-investors-registration.md)                                                                                    |

## Common misunderstandings

> **Wrong:** "Every investor has to be registered before it can hold the asset."
>
> **Right:** No registration is needed for an address that is an ONCHAINID or a wallet its owner linked to one. The registry resolves it through the global identity registry. Registration by an agent is for addresses that cannot link themselves.

> **Wrong:** "An omnibus wallet is registered to the investors behind it."
>
> **Right:** An omnibus wallet, for example at a centralized exchange, is registered to the identity of the entity that operates it. The register records that entity as the holder. The individual owners behind the omnibus position are in the operator's own books.

> **Wrong:** "Registering the investor whitelists the wallet."
>
> **Right:** Registration says whose the address is, for this asset. Whether that identity may hold the asset is decided from its claims, at each transfer. A registered address whose identity has no valid claims is not verified.

> **Wrong:** "The agent registers the investor's country."
>
> **Right:** The registry stores no country. The `country` argument is ignored. Where an investor resides is attested by a claim on its identity, and any rule about it is a compliance module.

> **Wrong:** "A local registration and a global link are the same record."
>
> **Right:** They are two records in two contracts. The global link is made by the owner, in the `IdentityFactory`, for every asset. The local registration is made by an agent, in the asset's identity storage, for the assets that share it. When both exist, the local one takes precedence for those assets.

## Integration notes

* Read `identity(address)` before registering. If it already returns the right identity, do nothing.
* Use `TREXRegistry.batchRegisterIdentity(addresses, identities, countries)` for many addresses. It is gated by the same role and reverts as a whole if one entry fails. The three lists have the same length.
* Index `IdentityStored` together with `IdentityOverridden`. An override logs both, in that order, and the second is what tells an indexer that the asset departs from the global link.
* The token registers an address itself in one case: the recovery of a lost wallet registers the new address when it resolves nowhere.
* Do not register an address to give it eligibility. It has no such effect.
* Keep the Issuer's evidence that the address belongs to the identity. The contract takes the agent's word.
* An address that can sign, or that can send a message from its own chain, links itself in the global identity registry. Registration by an agent is not the path for it.

## Related flows

* [07 Link a wallet to an ONCHAINID](/guides/identity/07.-link-a-wallet-to-an-onchainid.md) : the owner's global link, which usually makes this flow unnecessary
* [17 Update an investor's registration](/guides/agents/17.-update-an-investors-registration.md) : changing the registered identity
* [18 Remove an investor's registration](/guides/agents/18.-remove-an-investors-registration.md) : deleting the local registration
* [05 Issue a claim to an investor](/guides/claim-issuer/05.-issue-a-claim-to-an-investor.md) : what makes the identity eligible
* [15 Recover a position from a lost wallet](/guides/agents/15.-recover-a-position-from-a-lost-wallet.md) : registers a new address as part of a recovery


---

# 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/guides/agents/06.-register-an-investor-for-an-asset.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.
