Skip to content

# feat: add contract versioning, migration framework, and frontend compatibility warnings - #199

Merged
Sendi0011 merged 7 commits into
JointSave-org:mainfrom
JemimahEkong:feat/contract-versioning-migration
Jul 27, 2026
Merged

# feat: add contract versioning, migration framework, and frontend compatibility warnings#199
Sendi0011 merged 7 commits into
JointSave-org:mainfrom
JemimahEkong:feat/contract-versioning-migration

Conversation

@JemimahEkong

Copy link
Copy Markdown
Contributor

Overview

This PR introduces a complete contract versioning and migration foundation for JointSave's Soroban contracts, enabling safer future upgrades without requiring full contract replacement or manual state migrations.

The implementation adds version tracking across contracts, migration helpers, frontend compatibility checks, and documentation for future migration workflows.

Closes #184

Smart Contract Changes

Contract Versioning

Added version support to all six contracts:

  • Factory
  • Rotational
  • Target
  • Flexible
  • Reputation
  • YieldStrategy

Changes include:

  • Added VERSION: u32 = 1 constant
  • Added get_version() view function
  • Added version tracking helpers where migration is supported

Migration Framework

Added new migration crate:

smartcontract/migration/

Features:

  • Migratable trait definition
  • Version step validation
  • Migration lineage tracking helpers
  • Migration storage utilities

Migration rules:

  • Versions must increment one step at a time
  • Version jumps are rejected
  • Migration operations are designed to be idempotent

Pool Contract Migration Support

Added migrate(to_version) support for:

  • Rotational
  • Target
  • Flexible
  • Factory

Includes:

  • Admin authorization checks
  • Version validation
  • Migration event emission
  • Placeholder migration hooks for future upgrade logic

Migration Lineage Tracking

Added migrated_from storage tracking for pool and factory contracts.

This allows deployments to preserve migration history and trace contract lineage.

Factory Migration Registry

Added:

register_migration(admin, old_factory, new_factory)

This records relationships between factory versions while maintaining admin-only control.

Reputation & YieldStrategy

Added version tracking only:

  • VERSION
  • get_version()

These contracts remain standalone and do not require migration execution.

Frontend Changes

Contract Version Fetching

Added contract version awareness to:

  • Rotational pools
  • Target pools
  • Flexible pools

New helpers:

  • fetchContractVersion()
  • isContractVersionUnknown()

Pool state objects now include:

  • contractVersion

Known Version Registry

Added:

KNOWN_CONTRACT_VERSIONS

This keeps frontend compatibility expectations centralized.

Unknown Version Warning UI

Added user-facing warnings when a pool contract version is newer than the frontend supports.

Warnings added to:

  • Pool cards
  • Group details page

Users will see:

This pool uses a newer contract version. Some features may not be available. Please update the app.

Documentation

Added:

smartcontract/MIGRATIONS.md

Documentation covers:

  • Migration architecture
  • Creating new migrations
  • Testnet migration process
  • Verification steps
  • Rollback considerations
  • Frontend compatibility handling
  • Contract-specific migration notes

Added example migration script:

migrations/migrate_rotational_v1_to_v2.sh

Demonstrates:

  1. Checking current version
  2. Deploying upgraded WASM
  3. Running migration
  4. Verifying new version
  5. Performing smoke tests

Testing

Added contract version frontend tests covering:

  • Matching versions
  • Older contract versions
  • Newer contract versions
  • Missing version values
  • Version mismatch scenarios

Results:
npm run test:unit
105/105 tests passing

Additional validation:
cargo fmt --check ✅

TypeScript validation confirmed no new errors were introduced in modified files.

Validation Notes

Check Result
Rust formatting ✅ Passed
Frontend unit tests ✅ 105/105 passed
Contract version tests ✅ 5/5 passed
Migration documentation ✅ Added
Migration example script ✅ Added

cargo build and cargo test could not be executed locally due to missing MSVC Build Tools environment dependency, not related to code changes.

