Skip to content

feat: add contract upgrade/migration framework with time-lock governance#201

Open
GazzyLee wants to merge 1 commit into
BCPathway:mainfrom
GazzyLee:feat/contract-upgrade-migration
Open

feat: add contract upgrade/migration framework with time-lock governance#201
GazzyLee wants to merge 1 commit into
BCPathway:mainfrom
GazzyLee:feat/contract-upgrade-migration

Conversation

@GazzyLee
Copy link
Copy Markdown

Summary

Implements a secure, two-phase contract upgrade mechanism with a time-lock delay, version tracking, migration guards, and multi-sig support. Additionally fixes several critical bugs discovered in the token and admin crates.

Bug Fixes

  • contracts/token: Removed duplicate Allowance(Address,Address) variant from DataKey enum
  • contracts/token: Cleaned dead code after early return in read_allowance()
  • contracts/token: Fixed transfer_from() double move_balance and write_allowance calls
  • contracts/token: Fixed burn_from() double write_allowance calls
  • contracts/admin: Removed undefined action_type field from Proposal construction

Upgrade Architecture

The upgrade follows a three-phase lifecycle with governance safeguards:

  1. upgrade(new_wasm_hash) (admin-only) — Schedules a pending upgrade by storing the target WASM hash and setting a deadline = current ledger + UPGRADE_DELAY_LEDGERS (5000, ~7 hours). Emits UPGRADE_SCHEDULED event.

  2. execute_upgrade() (anyone, after deadline) — Anyone can call once the deadline passes. Invokes update_current_contract_wasm() and clears the pending upgrade state. Emits UPGRADE_EXECUTED event. Panics if no upgrade is pending or if called before the deadline.

  3. migrate(version) (admin-only) — Updates the on-chain contract version number. Panics if a pending upgrade exists (must execute first), if version ≤ current version, or if caller is not admin. Emits MIGRATED event.

Upgrade via Multi-Sig

Added TokenAction::Upgrade(BytesN<32>) variant to the admin crate, enabling multi-sig proposals for contract upgrades via propose_actionapprove_proposalexecute_proposal.

New Data Keys

Key Type Purpose
ContractVersion u32 Current contract version number
PendingUpgradeHash BytesN<32> Pending WASM hash for scheduled upgrade
UpgradeDeadline u32 Ledger sequence after which upgrade can be executed

New Token Error

Version

  • version() now returns "2.0.0"

SDK Updates

  • client.ts: Added executeUpgrade(source), migrate(version, source), getContractVersion() methods; proposeAction() now accepts { Upgrade: [wasmHash] } action type
  • events.ts: Added UPGRADE_SCHEDULED, UPGRADE_EXECUTED, MIGRATED event types
  • README.md: Documented three-phase upgrade lifecycle with code examples

Testing

  • 41 tests covering all functionality: transfers, allowances, burns, ownership, roles, pause, batch operations, upgrade scheduling, deadline enforcement, version migration, and guard conditions
  • All 41 tests passing
  • SDK: 12 tests passing

Notes

  • The actual WASM replacement (update_current_contract_wasm) requires a properly compiled Soroban WASM and cannot be fully exercised in native unit tests — recommended for integration/acceptance testing
  • UPGRADE_DELAY_LEDGERS = 5000 as a module-level const for governance safety

Closes #161

- Fix critical contract bugs: duplicate DataKey, dead code, allowance/token accounting
- Add TokenAction::Upgrade variant for multi-sig upgrade proposals
- Implement two-phase upgrade: upgrade() schedules with delay, execute_upgrade() replaces WASM
- Implement migrate() with strict version-increasing enforcement
- Add contract_version() view function and bump version() to 2.0.0
- Set UPGRADE_DELAY_LEDGERS = 5000 (~7 hours) for governance safety
- Add UPGRADE_SCHEDULED, UPGRADE_EXECUTED, MIGRATED events
- Rewrite test.rs with 41 tests covering all functionality (39 pass core, 2 verify upgrade scheduling)
- Update SDK client.ts with executeUpgrade(), migrate(), getContractVersion() methods
- Update SDK events.ts with new event types
- Update SDK README.md with full upgrade/migration documentation
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 31, 2026

@GazzyLee Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement contract upgrade mechanism with version migration support

1 participant