Skip to content

implement upgrade safety gate and post-upgrade invariant tests#497

Open
Kingajong wants to merge 10 commits into
Pulsefy:mainfrom
Kingajong:main
Open

implement upgrade safety gate and post-upgrade invariant tests#497
Kingajong wants to merge 10 commits into
Pulsefy:mainfrom
Kingajong:main

Conversation

@Kingajong
Copy link
Copy Markdown

Closes #432
test(contract): implement upgrade safety gate and post-upgrade invariant tests

Implement a robust suite of integration tests in upgrade_test.rs to validate the upgrade safety gate mechanism, window constraints, and post-upgrade invariants.

Acceptance Criteria Implemented:

  • AC1: Verify upgrades are strictly blocked outside the allowed window.
  • AC2: Ensure post-upgrade invariant checks (e.g., corrupt fee states) fail deterministically with an InternalError.
  • AC3: Verify indexable upgrade events are emitted correctly for tracking.

Test Coverage (upgrade_test.rs):

  • upgrade_safety_gate_blocks_upgrade_outside_window
  • upgrade_safety_gate_invariant_failure_deterministic
  • upgrade_safety_gate_emits_events
  • upgrade_safety_gate_post_upgrade_invariants_enforced (Happy path ceremony)
  • upgrade_safety_gate_blocks_double_start (Rejects concurrent upgrades)
  • upgrade_safety_gate_non_admin_blocked (Rejects unauthorized upgrades)

Upgrade Flow Validated:

  1. set_upgrade_window(start, end) -> Defines the validity window.
  2. start_upgrade(new_version) -> Emits UpgradeStarted, sets in-progress flag.
  3. upgrade(new_wasm_hash) -> Executes the WASM swap.
  4. complete_upgrade(new_version) -> Runs migrate(), enforces invariants, emits UpgradeCompleted.

Kingajong added 7 commits May 29, 2026 15:53
…alidation

- Add 3 new DataKey variants: UpgradeWindowStart, UpgradeWindowEnd, UpgradeInProgress
- Implement set_upgrade_window() to configure upgrade time bounds
- Implement get_upgrade_window() to retrieve current window settings
- Implement is_upgrade_window_active() for ledger timestamp validation
- Implement set_upgrade_in_progress() and is_upgrade_in_progress() for concurrency control
- Implement assert_post_upgrade_invariants() with 4 deterministic checks
- Invariant failure triggers panic for atomic rollback
- Addresses AC2: Post-upgrade invariants enforced deterministically
- Issue Pulsefy#432
- Add UpgradeStartedEvent with admin, schema_version, old_version, new_version, window_start, window_end
- Add UpgradeCompletedEvent with admin, schema_version, old_version, new_version
- Implement publish_upgrade_started() emitter with TOPIC_ADMIN indexing
- Implement publish_upgrade_completed() emitter with TOPIC_ADMIN indexing
- Events include schema_version=2 for consistency with existing patterns
- Admin address indexed as #[topic] for event filtering
- Addresses AC3: Indexers can track upgrades from events alone
- Issue Pulsefy#432
…lidation

- Update imports: add publish_upgrade_started, publish_upgrade_completed
- Modify migrate(): add assert_post_upgrade_invariants call before return
- Add set_upgrade_window(): admin-only, sets UpgradeWindowStart/End
- Add start_upgrade(): admin-only, window-gated, sets UpgradeInProgress
  * Validates is_upgrade_window_active() - fails with InvalidAmount if outside window
  * Validates not is_upgrade_in_progress() - prevents concurrent upgrades
  * Emits UpgradeStartedEvent with window bounds
- Add complete_upgrade(): admin-only, finalizes upgrade with invariant checks
  * Validates is_upgrade_in_progress()
  * Calls migrate() to trigger invariant validation
  * Emits UpgradeCompletedEvent
- Three-step ceremony: set_upgrade_window -> start_upgrade -> complete_upgrade
- Addresses AC1 (window gating), AC2 (invariant validation), AC3 (events)
- Issue Pulsefy#432
- Add pub fn set_upgrade_window() - configure upgrade time window bounds
- Add pub fn get_upgrade_window() - query current upgrade window settings
- Add pub fn start_upgrade() - window-gated upgrade initiation (AC1)
- Add pub fn complete_upgrade() - invariant-validated upgrade completion (AC2)
- All functions delegated to admin module for core logic
- Full docstrings with usage examples and error codes
- Addresses AC1 (window gating), AC2 (invariant validation), AC3 (via events)
- Issue Pulsefy#432
Ignore commit helper scripts (commit_*.ps1, commit_*.sh)
that may be generated per-issue for deployment convenience.
Adds 6 tests for the three-step upgrade ceremony with window gating
and post-upgrade invariant validation:

1. upgrade_safety_gate_blocks_upgrade_outside_window
   - Verifies AC1: upgrades blocked when no window is set, before window
     start, and after window end. Confirms success only within window.

2. upgrade_safety_gate_post_upgrade_invariants_enforced
   - Happy path: full ceremony (start_upgrade -> migrate -> complete_upgrade)
     validates invariants pass and upgrade_in_progress is cleared.

3. upgrade_safety_gate_invariant_failure_deterministic
   - Verifies AC2: deliberately corrupts fee_bps to 99999 (>10k bound),
     calls try_migrate(), asserts it returns Err(InternalError).
     Then restores config and completes upgrade cleanly.

4. upgrade_safety_gate_emits_events
   - Verifies AC3: captures event count before/after ceremony, asserts
     at least UpgradeStarted + UpgradeCompleted were emitted.

5. upgrade_safety_gate_blocks_double_start
   - Verifies concurrent upgrade is rejected; after complete_upgrade a
     new start is allowed.

6. upgrade_safety_gate_non_admin_blocked
   - Verifies non-admin cannot call set_upgrade_window or start_upgrade.
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 29, 2026

@Kingajong 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

@Cedarich
Copy link
Copy Markdown
Contributor

Fix workflow

- admin.rs: reorder imports alphabetically, collapse start_upgrade sig,
  split publish_upgrade_started call args
- lib.rs: collapse start_upgrade sig to single line
- upgrade_test.rs: normalize assert!/chained-call formatting per fmt
@Cedarich
Copy link
Copy Markdown
Contributor

Please fix workflow

@Cedarich
Copy link
Copy Markdown
Contributor

Please fix workflow

@Cedarich
Copy link
Copy Markdown
Contributor

@Kingajong

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.

32. Upgrade Safety Gate (Explicit Upgrade Window + Post-Upgrade Invariants)

2 participants