Impact

This change provides:

  • Safer future contract upgrades
  • Clear contract version tracking
  • Migration lineage visibility
  • Frontend compatibility protection
  • A documented upgrade workflow for maintainers

Existing contracts remain fully backward compatible at version 1, and existing functionality is preserved.

…banner

Smart contracts:
- Add Migratable trait and migration helpers in smartcontract/migration/ crate
- Add VERSION const + get_version() to all 6 contracts (rotational, target, flexible, factory, reputation, yield-strategy)
- Add migrate() with admin auth and version-step validation to pool + factory contracts
- Add migrated_from lineage tracking to pool and factory contracts
- Add register_migration() to Factory contract
- Add cargo fmt formatting fixes across all contracts

Frontend:
- Add KNOWN_CONTRACT_VERSIONS constant and isContractVersionUnknown() helper
- Add contractVersion field to pool state types and fetch it on-chain
- Add version warning banners in pool cards and group details pages
- Add contract-version.test.ts unit tests
- Add contract-version.test.ts to test:unit script

Documentation:
- Add MIGRATIONS.md with full migration guide, testnet deployment steps, rollback notes
- Add sample migration script (migrate_rotational_v1_to_v2.sh)
@Sendi0011
Sendi0011 self-requested a review July 25, 2026 17:18

@Sendi0011 Sendi0011 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comprehensive PR! The migration framework is well-designed. A few issues to address before merge:

Critical:

  1. migrate() idempotency claim is incorrect — The doc says running migrate(2) twice is safe, but the code does assert!(to_version == current + 1). If current is already 2, the second call fails with 2 == 3 → false. Either update the docs to say "not idempotent, will reject re-runs" or change the logic to treat to_version == current as a no-op success.

  2. package.json references lib/pending-transactions.test.ts in the test:unit script but that file doesn't exist in this PR — it's from another branch. This will break CI.

Improvements:

  1. fetchContractVersion adds an extra RPC call per pool load — On the dashboard with many pool cards, this means N additional calls. Consider batching or caching to avoid performance regression.

  2. group-details.tsx uses an inline IIFE in JSX — The (() => { ... })() pattern is hard to read and debug. Extract to a named component or helper function.

  3. KNOWN_CONTRACT_VERSIONS includes reputation and yieldStrategy but the frontend never fetches their versions. Remove them or add a comment explaining they're reserved for future use.

  4. Test duplicates isContractVersionUnknown — The test file re-implements the function to avoid React imports. Extract the logic to a pure util file (no React deps) so both can import from the same source.

@JemimahEkong

JemimahEkong commented Jul 25, 2026 via email

Copy link
Copy Markdown
Contributor Author

- Add migration idempotency (early return when to_version == current_version) for all 4 contracts
- Cache fetchContractVersion RPC results to avoid redundant fetches for same contract
- Extract isContractVersionUnknown pure utility to frontend/lib/contract-version.ts
- Extract VersionWarning component in group-details.tsx (replace IIFE pattern)
- Remove reputation and yieldStrategy from KNOWN_CONTRACT_VERSIONS (no migrate() functions)
- Add 12 migration idempotency Rust tests (3 per contract)
- Merge main to restore CHAT_MESSAGE_MAX_LENGTH and CHAT_RATE_LIMIT_MS constants
- Fix Prettier formatting in group-details.tsx, pool-card.tsx, useJointSaveContracts.ts
- Update test:unit script to include new test files from main
…om/JemimahEkong/Joint_Save into feat/contract-versioning-migration

# Conflicts:
#	frontend/lib/constants.ts
#	frontend/package.json
Trailing ─── line after closing brace caused 62 compilation errors
in jointsave-flexible during cargo test

@Sendi0011 Sendi0011 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job 👍 - Approving

@Sendi0011
Sendi0011 merged commit c33883e into JointSave-org:main Jul 27, 2026
4 checks passed
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.

[Feature] Implement contract state migration and versioning system for safe future upgrades

2 participants