The Medical Records contract includes a built-in data migration system. This ensures that when the contract logic is upgraded (e.g., adding new fields to a struct), the existing data in storage is automatically updated to match the new format.
- Versioning: The contract tracks a
ContractVersionin storage (default is 0). - Atomicity: The
upgradefunction performs two actions in a single transaction:- Updates the WASM code.
- Runs the
migrate_datalogic.
- Safety: If the migration logic fails (panics), the entire transaction reverts. The contract code remains on the old version, preventing data corruption.
To upgrade the contract, the Admin must perform the following:
- Deploy the new WASM file to the network to get its
wasm_hash. - Call the
upgradefunction on the existing contract:soroban contract invoke \ --id <CONTRACT_ID> \ --source <ADMIN_SECRET> \ --network <NETWORK> \ -- \ upgrade \ --new_wasm_hash <NEW_WASM_HASH>
When you make a "breaking change" to the data structure (e.g., V1 to V2):
-
Increment Version: In
lib.rs, update the constant:const CURRENT_CONTRACT_VERSION: u32 = 2; // Was 1
-
Add Migration Logic: Inside
migrate_data, add a specific handler for the new version gap:if current_version < 2 { // specific logic to transform data from V1 format to V2 migrate_v1_to_v2(env); }
-
Test: Add a test case in
tests/test_migration.rsthat explicitly sets up "Old Data" and verifies it transforms correctly into "New Data".
If a release keeps a legacy function temporarily available, do not remove it immediately. Instead:
- Add
#[deprecated(...)]to the old function. - Register that function in the upgradeability deprecation registry.
- Emit a deprecation warning event from the old function body.
- Point callers to the replacement function and planned removal version.
See docs/deprecation_migration.md for the recommended pattern.