27. Upgrade a suite
Upgrading a suite replaces the code behind its contracts with a newer version, while every balance, registration, rule and role stays in place. Who triggers it depends on how the suite was deployed. A shared suite follows the network's versions: Network governance publishes a version and activates it for every shared suite at once. An isolated suite is upgraded by its Issuer, on its own beacons, when the Issuer decides.
At a glance
Triggered by
Network governance for a shared suite; Issuer for an isolated suite
Actors
Network governance, Issuer, Platform
Contracts
TREXImplementationAuthority, the beacons of the suite, TREXAccessManager, Token, TREXRegistry, IdentityRegistryStorage, ModularCompliance
Preconditions
The token suite is deployed (see 01); the new implementations are deployed and reviewed; for a shared suite, the caller holds the platform VERSION_MANAGER role; for an isolated suite, the caller holds ADMIN_ROLE on the suite's TREXAccessManager and knows the suite's beacons
Result
The contracts of the suite run the implementations of the new version, with their state unchanged
Actors and roles
Network governance
Votes each version upgrade, publishes the version, and activates it for shared suites after a delay.
The platform VERSION_MANAGER role on the TREXImplementationAuthority, with an execution delay
Issuer
For a shared suite: follows the upgrade and verifies it. For an isolated suite: performs it.
ADMIN_ROLE on its TREXAccessManager
Platform
Reads the versions, prepares the calls and verifies the result.
The key of the party it acts for
Sequence
Step by step
Step 1. Publish the version
Who: Network governance (VERSION_MANAGER)
Call: TREXImplementationAuthority.publish(version, implementations)
Before the call: The five implementations of the version are deployed: token, registry, identity storage, compliance, access manager. The version is a semantic version that was not published before. To be activated in step 3, it is higher than the active version. When the role carries an execution delay, the call is scheduled first, as in step 3.
What the contract checks:
The caller holds the platform
VERSION_MANAGERrole. Otherwise the call reverts withAccessManagedUnauthorized.The version was not published before. Otherwise
VersionAlreadyPublished.None of the five implementation addresses is zero. Otherwise
EmptyImplementations.
What changes: The authority archives the implementations under the version and emits VersionPublished(version, implementations). No beacon changes. No suite is affected. The version is now readable with implementationsFor(version), and can be inspected by anyone before it is activated.
Step 2. Review the version
Who: Issuer, with the Platform
Call: Off-chain, using read calls
Before the call: VersionPublished was emitted. The upgrade was voted by Network governance, and its activation is scheduled: it executes after the delay of the VERSION_MANAGER role, which leaves Issuers the time of that delay to review.
What happens: The Platform reads TREXImplementationAuthority.implementationsFor(version) and checks the five addresses against the published source and the audit report of that version. An Issuer that wants to protect its asset during a shared upgrade can pause the token before step 3 and lift the pause after step 5.
What changes: Nothing on-chain.
Step 3. Activate the version, for shared suites
Who: Network governance (VERSION_MANAGER)
Call: schedule(target, data, when) on the access manager of the network, where target is the authority and data the call upgrade(version). Then, once the delay has elapsed, TREXImplementationAuthority.upgrade(version)
Before the call: Step 1 is done. publishAndUpgrade(version, implementations) does steps 1 and 3 in one call.
What the contract checks:
The caller holds the platform
VERSION_MANAGERrole. OtherwiseAccessManagedUnauthorized. The call was scheduled and its delay has elapsed. Otherwise the manager reverts withAccessManagerNotScheduledorAccessManagerNotReady.The version is greater than the active version. Otherwise
VersionNotNewer.The version was published. Otherwise
UnknownVersion.
What changes: The authority points its five beacons at the implementations of the version, in one transaction, and records it as the active version. Every shared suite runs the new code from that transaction. The authority emits SuiteUpgraded(version, implementations). Isolated suites are not affected.
Step 4. Upgrade the beacons, for an isolated suite
Who: Issuer (ADMIN_ROLE on the suite's manager)
Call: TREXAccessManager.execute(beacon, upgradeTo(implementation)), for the beacon of the token, of the registry, of the identity storage and of the compliance. For the beacon of the access manager itself: upgradeTo(implementation), called on that beacon by the admin account named at deployment.
Before the call: The Platform has the suite's beacon addresses, from the IsolatedSuiteDeployed event, and the implementations of the target version, from step 2. The Issuer groups the calls in one transaction, so that the suite never runs contracts of two versions.
What the contract checks:
The caller may call
upgradeToon the beacon through the manager. By default that requiresADMIN_ROLE. Otherwise the call reverts withAccessManagerUnauthorizedCall.The beacon's owner is the caller: the manager, or the admin account for the manager's own beacon. Otherwise the beacon reverts.
The new implementation is a contract. Otherwise the beacon reverts with
BeaconInvalidImplementation.
What changes: Each beacon points at its new implementation and emits Upgraded(implementation). The contracts of the suite run the new code. The network's authority and the shared beacons are not involved.
Step 5. Verify
Who: Platform, on behalf of the Issuer
Call: Off-chain, using read calls
Before the call: Step 3 or step 4 is confirmed.
What happens: The Platform reads Token.version(), and for a shared suite TREXImplementationAuthority.currentVersion(). It reads a sample of state that must be unchanged: Token.totalSupply(), a few balances, TREXRegistry.getClaimTopics(), ModularCompliance.getModules(), the roles of the suite. It runs TREXRegistry.isVerified and ModularCompliance.canTransfer for a known holder.
What changes: Nothing on-chain.
State after the flow
Token.version()returns the new version.For a shared suite,
TREXImplementationAuthority.currentVersion()returns the new version andimplementations()its five implementations.The addresses of the suite have not changed. Only the code behind them has.
Balances, frozen amounts, bridged positions, registrations, claim topics, trusted issuers, modules and their settings, positions and roles are unchanged.
The token is in the pause state it was in before the upgrade.
Failure modes
publish or upgrade reverts with AccessManagedUnauthorized
The caller does not hold the platform VERSION_MANAGER role (steps 1 and 3, check 1)
Use the governance account that holds the role
upgrade reverts with AccessManagerNotScheduled or AccessManagerNotReady
The role carries an execution delay, and the call was not scheduled or its delay has not elapsed (step 3, check 1)
Schedule the call on the access manager of the network and wait for the delay
Reverts with VersionAlreadyPublished
The version number was used before (step 1, check 2)
Publish under a new number. A published version cannot be changed
Reverts with EmptyImplementations
One of the five addresses is zero (step 1, check 3)
Give all five, even those that did not change
Reverts with VersionNotNewer
The target is not greater than the active version (step 3, check 2)
Versions only move forward. Publish a higher version
Reverts with UnknownVersion
The version was never published (step 3, check 3)
Publish it first
An isolated upgrade reverts with AccessManagerUnauthorizedCall
The caller does not hold the role that gates upgradeTo on the beacon, ADMIN_ROLE by default (step 4, check 1)
Use the admin account, or the role the Issuer mapped to this operation
An isolated upgrade reverts in the beacon
The call did not come from the beacon's owner, or the implementation has no code (step 4, checks 2 and 3)
Call through the manager, with a deployed implementation
An isolated suite did not move with the network's upgrade
Isolated suites do not follow the shared beacons
Intended. Run step 4
A module behaves as before after its own upgrade
A module is upgraded separately, and the compliance reads its types when it is bound
Call ModularCompliance.resyncModuleTypes(module)
A faulty version is active
The version was activated before a defect was found
Publish and activate a corrected version with a higher number. There is no rollback
Common misunderstandings
Wrong: "An upgrade deploys a new token."
Right: The addresses stay the same. Each contract is a proxy that reads its code from a beacon. An upgrade changes what the beacon points to. The state, held by the proxy, is untouched.
Wrong: "The Issuer upgrades its token."
Right: Only for an isolated suite. A shared suite is upgraded by the network's
VERSION_MANAGER, for all shared suites at once. The Issuer chose between the two at deployment.
Wrong: "If the new version is faulty, roll back."
Right: The authority refuses any version that is not greater than the active one. The way back is forward: a corrected version with a higher number. This is why a version is published, and reviewable, before it is activated.
Wrong: "Upgrading the suite upgrades the compliance modules and the identities."
Right: A suite is the token, the registry, the storage, the compliance and the access manager. Compliance modules are upgraded by their own authority. ONCHAINIDs are upgraded through the
IdentityFactory. Each has its own path and its own role.
Integration notes
Index
VersionPublishedandSuiteUpgradedon the authority. The first announces a version, the second activates it. The activation is also visible beforehand, as an operation scheduled in the access manager of the network.Do not cache ABIs by address without a version. Read
Token.version()and pick the ABI that matches.For an isolated suite, keep the five beacon addresses from
IsolatedSuiteDeployed. A proxy does not expose its beacon through a function.For an isolated suite, take the implementations from the authority, with
implementationsFor(version), so that the suite runs a published and reviewed set.Group the beacon upgrades of an isolated suite in one transaction with the manager's
multicall.An Issuer can map
upgradeToon its beacons to a dedicated role with a delay, so that an upgrade is scheduled and visible before it executes.After an upgrade, run the same reads as before it and compare. An upgrade changes behavior, never state.
Related flows
01 Deploy a token suite : where shared or isolated is chosen
25 Commission a suite and grant roles : mapping an operation to a role
12 Remove a compliance rule : a module is handled separately from the suite
16 Pause and unpause a token : protecting the asset during an upgrade
Last updated