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

Upgradeability: beacons and versions

The contracts that hold a register have to be able to change: to fix a defect, to follow a standard, to add a capability. They also have to change safely and visibly, because the assets they record outlive any version of the code. The protocol provides upgradeability through standard mechanisms that auditors and tooling already understand, and it is explicit about who can change the code of what.

What is upgradeable, and how

Contract
Mechanism
Who can upgrade it

Token, TREXRegistry, IdentityRegistryStorage, ModularCompliance, TREXAccessManager

Beacon proxy

In a shared suite: the VERSION_MANAGER of the network. In an isolated suite: the Issuer.

Identity (every ONCHAINID)

Beacon proxy, one beacon for all identities

The beacon upgrader of the identity layer, after a delay

Compliance modules

UUPS proxy

The authority of the module

UtilityChecker, IdentityUtilities

UUPS proxy

The owner of UtilityChecker. The holder of DEFAULT_ADMIN_ROLE on IdentityUtilities

TREXFactory, TREXImplementationAuthority, TrustedGatewayRegistry

Not upgradeable

IdentityFactory, ReputationRegistry, EASClaimIssuer

Not upgradeable

ERC734Validator, KeyApprovalModule, RecoveryModule

Not upgradeable

A contract that is not upgradeable is replaced by deploying a new one and pointing to it. The factory, for instance, can be given a new implementation authority for the suites it deploys from then on.

Beacon proxies

A beacon holds the address of the current implementation for a family of proxies. Each proxy asks its beacon where the code is. Changing the address in the beacon changes the code of every proxy that points to it, in one transaction.

A token suite has five kinds of contract, and the authority holds one beacon for each. Every suite deployed in shared mode points to these five beacons.

Versions

The TREXImplementationAuthority does not upgrade one contract at a time. It moves a suite from one version to the next, where a version is a complete, coherent set of five implementations.

Function
Effect

publish(version, implementations)

Archives the five implementations of a version. No beacon changes. No suite is affected.

upgrade(version)

Points the five beacons at the implementations of a published version. Every shared suite moves to that version in one transaction.

publishAndUpgrade(version, implementations)

Both at once.

All three require the VERSION_MANAGER platform role. A version upgrade is decided by a vote of Network governance, and the role carries an execution delay: the upgrade is scheduled, stays visible for the delay, and only then executes.

Rule
Reason

A version is a semantic version: major, minor, patch.

Versions are ordered.

A version is published once. Its implementations cannot be changed afterward.

What a version number designates never varies.

Publishing and upgrading are separate.

A version can be published, inspected and verified on-chain before any suite runs it.

An upgrade only moves forward. The target must be greater than the active version.

A beacon can never be rolled back onto older code.

The five contracts move together.

A suite never runs a token of one version against a compliance of another.

There is no rollback. The way back from a faulty version is a new version with a higher number.

currentVersion() returns the active version. implementations() returns the implementations it designates, implementationsFor(version) those of any published version, and beacons() the five beacon addresses, which never change. The events VersionPublished and SuiteUpgraded record every step.

Shared and isolated suites

An Issuer chooses at deployment who upgrades its suite.

Shared suite
Isolated suite

Deployed with

deployTREXSuite

deployTREXSuiteIsolated

Beacons

The five beacons of the authority, common to all shared suites

Its own beacons, created for it from the active version

Owner of the beacons

The TREXImplementationAuthority

The suite's own AccessManager. The beacon of that manager belongs to the admin the Issuer named.

Who upgrades

The VERSION_MANAGER, for every shared suite at once

The Issuer, through its manager

Follows the network's versions

Automatically

Only when the Issuer upgrades its own beacons

Identity storage

Its own, or an existing shared one

Always its own

In an isolated suite, the Issuer upgrades a contract by having its manager point the corresponding beacon at a new implementation. By default only the admin of that manager can do so. The Issuer can assign the operation to a narrower role, with a delay.

An isolated suite always deploys its own identity storage. A storage reused from another suite would keep the beacon that deployed it, and shared upgrades would still reach it.

Trust statement. In a shared suite, the VERSION_MANAGER can replace the code of the token, the registry, the storage, the compliance and the access manager of every suite at once. It does so on a vote of Network governance and after a delay. An Issuer that does not accept this deploys an isolated suite and takes on the responsibility of upgrading it.

Identities

Every ONCHAINID points to one beacon, owned by the IdentityFactory. Upgrading that beacon changes the implementation of every identity.

The factory refuses a new implementation unless it:

  • names this same factory,

  • names the same key registry as the implementation it replaces,

  • has its own initialization locked,

  • reports the version that the upgrader announced.

The upgrade is gated by a dedicated role with an execution delay. It is scheduled first, stays visible during the delay, and can be cancelled before it takes effect.

Two things cannot change through an upgrade of identities. The key registry stays the same contract, so no upgrade can move an identity's keys. And the signing domain of identities is kept constant, because every stored claim is verified against it.

Compliance modules

A compliance module is one upgradeable contract, serving every compliance that binds it. Upgrading it changes the rule for all of them. The upgrade is authorized by the module's own authority, which is separate from any token suite.

If an upgrade changes the types a module declares, each compliance applies the change by calling resyncModuleTypes. See Modular compliance.

What keeps an upgrade safe

Safeguard
What it prevents

Namespaced storage. Every upgradeable contract keeps its state in a storage region derived from a name, not in sequential slots.

A new variable overwriting an old one, or the state of an inherited contract. This class of error has caused serious failures in upgradeable systems built without it.

Coordinated versions.

A suite running mismatched contracts.

Forward-only upgrades.

A return to code that was replaced for a reason.

Publish before upgrade.

Code that reaches suites without having been visible on-chain.

Continuity checks on identities.

An upgrade that silently points every identity at another key registry or another factory.

The compliance and the registry of a circulating token stay in place. They are upgraded, never swapped.

A token whose positions are attributed by a contract that has not seen them.

Role-gated and delayable. Every upgrade path is a role in an access manager.

An upgrade by an unauthorized party, or one that takes effect unseen.

Storage is described under Namespaced storage (ERC-7201).

Who can change the code

Code of
Changed by
The Issuer's protection

A shared suite

VERSION_MANAGER, after a vote of Network governance and a delay

The delay, during which the upgrade is visible. Or choose an isolated suite

An isolated suite

The Issuer's own manager

Its own governance

Identities

The beacon upgrader of the identity layer

The delay, during which the upgrade is visible

A compliance module

Network governance, for the shared modules

Deploy its own instance of the module

Reading versions

Read
Returns

Token.version()

The version of the token implementation, for example 5.0.0.

Identity.version()

The version of the identity implementation.

TREXImplementationAuthority.currentVersion()

The version the shared beacons point to.

Last updated