feat(contracts): add storage versioning and migrations to all contracts - #49
Merged
merlik787-droi merged 7 commits intoJul 23, 2026
Conversation
…x#35 - Add pub const VERSION: u32 = 1 to all six contracts - Add DataKey::Version to every DataKey enum - Add V0 snapshot structs (CourseV0, BadgeV0, StakeInfoV0, ProposalV0, QuestV0) so future migrations can decode pre-upgrade records - Implement upgrade_contract (doc-update only where already present) with explicit note to call migrate() after WASM swap - Implement migrate(admin) with ordered version-gate (current < VERSION), idempotency guard, and per-transition comment blocks for v0→v1 - Implement contract_version() returning stored version (defaults 0) - Add SpenderCount to reward-pool DataKey + wire counter in add_approved_spender - Add estimated_storage_footprint to RewardPoolInterface trait and impl - Add migration tests for all six contracts: version initially 0, v0→v1 sets version, double-migrate panics, non-admin panics, data-preservation (Course/Badge/Proposal/Quest/ Submission/StakeInfo/SpenderCount all intact after migrate) - Add docs/upgrade-guide.md describing upgrade semantics, the two-tx procedure, how to write future migration steps, and a coverage table
…rustc ethnum 1.5.2 introduced an unsafe mem::transmute(()) -> TryFromIntError that fails to compile on rustc versions before ~1.86 because the source and target types have different sizes. Pinning to 1.5.0 restores compatibility with the CI toolchain.
ethnum 1.5.0 and 1.5.2 both contain a broken mem::transmute(()) call in error.rs:16 that fails on Rust stable (1.87+). The CI uses dtolnay/rust-toolchain@stable which resolves to the current stable release, making this a hard build failure. ethnum 1.5.3 is the upstream patch release that removes the broken transmute. Only Cargo.lock is updated — ethnum is a transitive dependency via soroban-env-common so no Cargo.toml change is needed.
merlik787-droi
requested changes
Jul 22, 2026
merlik787-droi
left a comment
Contributor
There was a problem hiding this comment.
@Clement-coder remove all test snapshots
…variant The migrate() and contract_version() functions referenced VERSION and DataKey::Version which were never declared, causing a compile error. Also add test_snapshots/ to .gitignore so auto-generated ledger snapshot files are never committed.
Contributor
Author
@merlik787-droi All test snapshots remove, kindly review the PR ? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #35
Adds storage versioning and safe migration infrastructure across all six contracts:
course-registry,badge-nft,reward-pool,stake-vault,governance, andquest-engine.Changes
All six contracts
pub const VERSION: u32 = 1— compile-time schema version constantDataKey::Version— instance-storage slot for the on-chain versionmigrate(admin)— applies pending schema migrations in order, writes new version; panics if already at current version or caller is not admincontract_version()— returns the stored version (defaults to 0 for pre-versioning deploys)upgrade_contractdoc updated to requiremigrate()call after WASM swapV0 snapshot structs
Kept alongside current structs so future migration steps can decode old records:
CourseV0,BadgeV0,StakeInfoV0,ProposalV0,QuestV0reward-pool extras
DataKey::SpenderCountadded; counter wired intoadd_approved_spenderestimated_storage_footprint()added toRewardPoolInterfacetrait and implDocumentation
docs/upgrade-guide.md— describes the two-transaction upgrade procedure, version history, the V0 struct pattern, and a step-by-step guide for writing future migration stepsTests
Migration tests added to every contract:
test_*_contract_version_initial_zerotest_*_migrate_v0_to_v1_sets_versiontest_*_migrate_twice_panicstest_*_migrate_unauthorized_panicstest_*_migrate_v0_to_v1_preserves_*All 201 tests pass (
cargo test— zero failures, zero warnings).Upgrade procedure (summary)
See
docs/upgrade-guide.mdfor full details.