> For the complete documentation index, see [llms.txt](https://docs.t-rex.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.t-rex.network/guides/issuer/27.-upgrade-a-suite.md).

# 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](/guides/issuer/01.-deploy-a-token-suite.md)); 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

| Actor              | Role in this flow                                                                                    | What they hold                                                                                    |
| ------------------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| 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

```mermaid
sequenceDiagram
    participant Gov as Network governance
    participant NetAM as Access manager of the network
    participant IA as TREXImplementationAuthority
    participant Issuer
    participant AM as TREXAccessManager
    participant Beacon as Suite beacons
    participant Platform

    Gov->>IA: publish(version, implementations)
    IA-->>Platform: VersionPublished(version, implementations)
    alt shared suite
        Gov->>NetAM: schedule(authority, upgrade(version), when)
        Note over Gov,IA: the delay of the VERSION_MANAGER role runs
        Gov->>IA: upgrade(version)
        IA->>IA: caller holds VERSION_MANAGER, version published and newer
        IA->>Beacon: upgradeTo, on the five shared beacons
        IA-->>Platform: SuiteUpgraded(version, implementations)
    else isolated suite
        Platform->>IA: implementationsFor(version) (read)
        Issuer->>AM: execute(beacon, upgradeTo(implementation)), for each beacon
        AM->>Beacon: upgradeTo(implementation)
        Beacon-->>Platform: Upgraded(implementation)
    end
    Platform->>Platform: read Token.version() and check the suite
```

## 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:**

1. The caller holds the platform `VERSION_MANAGER` role. Otherwise the call reverts with `AccessManagedUnauthorized`.
2. The version was not published before. Otherwise `VersionAlreadyPublished`.
3. 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:**

1. The caller holds the platform `VERSION_MANAGER` role. Otherwise `AccessManagedUnauthorized`. The call was scheduled and its delay has elapsed. Otherwise the manager reverts with `AccessManagerNotScheduled` or `AccessManagerNotReady`.
2. The version is greater than the active version. Otherwise `VersionNotNewer`.
3. 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:**

1. The caller may call `upgradeTo` on the beacon through the manager. By default that requires `ADMIN_ROLE`. Otherwise the call reverts with `AccessManagerUnauthorizedCall`.
2. The beacon's owner is the caller: the manager, or the admin account for the manager's own beacon. Otherwise the beacon reverts.
3. 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 and `implementations()` 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

| Symptom                                                                       | Cause                                                                                                              | Fix                                                                                 |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `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 `VersionPublished` and `SuiteUpgraded` on 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 `upgradeTo` on 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](/guides/issuer/01.-deploy-a-token-suite.md) : where shared or isolated is chosen
* [25 Commission a suite and grant roles](/guides/issuer/25.-commission-a-suite-and-grant-roles.md) : mapping an operation to a role
* [12 Remove a compliance rule](/guides/issuer/12.-remove-a-compliance-rule.md) : a module is handled separately from the suite
* [16 Pause and unpause a token](/guides/agents/16.-pause-and-unpause-a-token.md) : protecting the asset during an upgrade


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.t-rex.network/guides/issuer/27.-upgrade-a-suite.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
