This repository implements a comprehensive upgrade system for Soroban smart contracts with governance, migration support, and rollback capabilities.
- ✅ Multi-Signature Governance - Require multiple approvals for upgrades
- ✅ Storage Migration - Automated data migration between versions
- ✅ Rollback Support - Emergency rollback to previous versions
- ✅ Upgrade History - Complete audit trail of all upgrades
- ✅ Version Tracking - Semantic versioning for contracts
- ✅ Testing Framework - Comprehensive upgrade testing
- ✅ Automated Scripts - CLI tools for upgrade management
// In your contract initialization
use upgrade::{init_admin, init_upgrade_system};
pub fn initialize(env: Env, admin: Address) {
admin.require_auth();
init_admin(&env, &admin);
init_upgrade_system(&env);
}# Using the upgrade script
./contracts/scripts/upgrade-contract.sh credit-score testnet
# Or manually
soroban contract invoke \
--id $CONTRACT_ID \
--fn upgrade \
-- \
--admin $ADMIN_ADDRESS \
--new_wasm_hash $NEW_WASM_HASH# Using the rollback script
./contracts/scripts/rollback-contract.sh credit-score testnet
# Or manually
soroban contract invoke \
--id $CONTRACT_ID \
--fn rollback \
-- \
--admin $ADMIN_ADDRESScontracts/
├── governance/
│ └── src/
│ └── upgrade_proposal.rs # Multi-sig upgrade manager
├── credit-score/
│ └── src/
│ └── upgrade.rs # Contract-specific upgrade logic
├── fraud-detect/
│ └── src/
│ └── upgrade.rs # Contract-specific upgrade logic
├── scripts/
│ ├── upgrade-contract.sh # Automated upgrade script
│ └── rollback-contract.sh # Automated rollback script
├── tests/
│ └── upgrade.test.rs # Comprehensive upgrade tests
└── docs/
├── upgrade-guide.md # Detailed upgrade guide
└── upgrade-proposal-template.md # Proposal template
┌─────────────────────────────────────────────────────────────┐
│ Upgrade Lifecycle │
└─────────────────────────────────────────────────────────────┘
1. Propose Upgrade
├─ Build new WASM
├─ Upload to network
└─ Create proposal
2. Governance Approval
├─ Collect signatures
├─ Verify quorum
└─ Queue for execution
3. Execute Upgrade
├─ Run pre-upgrade checks
├─ Execute migrations
├─ Update WASM
└─ Verify success
4. Post-Upgrade
├─ Monitor behavior
├─ Verify functionality
└─ Update documentation
5. Rollback (if needed)
├─ Detect issues
├─ Execute rollback
└─ Restore previous state
pub fn upgrade(env: Env, admin: Address, new_wasm_hash: BytesN<32>) {
admin.require_auth();
verify_admin(&env, &admin);
// Execute migrations
let old_version = get_version(&env);
execute_migrations(&env, old_version, old_version + 1);
// Perform upgrade
env.deployer().update_current_contract_wasm(new_wasm_hash);
// Update version
set_version(&env, old_version + 1);
}pub fn upgrade_with_migration(
env: Env,
admin: Address,
new_wasm_hash: BytesN<32>,
migration_notes: String,
) {
admin.require_auth();
verify_admin(&env, &admin);
let old_version = get_version(&env);
// Store rollback hash
store_rollback_hash(&env, &new_wasm_hash);
// Execute migrations
execute_migrations(&env, old_version, old_version + 1);
// Perform upgrade
env.deployer().update_current_contract_wasm(new_wasm_hash);
// Record upgrade
record_upgrade(&env, old_version, old_version + 1, new_wasm_hash, admin, migration_notes);
}pub fn rollback(env: Env, admin: Address) {
admin.require_auth();
verify_admin(&env, &admin);
let rollback_hash = get_rollback_hash(&env)
.expect("No rollback available");
env.deployer().update_current_contract_wasm(rollback_hash);
let current_version = get_version(&env);
set_version(&env, current_version - 1);
}use upgrade_manager::UpgradeManagerClient;
// Deploy and initialize
let upgrade_mgr = UpgradeManagerClient::new(&env, &upgrade_manager_id);
upgrade_mgr.initialize(&admin, &3, &604800); // 3 approvals, 7-day timeout
// Add authorized upgraders
upgrade_mgr.add_authorized(&admin, &upgrader1);
upgrade_mgr.add_authorized(&admin, &upgrader2);
upgrade_mgr.add_authorized(&admin, &upgrader3);// Propose upgrade
let proposal_id = upgrade_mgr.propose_upgrade(
&proposer,
&UpgradeType::ContractUpgrade,
&target_contract,
&new_wasm_hash,
&migration_data,
&description,
);
// Collect approvals
upgrade_mgr.approve_upgrade(&proposal_id, &approver1);
upgrade_mgr.approve_upgrade(&proposal_id, &approver2);
upgrade_mgr.approve_upgrade(&proposal_id, &approver3);
// Execute
let result = upgrade_mgr.execute_upgrade(&proposal_id, &executor);fn execute_migrations(env: &Env, from_version: u32, to_version: u32) {
match (from_version, to_version) {
(0, 1) => migrate_v0_to_v1(env),
(1, 2) => migrate_v1_to_v2(env),
(2, 3) => migrate_v2_to_v3(env),
_ => {}
}
}
fn migrate_v1_to_v2(env: &Env) {
// Add new config field
let old_config: ConfigV1 = get_config(env);
let new_config = ConfigV2 {
old_field: old_config.old_field,
new_field: default_value(),
};
set_config(env, &new_config);
// Extend TTL
extend_storage_ttl(env);
}# Run all upgrade tests
cd contracts
cargo test upgrade
# Run specific test
cargo test test_upgrade_with_migration
# Run with output
cargo test upgrade -- --nocapture# 1. Deploy to testnet
soroban contract deploy \
--wasm target/wasm32-unknown-unknown/release/contract.wasm \
--network testnet
# 2. Initialize
soroban contract invoke \
--id $CONTRACT_ID \
--fn initialize \
-- --admin $ADMIN
# 3. Test upgrade
./contracts/scripts/upgrade-contract.sh contract-name testnet
# 4. Verify
soroban contract invoke \
--id $CONTRACT_ID \
--fn get_versionAutomated upgrade script with safety checks.
./contracts/scripts/upgrade-contract.sh <contract-name> <network> [--emergency]
# Examples
./contracts/scripts/upgrade-contract.sh credit-score testnet
./contracts/scripts/upgrade-contract.sh fraud-detect mainnet
./contracts/scripts/upgrade-contract.sh credit-score testnet --emergencyFeatures:
- Builds and optimizes WASM
- Uploads to network
- Creates backup
- Executes upgrade
- Verifies success
- Logs history
Automated rollback script.
./contracts/scripts/rollback-contract.sh <contract-name> <network>
# Examples
./contracts/scripts/rollback-contract.sh credit-score testnet
./contracts/scripts/rollback-contract.sh fraud-detect mainnetFeatures:
- Attempts automatic rollback
- Falls back to manual process
- Shows upgrade history
- Provides step-by-step instructions
# Deploy to testnet
soroban contract deploy --wasm contract.wasm --network testnet
# Test thoroughly
# ... run tests ...
# Only then deploy to mainnet
soroban contract deploy --wasm contract.wasm --network mainnetconst MAJOR_VERSION: u32 = 1;
const MINOR_VERSION: u32 = 2;
const PATCH_VERSION: u32 = 3;
pub fn get_version(env: &Env) -> (u32, u32, u32) {
(MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION)
}#[contracttype]
pub struct UpgradeRecord {
pub from_version: u32,
pub to_version: u32,
pub wasm_hash: BytesN<32>,
pub timestamp: u64,
pub executor: Address,
pub notes: String,
}
fn record_upgrade(env: &Env, record: UpgradeRecord) {
let mut history = get_history(env);
history.push_back(record);
set_history(env, &history);
}fn store_rollback_hash(env: &Env, current_hash: &BytesN<32>) {
env.storage().persistent().set(&symbol_short!("rollback"), current_hash);
env.storage().persistent().extend_ttl(&symbol_short!("rollback"), MONTH_LEDGERS, MONTH_LEDGERS);
}fn extend_storage_ttl(env: &Env) {
const YEAR_LEDGERS: u32 = 6_307_200;
let keys = vec![
symbol_short!("config"),
symbol_short!("admin"),
symbol_short!("data"),
];
for key in keys {
if env.storage().persistent().has(&key) {
env.storage().persistent().extend_ttl(&key, YEAR_LEDGERS, YEAR_LEDGERS);
}
}
}# Check contract status
soroban contract invoke --id $CONTRACT_ID --fn get_version
# Check upgrade history
soroban contract invoke --id $CONTRACT_ID --fn get_upgrade_history
# Attempt rollback
./contracts/scripts/rollback-contract.sh contract-name network# Verify storage integrity
soroban contract invoke --id $CONTRACT_ID --fn verify_storage
# Check specific keys
soroban contract invoke --id $CONTRACT_ID --fn get_config# Get current version
soroban contract invoke --id $CONTRACT_ID --fn get_version
# Compare with expected
echo "Expected: 2, Actual: $VERSION"
# If mismatch, investigate upgrade history
soroban contract invoke --id $CONTRACT_ID --fn get_upgrade_history- Admin Authorization - Always verify admin before upgrades
- Multi-Sig Governance - Use multiple approvers for mainnet
- Testnet Testing - Thoroughly test before mainnet deployment
- Rollback Plan - Always have a rollback strategy
- Monitoring - Monitor contract behavior post-upgrade
- Audit - Security audit for major upgrades
- Upgrade Guide - Comprehensive upgrade documentation
- Proposal Template - Template for upgrade proposals
- Soroban Docs - Official Soroban documentation
- Test Suite - Upgrade test examples
For questions or issues:
- Open an issue on GitHub
- Join our Discord community
- Email: support@example.com
[Your License]