> 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/issuer/01.-deploy-a-token-suite.md).

# 01. Deploy a token suite

Deploying a token suite creates the contracts of one asset in a single transaction: the token, its eligibility registry, its identity storage, its compliance, its access manager and the ONCHAINID of the token. The Deployer triggers it. The Deployer is the Issuer itself, once Network governance has granted it the `ASSET_DEPLOYER` role, or a tokenization provider that holds that role and deploys for the Issuers it serves. It is the first operation in the life of an asset. The token comes out wired, paused and with no supply.

## At a glance

|                   |                                                                                                                                                                                                                                                                                          |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Triggered by**  | Deployer                                                                                                                                                                                                                                                                                 |
| **Actors**        | Deployer, Issuer, Platform                                                                                                                                                                                                                                                               |
| **Contracts**     | `TREXFactory`, `TREXImplementationAuthority`, `IdentityFactory`, `Token`, `TREXRegistry`, `IdentityRegistryStorage`, `ModularCompliance`, `TREXAccessManager`                                                                                                                            |
| **Preconditions** | The Deployer holds the `ASSET_DEPLOYER` role; the `TREXFactory` holds it too, to create the identity of the token on the `IdentityFactory`; every compliance module to bind is deployed; every Claim Issuer to trust exists; the Issuer has named the account that receives `ADMIN_ROLE` |
| **Result**        | A complete suite exists at deterministic addresses, commissioned, paused, with zero supply, and its `ADMIN_ROLE` is held by the Issuer's account                                                                                                                                         |

## Actors and roles

| Actor    | Role in this flow                                                                                                                              | What they hold                                                            |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Deployer | Submits the deployment. It is an Issuer that deploys its own assets, or a tokenization provider that deploys for its customers.                | The `ASSET_DEPLOYER` role, granted by Network governance                  |
| Issuer   | Decides the parameters of the asset and names the account that administers the suite. Transacts in this flow only when it is its own Deployer. | The account that receives `ADMIN_ROLE` on the suite's `TREXAccessManager` |
| Platform | Assembles the parameters, runs the pre-check and submits with the Deployer's key.                                                              | The Deployer's signing key, or a key authorized for it                    |

## Sequence

```mermaid
sequenceDiagram
    participant Platform
    participant Deployer
    participant Factory as TREXFactory
    participant IA as TREXImplementationAuthority
    participant IdFactory as IdentityFactory
    participant AM as TREXAccessManager

    Platform->>Factory: getToken(salt) (read)
    Platform->>Deployer: parameters ready, submit
    Deployer->>Factory: deployTREXSuite(salt, tokenDetails, claimDetails)
    Factory->>Factory: caller holds the ASSET_DEPLOYER role, inputs valid
    Factory->>IA: beacons()
    Factory->>Factory: deploy access manager, storage, registry, compliance
    Factory->>IdFactory: createIdentityFor(futureToken, ASSET, salt, keys)
    Factory->>Factory: deploy Token
    Factory->>AM: createDomain, assign, commission
    Factory->>AM: grantRole(ADMIN_ROLE, admin), renounceRole(ADMIN_ROLE)
    Factory-->>Platform: TREXSuiteDeployed(token, registry, storage, compliance, salt)
```

## Step by step

### Step 1. Prepare the deployment

**Who:** Platform, on behalf of the Deployer and the Issuer

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

**Before the call:** The Issuer has decided the parameters of the asset. Network governance has granted the `ASSET_DEPLOYER` role to the Deployer.

**What happens:** The Platform assembles the three arguments.

`salt` is a string, chosen freely, used once per factory. With the factory's address it determines every address of the suite. The Platform calls `TREXFactory.getToken(salt)` and expects the zero address.

`tokenDetails`:

