For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

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.

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.

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 and 04

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

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), configure eligibility and compliance, mint the first positions (08), lift the pause (16).

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.

Last updated