World upgrades
EVE Frontier world-contracts ships as versioned releases. Each upgrade creates a new package object (new address); older versions stay on-chain and stay callable.
How package upgrades work on Sui
Read these in order:
Object and package versioning — User packages get a new package ID per publish/upgrade; the family is tied by original ID and UpgradeCap.
Upgrading packages — Compatibility rules,
UpgradeCap/ tickets,sui client upgrade, old packages remain on-chain.Move package management —
published-at, dependencies, upgraded dependencies.
Where the IDs live
After a world upgrade, use published-at (per environment) as the default for new transactions and for tooling that resolves module paths—unless you intentionally depend on an older version.
In world-contracts, each environment is recorded in contracts/world/Published.toml:
original-id— First package in the upgrade family (the original publish address).published-at— Latest package ID; use for app config and new world APIs when you want current bytecode.
Bump your Move dependency to the release tag you need (e.g. v0.0.21), refresh Move.lock, then republish or upgrade your extension with your UpgradeCap if the world API you use changed.
TypeScript / dApps
Use a configurable packageId in moveCall targets (see Interfacing with the EVE Frontier World). After an upgrade, set packageId from published-at for that network, rebuild, and redeploy.
MVR (future)
Move Registry (MVR) resolves a stable name (e.g. @evefrontier/world) to the latest package and helps canonicalize types. TS SDK tooling can bake in MVR resolution at build time. Operator setup: MVR setup in world-contracts.
Migration checklist
If you are still pinned to an old world package ID:
dApps
Point config at published-at when you need new functions or fixes.
Move extensions
Bump world-contracts, test, upgrade your package if needed.
Indexers
Do not assume a single type prefix across upgrades, expand filters or use canonical type resolution (GraphQL type; see also MystenLabs/sui#12853 for event edge cases).
Which package ID for what?
New functions (only in upgraded bytecode)
Latest (published-at) in moveCall targets.
Existing flows (unchanged public APIs)
Original or latest—both work.
Object lookups / type filters (e.g. getOwnedObjects)
Use the package ID in the object’s type string (often original for objects from before the upgrade, e.g. originalId::gate::JumpPermit). Types are not auto-retagged.
Example: A new invalidate entrypoint ships on the upgraded package(v0.0.20). Issue JumpPermit can use latest or original; invalidate must use latest.
GraphQL: type accepts a type string with any package address in the lineage at or after the defining (first) package for that type and returns the canonical form—useful when comparing types across upgrades.
Last updated

