mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 14:48:06 -05:00
* refactor: switch to multitiered governance with multisigs * feat: add scripts for assisting with upgrading contracts and * test: add tests for governance upgrade * chore: install Foundry with Hardhat compatability * fix: add separate intializeGovernance function for upgrading Uses reinitializer modifier for proper security around function call * feat: migrate new function to AccessControl governance * test: full end to end upgrade typescript test * chore: add hardhat-upgrade * chore: add foundry outputs to gitignore * test: add Foundry upgrade script and test for deployed contracts * refactor: update PCR0 inputs to be 32 bytes for GCP image hashes Still pad to 48 bytes to ensure compatibility with mobile app. * feat: add PCR0 migration script + test file * fix: use custom natspec to prevent constructor warnings on upgrade * test: cleanup tests and add role transfer to upgrade script * test: add deployed libraries to foundry.toml for proper library linking * chore: add /contracts/broadcast to gitignore for foundry deployments * fix: set variable in initializer instead of defining in declaration * test: improve upgrade test script to check all state variables * docs: better explain safety behind using unsafeSkipStorageCheck * doc: add guide for upgrading to AccessControl governance * style: change multisig role names CRITICAL_ROLE -> SECURITY_ROLE (3/5) STANDARD_ROLE -> OPERATIONRS_ROLE (2/5) * refactor: change OFAC + CSCA root update functions to 2/5 multisig * fix: package version clashes + outdated code from old ver of packages OpenZeppelin v5.5.0 no longer requires __UUPS_Upgradeable_Init, new OZ version requires opcodes that need cancun evmVersion, hard defining @noble/hashes led to clashes with other dependencies * fix: fix PCR0 tests broken from change in byte size * feat: add contract upgrade tooling with Safe multisig integration - Add unified 'upgrade' Hardhat task with automatic safety checks - Add deployment registry for version tracking - Add Safe SDK integration for auto-proposing upgrades - Update UPGRADE_GUIDE.md with new workflow documentation - Validate version increments, reinitializer, and storage layout * fix: revert fix on Hub V1 contract that is not supported * style: update upgraded contracts to not use custom:version-history * fix: V1 test requires old style as well * fix: correct registry currentVersion to reflect actual deployed versions On-chain verification confirmed all contracts are using OLD Ownable2StepUpgradeable: - Hub: 2.11.0 (was incorrectly 2.12.0) - Registry: 1.1.0 (was incorrectly 1.2.0) - IdCard: 1.1.0 (was incorrectly 1.2.0) - Aadhaar: 1.1.0 (was incorrectly 1.2.0) Owner address: 0xcaee7aaf115f04d836e2d362a7c07f04db436bd0 * fix: upgrade script now correctly handles pre-defined versions in registry When upgrading to a version that already exists in registry.json (like 2.12.0), the script now uses that version's initializerVersion instead of incrementing from the latest version. This fixes the reinitializer validation for the governance upgrade. * fix: upgrade script handles Ownable contracts and outputs transaction data - Detect Ownable pattern before creating Safe proposals - Output transaction data for owner direct execution in --prepare-only mode - Use initializerFunction from registry (initializeGovernance) instead of constructing names - Skip Safe proposal creation for initial Ownable → AccessControl upgrade - After upgrade, owner grants SECURITY_ROLE to Safe for future upgrades * feat: IdentityVerificationHub v2.12.0 deployed on Celo - Implementation: 0x05FB9D7830889cc389E88198f6A224eA87F01151 - Changelog: Governance upgrade * feat: IdentityRegistryIdCard v1.2.0 deployed on Celo - Implementation: 0x7d5e4b7D4c3029aF134D50642674Af8F875118a4 - Changelog: Governance upgrade * feat: IdentityRegistryAadhaar v1.2.0 deployed on Celo - Implementation: 0xbD861A9cecf7B0A9631029d55A8CE1155e50697c - Changelog: Governance upgrade * feat: IdentityRegistry v1.2.0 deployed on Celo - Implementation: 0x81E7F74560FAF7eE8DE3a36A5a68B6cbc429Cd36 - Changelog: Governance upgrade * feat: add multisig addresses to registry * feat: PCR0Manager v1.2.0 deployed on Celo - Implementation: 0x9743fe2C1c3D2b068c56dE314e9B10DA9c904717 - Changelog: Governance upgrade * refactor: cleanup old scripts * chore: yarn prettier formatting
5.7 KiB
5.7 KiB
Contract Upgrade Guide
Quick Start
1. Update Your Contract
// Update version in NatSpec
* @custom:version 2.13.0
// Update reinitializer modifier (increment by 1)
function initialize(...) external reinitializer(13) {
// Add any new initialization logic
}
2. Run the Upgrade Script
cd contracts
npx hardhat upgrade --contract IdentityVerificationHub --network celo --changelog "Added feature X"
3. Approve in Safe
The script outputs instructions to submit to the Safe multisig. Once 3/5 signers approve, execute the transaction.
Governance Roles
| Role | Threshold | Purpose |
|---|---|---|
SECURITY_ROLE |
3/5 | Contract upgrades, role management |
OPERATIONS_ROLE |
2/5 | CSCA root updates, OFAC list updates |
Detailed Workflow
Step 1: Modify the Contract
- Make your code changes
- Update
@custom:versionin the contract's NatSpec comment - Increment the
reinitializer(N)modifier (e.g.,reinitializer(12)→reinitializer(13)) - Add any new storage fields at the end of the storage struct
Example:
/**
* @title IdentityVerificationHubImplV2
* @custom:version 2.13.0
*/
contract IdentityVerificationHubImplV2 is ImplRoot {
struct HubStorage {
// Existing fields...
uint256 newField; // Add new fields at the end only
}
function initialize(...) external reinitializer(13) {
// Initialize new fields if needed
HubStorage storage $ = _getHubStorage();
$.newField = defaultValue;
}
}
Step 2: Run the Upgrade Script
npx hardhat upgrade --contract <ContractName> --network <network> --changelog "Description"
Options:
--contract- Contract name (e.g.,IdentityVerificationHub)--network- Target network (celo,sepolia,localhost)--changelog- Brief description of changes--prepare-only- Deploy implementation without creating Safe proposal
Step 3: Script Execution
The script automatically:
- Validates version - Ensures
@custom:versionis incremented correctly - Checks reinitializer - Verifies
reinitializer(N)matches expected version - Validates storage - Ensures no breaking storage layout changes
- Compiles fresh - Clears cache to prevent stale bytecode
- Compares bytecode - Warns if implementation hasn't changed
- Deploys implementation - Deploys new implementation contract
- Updates registry - Records deployment in
deployments/registry.json - Creates git commit & tag - Auto-commits changes with version tag
- Creates Safe proposal - If you're a signer, auto-proposes to Safe
Step 4: Multisig Approval
If you're a Safe signer:
- Script auto-proposes the transaction
- Other signers approve in Safe UI
- Execute once threshold (3/5) is met
If you're not a signer:
- Script outputs transaction data for manual submission
- Copy data to Safe Transaction Builder
- Signers approve and execute
Safety Checks
The upgrade script performs these automatic checks:
| Check | What it Does | Failure Behavior |
|---|---|---|
| Version validation | Ensures semantic version increment | Blocks upgrade |
| Reinitializer check | Verifies modifier matches version | Blocks upgrade |
| Storage layout | Detects breaking storage changes | Blocks upgrade |
| Bytecode comparison | Warns if code unchanged | Prompts confirmation |
| Safe role verification | Confirms Safe has SECURITY_ROLE |
Blocks upgrade |
| Constructor check | Flags _disableInitializers() |
Prompts confirmation |
Registry Structure
All deployments are tracked in deployments/registry.json:
{
"contracts": {
"ContractName": {
"source": "ContractSourceFile",
"type": "uups-proxy"
}
},
"networks": {
"celo": {
"deployments": {
"ContractName": {
"proxy": "0x...",
"currentVersion": "2.12.0",
"currentImpl": "0x..."
}
}
}
},
"versions": {
"ContractName": {
"2.12.0": {
"initializerVersion": 12,
"changelog": "...",
"gitTag": "contractname-v2.12.0",
"deployments": { ... }
}
}
}
}
Utility Commands
# Check current deployment status
npx hardhat upgrade:status --contract IdentityVerificationHub --network celo
# View version history
npx hardhat upgrade:history --contract IdentityVerificationHub
Rollback
If issues occur after upgrade:
- Deploy the previous implementation version
- Create Safe transaction calling
upgradeToAndCall(previousImpl, "0x") - Execute with 3/5 multisig approval
Environment Setup
Required in .env:
CELO_RPC_URL=https://forno.celo.org
PRIVATE_KEY=0x... # Deployer wallet (needs ETH for gas)
Optional for contract verification:
CELOSCAN_API_KEY=...
ETHERSCAN_API_KEY=...
Troubleshooting
| Issue | Solution |
|---|---|
| "Version matches current" | Update @custom:version in contract |
| "Reinitializer mismatch" | Update reinitializer(N) to next version |
| "Storage layout incompatible" | Don't remove/reorder storage variables |
| "Safe not indexed" | Submit manually via Safe UI |
| "Bytecode unchanged" | Ensure you saved contract changes |