How to

Upgrading a contract

Records keep the history they were written under. When you change a contract that already has records, the old version is archived (it keeps reading old records), and each record moves to the new version through a signed upgrade action declared in the new contract.

1. Add an upgrade action

The new version names the exact artifact it upgrades from:

action Upgrade(owner: Identity)
    authorize dhl
    certify upgrade from aacc19c23739aabbc2b146b7e5a8cf34f4ef9b1b3cd3b2ea1a9a158f3a9d871e
    validate
        state.revision > 0
        context.signer == owner
        owner == state.owner
    apply
        state.revision = state.revision + 1

The Workbench tells you the running version's id when you try to install a new version without one.

2. If the state changes shape, add migrate

action Upgrade(owner: Identity)
    authorize dhl
    certify upgrade from 9f3c…e1
    migrate
        rename body -> text
        drop legacy_flag
    validate
        state.revision > 0
    apply
        state.revision = state.revision + 1

Rules, checked when compiling and again when loading:

  • Every old field is kept by name, renamed, or explicitly dropped. Nothing disappears implicitly.
  • New fields take their declared default (or their type's zero value).
  • Allowed value changes: the same type; Text(len=a) to Text(len=b) with b ≥ a; T to T?; a list or map growing its capacity. Narrowing, numeric conversions and enum changes are refused.
  • A private field becomes public only with an explicit expose <field> line.
  • Struct definitions used by state cannot change yet.

3. Install and upgrade the records

Install the new version from the The Workbench. The old one moves to contracts/archived/, and records not yet upgraded still read in their old version. Each record moves when someone signs its Upgrade action. For Mandala's built-in contracts, Mandala signs these upgrades at startup under your delegation, and retries what fails at the next start.

In a repository

Keep the previous version's exact source beside the contract, in an archived/ folder (contracts/std/business/archived/), so every node can still read records written under it. Never edit an archived file.