Skip to content

Contract Dependency Graph for Atomic Multi-Contract Upgrade Sequencing #27

Description

@elizabetheonoja-art

Problem Statement / Feature Objective

The current upgrade process for Soroban contracts (tariff-oracle, settlement, resource-token, meter-aggregator) is manual and order-dependent. Deploying a new version of the settlement contract that expects a different interface from the resource-token contract can cause the system to enter an inconsistent state where some contracts reference old interfaces while others reference new interfaces. During the upgrade window, cross-contract calls may fail due to ABI mismatch, breaking settlement finalization. A dependency graph must be introduced that models inter-contract interface dependencies, validates upgrade order, and supports atomic multi-contract upgrades via a coordinator contract.

Technical Invariants & Bounds

  • Contracts: tariff-oracle, settlement, resource-token, meter-aggregator, crl (5 contracts).
  • Dependencies are directional: contract A depends on B if A calls B via env.invoke_contract().
  • Interface version: each contract exposes an INTERFACE_VERSION: u32 constant; breaking changes increment it.
  • Upgrade window: max 30 ledgers (~150 seconds) to complete an atomic multi-contract upgrade.
  • Coordinator contract: a new upgrade-coordinator contract that receives a batch of (contract_address, wasm_hash, new_interface_version) tuples and applies them in topological order.
  • Rollback: if any upgrade in the batch fails, all previous upgrades in the batch must be reverted to the previous WASM hash and interface version.
  • Storage migration: each contract may define a migrate_storage(from_version, to_version) hook called by the coordinator after the WASM upgrade.

Codebase Navigation Guide

  • contracts/upgrade-coordinator/src/lib.rs — new contract for coordinating batched upgrades.
  • contracts/upgrade-coordinator/src/dag.rs — topological sort of contract dependencies.
  • contracts/*/src/lib.rs — each contract exports INTERFACE_VERSION and migrate_storage().
  • contracts/common/src/upgrade.rs — shared upgrade utilities.

Implementation Blueprint

  1. Define a DependencyGraph struct that reads INTERFACE_VERSION from each contract and builds a DAG. Validate no cycles exist.
  2. Implement topological sort: Kahn algorithm. Return error if ordering would require downgrading a dependency.
  3. Create the upgrade-coordinator contract with fn propose_upgrade(batch: Vec<UpgradeStep>) that stores the proposal, and fn execute_upgrade(batch_id) that applies steps in order, calling migrate_storage between WASM swaps.
  4. On failure of any step, the coordinator reverts all prior steps in reverse order, restoring previous WASM hashes and storage states.
  5. Add a GET /api/v1/contracts/dependencies admin endpoint showing the current DAG and interface versions.
  6. Write property-based tests that generate random DAGs and validate that topological ordering always respects dependency edges. Write integration test with a 3-contract upgrade cycle.

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official Campaign

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions