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
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:
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:
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:
The caller holds the
ASSET_DEPLOYERrole. Otherwise the call reverts withAccessManagedUnauthorized.The salt has not been used. Otherwise
TokenAlreadyDeployed.When no manager is supplied:
accessManagerAdminis not zero, is not the factory and is not the address of the manager about to be deployed. OtherwiseZeroAddressorInvalidAccessManagerAdmin. When a manager is supplied: it is a contract. OtherwiseAccessManagerNotAContract.There are at most five issuers and five claim topics. Otherwise
MaxClaimIssuersReachedorMaxClaimTopicsReached.For an isolated suite: no existing storage is supplied. Otherwise
IsolatedSuiteCannotReuseIRS.A supplied storage is governed by the suite's manager. Otherwise
StorageAuthorityMismatch.issuersandissuerClaimshave the same length. OtherwiseInvalidClaimPattern. Each issuer is not zero, is listed once and has at least one topic.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.When an identity is supplied for the token: the
IdentityFactorydoes not already bind the future token address to another identity. OtherwiseTokenIdentityAlreadyBound. When none is supplied: the factory is allowed to create anASSETidentity on theIdentityFactory.The name and the symbol are not empty and
decimalsis at most 18. OtherwiseEmptyStringorDecimalsOutOfRange.
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 ofclaimDetails;a
ModularCompliance, bound to the token, with the modules bound and configured;the ONCHAINID of the token, of type
ASSET, unless one was supplied, whoseMANAGEMENTkey 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 andToken.totalSupply()is zero.TREXRegistry.getClaimTopics()andTREXRegistry.getTrustedIssuers()return the configuration ofclaimDetails.ModularCompliance.getTokenBound()returns the token andModularCompliance.getModules()returns the modules oftokenDetails.When the factory created the token's ONCHAINID:
IdentityFactory.getIdentityreturns it for the token's address.When the factory deployed the manager: the suite is commissioned,
accessManagerAdminholdsADMIN_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
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)
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_ROLEto the account named inaccessManagerAdminand 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_DEPLOYERgates 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 platformOWNERrole, 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:
claimDetailsonly 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
TREXSuiteDeployedor fromgetToken(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_ROLEonly.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
TREXSuiteDeployedto discover assets, andIsolatedSuiteDeployedto know which suites carry their own beacons.
Related flows
25 Commission a suite and grant roles : makes the suite operable
03 Configure required claim topics : change the topics set at deployment
04 Add a trusted Claim Issuer : change the issuers set at deployment
11 Add a compliance rule : bind a module after deployment
08 Mint a position to an investor : the first issuance
16 Pause and unpause a token : lift the initial pause
33 Open an asset on a satellite : distribute on another chain
Last updated