25. Commission a suite and grant roles
Commissioning wires a deployed suite to its access manager: it maps every privileged function to a role of the Issuer's domain and sets which role administers which. Granting then gives those roles to the Issuer's operators. The Issuer triggers both, right after deployment. Until they are done, the suite is not operable: every privileged function answers to the holder of ADMIN_ROLE only, the token holds no AGENT role and the registry no IRS_WRITER.
When the TREXFactory deployed the access manager, the suite is already commissioned: step 2 is skipped.
An Issuer that supplied its own manager at deployment commissions the suite itself, in step 2. Such a manager comes from one of two sources.
The access manager factory of the T-REX Network [[TBC: name of the access manager factory and of its deployment function]]
The T-REX Network. The factory deploys the reference TREXAccessManager of the network.
Any other deployment
The Issuer. The T-REX Network does not review that contract.
In both cases the Issuer decides who holds which role. The protocol sets the roles and what each one gates. It does not prescribe how an Issuer splits them between its teams and its providers.
At a glance
Triggered by
Issuer
Actors
Issuer, Token Agent, Registry Agent, Compliance Owner, Platform
Contracts
TREXAccessManager, Token, TREXRegistry, IdentityRegistryStorage, ModularCompliance
Preconditions
The token suite is deployed (see 01); the Issuer's account holds ADMIN_ROLE on the suite's TREXAccessManager; the Issuer has decided which account receives which role
Result
Every privileged function of the suite is mapped to a role of the Issuer's domain, and the accounts the Issuer chose hold those roles
Actors and roles
Issuer
Commissions the suite and grants the administrative roles.
ADMIN_ROLE on the TREXAccessManager
Token Agent
Receives agent roles on the token. Does not transact in this flow.
An account or an ONCHAINID that receives the roles
Registry Agent
Receives the AGENT role. Does not transact. Typically the same operator as the Token Agent.
An account that receives the role
Compliance Owner
Receives OWNER. Usually the Issuer itself.
An account that receives the role
Platform
Computes role identifiers, runs the reads and submits with the Issuer's key.
The Issuer's signing key, or a key authorized for it
Sequence
Step by step
Step 1. Read the starting state
Who: Platform, on behalf of the Issuer
Call: Off-chain, using read calls
Before the call: The Platform knows the token's address.
What happens: The Platform reads Token.authority() to find the manager, TREXAccessManager.domainOf(token) to find the domain, and TREXAccessManager.getTargetFunctionRole(token, selector) for one privileged function, for example mint. A domain of zero, or a function still mapped to ADMIN_ROLE, means the suite is not commissioned.
What changes: Nothing on-chain.
Step 2. Commission the suite
Skip this step when the factory deployed the manager.
Who: Issuer (ADMIN_ROLE)
Call: The commissioning of AccessManagerSetupLib.commissionSuite(accessManager, token), executed from a script or a contract that holds ADMIN_ROLE. Before it: TREXAccessManager.createDomain(name) for a new domain, then TREXAccessManager.assign(domainId, token) in every case. The commissioning then makes these calls on the manager and on the storage:
assign(domainId, storage), when the storage has no domain yet;grantRoleofAGENTto the token, and ofIRS_WRITERto the registry;setTargetFunctionRole(target, selectors, roleId)for the token, the registry, the compliance and the storage;setRoleAdmin(roleId, adminRoleId)for each role;IdentityRegistryStorage.bindIdentityRegistry(registry), unless the registry is already bound.
Before the call: The Issuer chooses the domain: a new one for this asset, or an existing one, in which case the asset shares the agents of that domain.
What the contract checks:
The caller holds
ADMIN_ROLEon the manager, for every mapping and for the two grants. Otherwise the call reverts withAccessManagerUnauthorizedAccount.The domain exists and the token is assigned to one. Otherwise
DomainNotFoundorNotAssigned.When the storage is already in use by another suite: the caller holds
IRS_BINDERin the storage's domain. Otherwise the binding reverts withAccessManagedUnauthorized.
What changes: Every privileged function of the four contracts is mapped to its role in the domain. AGENT_ADMIN administers the agent roles, IRS_BINDER and VALIDATION_KEEPER. SUITE_ADMIN administers TOKEN_MANAGER, IDENTITY_MANAGER and COMPLIANCE_MANAGER. The token holds AGENT and the registry holds IRS_WRITER. The registry is bound to its storage. The manager emits DomainCreated, DomainAssigned, TargetFunctionRoleUpdated, RoleAdminChanged and RoleGranted.
Step 3. Grant the administrative roles
Who: Issuer (ADMIN_ROLE)
Call: TREXAccessManager.grantRole(roleId, account, executionDelay), once per role and account
Before the call: The Platform computes each role identifier from the domain and the role number:
roleId = domainId * 2^32 + roleNumber
OWNER
1
TOKEN_MANAGER
10
AGENT
2
IDENTITY_MANAGER
11
AGENT_MINTER
3
AGENT_ADMIN
12
AGENT_BURNER
4
SUITE_ADMIN
13
AGENT_PARTIAL_FREEZER
5
IRS_BINDER
14
AGENT_ADDRESS_FREEZER
6
IRS_WRITER
15
AGENT_RECOVERY_ADDRESS
7
COMPLIANCE_MANAGER
16
AGENT_FORCED_TRANSFER
8
VALIDATION_KEEPER
17
AGENT_PAUSER
9
The Issuer grants OWNER, SUITE_ADMIN and AGENT_ADMIN. executionDelay is zero for a role whose holder acts at once, or a number of seconds for a role whose holder must schedule its calls.
What the contract checks:
The caller holds the role that administers
roleId. For these three roles that isADMIN_ROLE. OtherwiseAccessManagerUnauthorizedAccount.
What changes: The account holds the role in the domain. The manager emits RoleGranted(roleId, account, delay, since, newMember).
Step 4. Grant the operational roles
Who: The holders of SUITE_ADMIN and of AGENT_ADMIN, or the Issuer after granting itself those roles
Call: TREXAccessManager.grantRole(roleId, account, executionDelay)
Before the call: Step 3 is done. The Issuer has decided how to split duties.
What the contract checks:
The caller holds the role that administers
roleId:SUITE_ADMINforTOKEN_MANAGER,IDENTITY_MANAGERandCOMPLIANCE_MANAGER;AGENT_ADMINforAGENT, the seven agent roles,IRS_BINDERandVALIDATION_KEEPER. OtherwiseAccessManagerUnauthorizedAccount.
What changes: Each account holds its role. One RoleGranted event per grant.
Step 5. Verify
Who: Platform
Call: Off-chain, using read calls
Before the call: Steps 3 and 4 are confirmed.
What happens: For each grant, the Platform reads TREXAccessManager.hasRole(roleId, account), which returns whether the account is a member and with what delay. For one function per role, it reads TREXAccessManager.canCall(account, target, selector).
What changes: Nothing on-chain.
State after the flow
TREXAccessManager.domainOf(token)returns the Issuer's domain.getTargetFunctionRolereturns a role of that domain for every privileged function of the token, the registry, the compliance and the storage.hasRoleis true for each account and role the Issuer granted.The token holds
AGENTand the registry holdsIRS_WRITER.The token is still paused and has no supply.
Failure modes
A privileged call on the suite reverts with AccessManagedUnauthorized
The caller does not hold the role, or holds it in another domain
Read hasRole with the identifier of the token's domain. Grant the role
A privileged call reverts with AccessManagerNotScheduled
The caller holds the role with an execution delay and did not schedule the call
Schedule the call on the manager, wait for the delay, then call
Every privileged call by an operator reverts, although its role is granted
The suite is not commissioned: its functions are not mapped, and answer to ADMIN_ROLE only (step 2)
Commission the suite
Commissioning reverts with NotAssigned
The token is not assigned to a domain (step 2, check 2)
assign(domainId, token) first
grantRole reverts with AccessManagerUnauthorizedAccount
The caller does not hold the administering role (steps 3 and 4)
Use the account that holds ADMIN_ROLE, SUITE_ADMIN or AGENT_ADMIN, as the role requires
A recovery reverts when it registers the new wallet
The token does not hold AGENT in its domain
Commission the suite again. It grants the role
A registration reverts in the storage
The registry does not hold IRS_WRITER, or is not bound to the storage
Commission the suite again
An operator can act on another asset of the Issuer
Both assets are in the same domain
Intended for a shared team. Otherwise place the assets in separate domains
A batch call reverts for a holder that has a delay
A batch function is authorized by the role of its single operation and requires immediate permission. batchRegisterIdentity is the exception: it has its own mapping and can be scheduled
Use the single operation, scheduled, or grant the role without delay
Common misunderstandings
Wrong: "The admin of the manager can mint."
Right:
ADMIN_ROLEmaps functions to roles and grants roles. Once the suite is commissioned,mintis gated byAGENT_MINTER, and the admin does not hold it unless it grants it to itself. Administering the suite and operating the token are separate powers.
Wrong: "Granting
AGENTmakes someone the token's agent."Right:
AGENTgates registrations in the registry and requests of cross-chain validations on behalf of holders. Minting, burning, freezing, forced transfers, recovery and the pause are seven separate roles, each granted on its own.
Wrong: "A role is granted on a token."
Right: A role is granted in a domain. It applies to every token assigned to that domain. Two tokens in one domain share their agents. To separate the teams of two assets, place the assets in two domains.
Wrong: "Assigning a token to a domain gives that domain's roles power over it."
Right: The domain registry is a directory. Authority comes from the mapping of each function to a role, which commissioning writes.
assignalone maps nothing and revokes nothing.
Integration notes
Compute role identifiers from the domain read on-chain, never from a constant. The same role has a different identifier in each domain.
Decode
RoleGrantedandRoleRevokedevents to maintain the list of role holders: the domain is the upper half of the identifier and the role number the lower half.Group the grants of steps 3 and 4 in one transaction with the manager's
multicall.Give the sensitive roles a delay and the emergency roles none. A pauser acts at once. A change of compliance rules can wait.
A role can be held by an ONCHAINID. The role check applies to the identity that makes the call, not to the key that instructed it.
Commissioning can be run again. It applies the same mappings.
Hold
ADMIN_ROLEin a multisig or in the Issuer's governance. It has no on-chain fallback.For an asset open on satellites, grant
VALIDATION_KEEPERto the keeper that the T-REX Network runs: 35.[[TBC: the address of the keeper of the T-REX Network]]createDomain,assignanddomainOfare functions ofTREXAccessManager. A manager from another source may not have them. The Issuer then chooses the domain number of each asset and keeps it in its own records. A manager from the access manager factory of the T-REX Network avoids this.
Related flows
01 Deploy a token suite : the precondition
03 Configure required claim topics : first use of
OWNER04 Add a trusted Claim Issuer : first use of
OWNER11 Add a compliance rule : uses
OWNERon the compliance08 Mint a position to an investor : first use of
AGENT_MINTER16 Pause and unpause a token : lifting the initial pause needs
AGENT_PAUSER
Last updated