| Field                | Meaning                                                                                                                                                                                                                                                                                                    |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`, `symbol`     | Not empty.                                                                                                                                                                                                                                                                                                 |
| `decimals`           | Between 0 and 18. Fixed after deployment.                                                                                                                                                                                                                                                                  |
| `irs`                | Zero to deploy a new identity storage. Or the address of an existing storage, to share local registrations with another asset. An existing storage is governed by an existing manager, so that manager is supplied in `accessManager` as well.                                                             |
| `ONCHAINID`          | Zero to have the factory create the token's identity. Or the address of an existing identity.                                                                                                                                                                                                              |
| `complianceModules`  | The modules to bind to the compliance.                                                                                                                                                                                                                                                                     |
| `complianceSettings` | The configuration call for each module, at the same index. Modules that need no settings go at the end of the list.                                                                                                                                                                                        |
| `accessManager`      | Zero to have the factory deploy a `TREXAccessManager` for the suite. Or the address of the Issuer's existing manager. Unless that manager comes from the access manager factory of the T-REX Network, the Issuer answers for its code. See [25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md). |
| `accessManagerAdmin` | The account that receives `ADMIN_ROLE` on the manager the factory deploys. Ignored when a manager is supplied.                                                                                                                                                                                             |

`claimDetails`:

| Field          | Meaning                                                           |
| -------------- | ----------------------------------------------------------------- |
| `claimTopics`  | The claim topics required by default. At most five here.          |
| `issuers`      | The Claim Issuers trusted at launch. At most five here.           |
| `issuerClaims` | For each issuer, at the same index, the topics it is trusted for. |

The Issuer also chooses between a shared suite, upgraded with the network's versions, and an isolated suite, which the Issuer upgrades itself. See [Upgradeability: beacons and versions](/governance-and-infrastructure/upgradeability-beacons-and-versions.md).

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

### Step 2. Deploy the suite

**Who:** Deployer (`ASSET_DEPLOYER` role)

**Call:** `TREXFactory.deployTREXSuite(salt, tokenDetails, claimDetails)`, or `TREXFactory.deployTREXSuiteIsolated(salt, tokenDetails, claimDetails)` for an isolated suite

**Before the call:** Step 1 is done.

**What the contract checks:**

1. The caller holds the `ASSET_DEPLOYER` role. Otherwise the call reverts with `AccessManagedUnauthorized`.
2. The salt has not been used. Otherwise `TokenAlreadyDeployed`.
3. When no manager is supplied: `accessManagerAdmin` is not zero, is not the factory and is not the address of the manager about to be deployed. Otherwise `ZeroAddress` or `InvalidAccessManagerAdmin`. When a manager is supplied: it is a contract. Otherwise `AccessManagerNotAContract`.
4. There are at most five issuers and five claim topics. Otherwise `MaxClaimIssuersReached` or `MaxClaimTopicsReached`.
5. For an isolated suite: no existing storage is supplied. Otherwise `IsolatedSuiteCannotReuseIRS`.
6. A supplied storage is governed by the suite's manager. Otherwise `StorageAuthorityMismatch`.
7. `issuers` and `issuerClaims` have the same length. Otherwise `InvalidClaimPattern`. Each issuer is not zero, is listed once and has at least one topic.
8. There are at least as many modules as settings. Otherwise `InvalidCompliancePattern`. Each module binds: it is listed once, it declares its types, it accepts this compliance, and its configuration call succeeds.
9. When an identity is supplied for the token: the `IdentityFactory` does not already bind the future token address to another identity. Otherwise `TokenIdentityAlreadyBound`. When none is supplied: the factory is allowed to create an `ASSET` identity on the `IdentityFactory`.
10. The name and the symbol are not empty and `decimals` is at most 18. Otherwise `EmptyString` or `DecimalsOutOfRange`.

**What changes:** The factory deploys, at addresses derived from its own address and the salt:

* a `TREXAccessManager`, unless one was supplied;
* an `IdentityRegistryStorage`, unless one was supplied, already bound to the registry;
* a `TREXRegistry`, holding the claim topics and the trusted issuers of `claimDetails`;
* a `ModularCompliance`, bound to the token, with the modules bound and configured;
* the ONCHAINID of the token, of type `ASSET`, unless one was supplied, whose `MANAGEMENT` key is the suite's manager;
* the `Token`, wired to the registry, the compliance, its identity and the manager, and paused.

When the factory deployed the manager, it then creates a domain named after the token, assigns the token and its storage to it, commissions the suite, grants `ADMIN_ROLE` to `accessManagerAdmin` and renounces its own. When a manager was supplied, the factory writes nothing into it.

The factory emits `Deployed` for each contract and `TREXSuiteDeployed(token, registry, storage, compliance, salt)`. For an isolated suite it also emits `IsolatedSuiteDeployed(token, beacons)`.

### Step 3. Record the addresses

**Who:** Platform

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

**Before the call:** The transaction of step 2 is confirmed.

**What happens:** The Platform reads the addresses from `TREXSuiteDeployed`, or from `TREXFactory.getToken(salt)` followed by `Token.identityRegistry()`, `Token.compliance()`, `Token.onchainID()` and `Token.authority()`. It stores them with the salt.

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

## State after the flow

* `TREXFactory.getToken(salt)` returns the token.
* `Token.paused()` is true and `Token.totalSupply()` is zero.
* `TREXRegistry.getClaimTopics()` and `TREXRegistry.getTrustedIssuers()` return the configuration of `claimDetails`.
* `ModularCompliance.getTokenBound()` returns the token and `ModularCompliance.getModules()` returns the modules of `tokenDetails`.
* When the factory created the token's ONCHAINID: `IdentityFactory.getIdentity` returns it for the token's address.
* When the factory deployed the manager: the suite is commissioned, `accessManagerAdmin` holds `ADMIN_ROLE`, and the factory holds no role. No operational role is granted yet.
* When a manager was supplied: the suite is deployed and not operable until it is commissioned.

## Failure modes

| Symptom                                                                | Cause                                                                                                                        | Fix                                                                                                                                                                    |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Reverts with `AccessManagedUnauthorized`                               | The calling key does not hold the `ASSET_DEPLOYER` role (step 2, check 1)                                                    | Use the Deployer's key. An Issuer or a tokenization provider that does not hold the role asks Network governance for it                                                |
| Reverts with `TokenAlreadyDeployed`                                    | The salt was already used on this factory (step 2, check 2)                                                                  | Choose another salt                                                                                                                                                    |
| Reverts with `InvalidAccessManagerAdmin` or `ZeroAddress`              | `accessManagerAdmin` is zero, the factory, or the future manager (step 2, check 3)                                           | Name the Issuer's own account                                                                                                                                          |
| Reverts with `AccessManagerNotAContract`                               | The supplied manager address has no code (step 2, check 3)                                                                   | Supply a deployed manager, or zero                                                                                                                                     |
| Reverts with `MaxClaimIssuersReached` or `MaxClaimTopicsReached`       | More than five issuers or five topics at deployment (step 2, check 4)                                                        | Deploy with five, add the others afterward with [03](/guides/issuer/03.-configure-required-claim-topics.md) and [04](/guides/issuer/04.-add-a-trusted-claim-issuer.md) |
| Reverts with `IsolatedSuiteCannotReuseIRS`                             | An existing storage was supplied to an isolated deployment (step 2, check 5)                                                 | Set `irs` to zero                                                                                                                                                      |
| Reverts with `StorageAuthorityMismatch`                                | The supplied storage is governed by another manager (step 2, check 6)                                                        | Supply the manager that governs the storage, or deploy a new storage                                                                                                   |
| Reverts with `InvalidClaimPattern`                                     | `issuers` and `issuerClaims` differ in length (step 2, check 7)                                                              | Give one list of topics per issuer                                                                                                                                     |
| Reverts with `InvalidCompliancePattern`                                | More settings than modules (step 2, check 8)                                                                                 | Align the two lists by index                                                                                                                                           |
| Reverts while binding a module                                         | A module is listed twice, declares no type, refuses the compliance, or its configuration call fails (step 2, check 8)        | Correct the module list or the settings                                                                                                                                |
| Reverts with `TokenIdentityAlreadyBound`                               | The future token address is already bound to another identity (step 2, check 9)                                              | Supply that identity, or choose another salt                                                                                                                           |
| Reverts in the `IdentityFactory`                                       | The `TREXFactory` does not hold `ASSET_DEPLOYER` itself, so it cannot create the identity of the token (step 2, check 9)     | Network governance grants the role to the `TREXFactory`                                                                                                                |
| Reverts with `EmptyString` or `DecimalsOutOfRange`                     | Empty name or symbol, or more than 18 decimals (step 2, check 10)                                                            | Correct `tokenDetails`                                                                                                                                                 |
| The suite is deployed and every privileged call by an operator reverts | A manager was supplied and the suite is not commissioned. Its privileged functions answer to the holder of `ADMIN_ROLE` only | Commission it: [25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md)                                                                                          |

## Common misunderstandings

> **Wrong:** "The factory owns the token it deployed."
>
> **Right:** The factory keeps no authority, and deploying gives the Deployer none. When the factory deploys the manager, it grants `ADMIN_ROLE` to the account named in `accessManagerAdmin` and renounces its own in the same transaction. A tokenization provider that deploys for an Issuer names the Issuer's account there. It then holds no role on the suite, unless the Issuer grants it one. When the Issuer supplies a manager, the factory never writes into it.

> **Wrong:** "A party that can deploy suites controls the factory."
>
> **Right:** `ASSET_DEPLOYER` gates the deployment of a suite and the creation of the identity of a token, and nothing else. The references of the factory, which are the implementation authority, the identity factory and the trusted gateway registry, are set under the platform `OWNER` role, which Network governance holds.

> **Wrong:** "Once the suite is deployed, the asset is live."
>
> **Right:** The token is deployed paused, with no supply, and no operational role has been granted. The launch order is: deploy, commission and grant roles ([25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md)), configure eligibility and compliance, mint the first positions ([08](/guides/positions/08.-mint-a-position-to-an-investor.md)), lift the pause ([16](/guides/agents/16.-pause-and-unpause-a-token.md)).

> **Wrong:** "The name and the symbol are part of the token's address."
>
> **Right:** The addresses of a suite depend on the factory's address and the salt, and on nothing else. Two deployments with different names and the same salt target the same addresses, and the second reverts.

> **Wrong:** "Eligibility is fixed at deployment."
>
> **Right:** `claimDetails` only sets the starting configuration, and is limited to five topics and five issuers. The Issuer changes both afterward, up to 15 topics and 50 issuers.

## Integration notes

* Compute nothing by hand. Read the addresses from `TREXSuiteDeployed` or from `getToken(salt)` and the token's getters.
* Store the salt with the asset. It is the handle of the suite on the factory, and it is what gives T-REX Lite the same address on an EVM satellite.
* Run `getToken(salt)` before submitting. A used salt is the most common cause of a revert.
* Deploying with a shared storage does not bind the new registry to it. The Issuer binds it when it commissions the suite.
* When the Issuer supplies its own manager, plan the commissioning as the next transaction. Until then the suite is not operable: its privileged functions answer to the holder of `ADMIN_ROLE` only.
* A module that restricts by default, such as a spender list, is deployed with its settings in `complianceSettings`, so that it is never bound unconfigured.
* Index `TREXSuiteDeployed` to discover assets, and `IsolatedSuiteDeployed` to know which suites carry their own beacons.

## Related flows

* [25 Commission a suite and grant roles](/guides/issuer/25.-commission-a-suite-and-grant-roles.md) : makes the suite operable
* [03 Configure required claim topics](/guides/issuer/03.-configure-required-claim-topics.md) : change the topics set at deployment
* [04 Add a trusted Claim Issuer](/guides/issuer/04.-add-a-trusted-claim-issuer.md) : change the issuers set at deployment
* [11 Add a compliance rule](/guides/issuer/11.-add-a-compliance-rule.md) : bind a module after deployment
* [08 Mint a position to an investor](/guides/positions/08.-mint-a-position-to-an-investor.md) : the first issuance
* [16 Pause and unpause a token](/guides/agents/16.-pause-and-unpause-a-token.md) : lift the initial pause
* [33 Open an asset on a satellite](/guides/cross-chain/33.-open-an-asset-on-a-satellite.md) : distribute on another chain


---

# 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/issuer/01.-deploy-a-token-suite.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.
