feat: add role-based access control and emergency pause#4
Merged
Conversation
Add support for creating and managing multiple isolated treasury vaults. Each vault maintains independent signer sets, weights, and approval thresholds for flexible DAO governance. - Add VaultInfo struct for vault metadata and configuration - Implement per-vault storage mappings for signers - Add createVault, addSigner, removeSigner, setThreshold functions - Reserve 46 storage slots for future upgrades - Maintain backward compatibility with existing storage layout
Comprehensive test suite for multi-vault operations including vault creation, signer management, threshold configuration, and access control. Tests verify proper isolation between vault instances and edge cases.
Implement automated upgrade workflows for Base Sepolia and Mainnet with safety confirmations. Add deployment metadata structure for tracking contract versions and upgrade history across networks.
Remove unnecessary documentation and dev files. Rewrite README with focus on use cases and practical examples instead of development info. Removed: - CODE_OF_CONDUCT.md - CONTRIBUTING.md - DEPLOYMENTS.md - SECURITY.md Updated: - README.md - simplified with use cases and deployed addresses
Clean multi-vault only implementation without backward compatibility layer. Breaking changes: - Remove global signer management (signers, signerList, threshold, totalWeight) - All proposals now vault-scoped (createProposal requires vaultId) - Initialize() simplified (no initial signers, create vault 0 manually after deploy) - Remove legacy functions (addSigner without vaultId, updateSignerWeight, etc) - Proposal struct includes vaultId field - Approvals check vault-specific signer permissions Storage layout optimized with 50 reserved slots for future upgrades.
Enhance deployment workflows to automatically extract and save contract addresses after deployment.
Changes:
- Parse deployment logs to extract proxy and implementation addresses
- Generate deployments/{network}.json with contract addresses and metadata
- Auto-commit deployment files back to repository
- Supports both Base Sepolia and Base Mainnet networks
This eliminates manual address tracking and ensures deployment history is preserved in the repository.
Add comprehensive vault lifecycle management: - Vault archival functionality for disabling vaults - Signer weight updates for mid-life configuration changes - Improved storage layout documentation for UUPS upgradeability - Clear separation of vault-level vs controller-level data Technical changes: - Add archiveVault() to permanently disable vaults - Add updateSignerWeight() to modify signer voting power - Fix OpenZeppelin v4.9.6 compatibility (__Ownable_init parameter) - Add VaultSignerWeightUpdated and VaultArchived events - Document storage slots for upgrade safety
New test coverage: - VaultLifecycle.t.sol: Tests for vault creation, archival, independence - ConfigurationChanges.t.sol: Tests for mid-life configuration changes Test scenarios: - Vault archival and reactivation restrictions - Signer weight updates and their effects on proposals - Threshold changes with active proposals - Removing signers who have voted on active proposals - Cross-vault configuration independence - Edge cases for signer and threshold management Removes outdated tests that used pre-multi-vault API. All 42 tests pass successfully.
Create VAULT_MODEL.md specification document covering: Architecture: - Vault lifecycle (active → archived states) - Data model separation (vault-level vs controller-level) - Storage layout for UUPS upgradeability Configuration Management: - Mid-life configuration change rules and effects - Threshold and weight update behaviors - Edge cases and constraints Integration Guidelines: - API reference for integrators - Event monitoring patterns - Security considerations for auditors Target audience: protocol integrators, auditors, and advanced users. Links added to README for discoverability.
Pin dependencies to specific versions: - forge-std@v1.12.0 - openzeppelin-contracts@v4.9.6 - openzeppelin-contracts-upgradeable@v4.9.6 Ensures ReentrancyGuardUpgradeable is available at expected path.
Update GitHub Actions workflows to use git submodules instead of cloning wrong OpenZeppelin versions: - Changed from v5.0.2 to v4.9.6 (via submodules) - Enable recursive submodule checkout - Remove manual dependency cloning - Add deployment info script for post-upgrade verification This ensures workflows use the same dependency versions as local dev.
Upgrade completed successfully: - New implementation: 0xF3eD7F568dAe09536768081a4BFcf44E55703529 - Proxy remains: 0xB4FD2402c97c0F2E38B3Be91596aDe8927A36439 - Gas used: 3,399,951 - Verified on Basescan New features available: - archiveVault() for permanent vault deactivation - updateSignerWeight() for mid-life signer weight changes
Production upgrade completed successfully: - New implementation: 0xe85061dDf1Df886A07C71a94f4BB76DB54EC9631 - Proxy remains: 0xB4FD2402c97c0F2E38B3Be91596aDe8927A36439 - Gas used: 3,399,951 - Verified on Basescan New production features: - archiveVault() - permanent vault deactivation - updateSignerWeight() - mid-life signer weight updates Both Base Sepolia and Mainnet now running upgraded implementation.
Replace OwnableUpgradeable with AccessControlUpgradeable in core contracts. Add GLOBAL_ADMIN, VAULT_ADMIN (per-vault), OPERATOR, and PAUSER roles. Implement granular permissions with proper hierarchy enforcement. Add emergency pause mechanism using PausableUpgradeable. - MultiVault: role checks for vault creation, configuration, and proposals - PayoutExecutor: role checks for payout operations - Vault admins can only modify their assigned vaults - Emergency pause blocks all state-changing operations - Adjust storage __gap to accommodate new pause state
Add 21 tests for role assignment, privilege escalation protection, and cross-vault isolation. Add 21 tests for emergency pause mechanism covering all operations. Role system tests verify: - DEFAULT_ADMIN, VAULT_ADMIN, OPERATOR, PAUSER role assignment - Role hierarchy enforcement (operators cannot grant roles) - Cross-vault isolation (vault admins cannot modify other vaults) - Privilege escalation prevention Emergency pause tests verify: - Only GLOBAL_ADMIN and PAUSER can pause/unpause - All state-changing operations blocked when paused - View functions remain accessible - Resume operations after unpause
Create comprehensive documentation for role-based access control: - Role hierarchy and access control matrix - Privilege escalation protection mechanisms - Emergency pause behavior and recovery procedures Add governance pattern guides for different organization types: - DAO treasury management pattern - Company treasury management pattern - Hybrid foundation + DAO pattern - Multi-project allocation pattern Include implementation examples, security considerations, and operational workflows for each pattern.
Create UpgradeRoles.s.sol for deploying new implementations with RBAC. Update UpdateDeployment.s.sol to work with AccessControl (remove owner() call). Upgrade script handles: - Deploy new MultiVault implementation - Deploy new PayoutExecutor implementation - Upgrade proxies via UUPS - Preserve existing storage and vault data
Add links to new documentation: - Role System Design - Governance Patterns Update key features section: - Role-Based Access Control - Emergency Pause circuit breaker - Enhanced security features
Add reinitializer functions to support migration from Ownable to AccessControl during contract upgrades. Without this, upgraded contracts would become unmanageable as no address would have DEFAULT_ADMIN_ROLE. Changes: - Add initializeV2() with reinitializer(2) to MultiVault.sol - Add initializeV2() with reinitializer(2) to PayoutExecutor.sol - Update Upgrade.s.sol to call initializeV2() during upgrade - Update UpgradeRoles.s.sol to call initializeV2() for both contracts This ensures smooth migration from v1 (Ownable) to v2 (AccessControl) while preserving admin access during UUPS proxy upgrades. All 84 tests passing.
Modified upgrade workflows to automatically read proxy addresses from deployments/*.json files instead of requiring manual input. Changes: - Remove proxy_address input parameter from workflows - Add step to read addresses from deployment JSON using jq - Use MULTIVAULT_PROXY and EXECUTOR_PROXY from deployment files - Update upgrade log to use auto-detected proxy address Benefits: - No manual address input required - Single source of truth for deployment addresses - Prevents human error in address specification - Faster workflow execution
Add diagnostic scripts to verify deployer address and ownership before running upgrade scripts. Changes: - script/CheckOwner.s.sol: Check if deployer is owner of proxy - script/ShowDeployer.s.sol: Display deployer address from private key These utilities help diagnose "caller is not the owner" errors during contract upgrades.
The previous approach cast the proxy to the new MultiVault type which uses AccessControl, causing ABI conflicts when calling upgradeToAndCall on proxies still using the old Ownable-based implementation. Changes: - Add IUUPSProxy interface to both upgrade scripts - Cast proxy to IUUPSProxy instead of MultiVault/PayoutExecutor - This avoids ABI mismatches between old and new implementations This fixes "Ownable: caller is not the owner" errors during upgrades caused by improper function selector resolution.
Add CheckCurrentState script to diagnose ownership and access control state before attempting upgrades. This helps identify if: - Contract uses Ownable (check owner()) - Contract uses AccessControl (check DEFAULT_ADMIN_ROLE) - Owner is address(0) (unmanageable contract) This diagnostic step will run before upgrade in workflows to catch permission issues early and provide clear error messages.
- Updated test.yml to trigger on 'developing' branch - Removed OpenZeppelin v5.0.2 installation steps from workflows - Fixed deploy workflows to use submodules: recursive - Removed all upgrade-related scripts and workflows - Deleted Upgrade.s.sol, UpgradeRoles.s.sol - Deleted CheckCurrentState.s.sol, CheckOwner.s.sol, ShowDeployer.s.sol - Deleted upgrade-base-sepolia.yml, upgrade-base-mainnet.yml Rationale: Existing contracts on both Base Sepolia and Mainnet have owner = address(0) and are unmanageable. Strategy pivot to deploy fresh contracts with proper AccessControl role system.
Updated deployment files with fresh contract addresses: Base Sepolia: - MultiVault: 0xc8c7F4E139B10711f9a9cbf827De58437C001d37 - PayoutExecutor: 0xCCc16fC6e3cb9a8260689a15fd9687C857D6Ccf7 Base Mainnet: - MultiVault: 0x183551dda7Aa336f8a08633E8EdF5562BC771371 - PayoutExecutor: 0x08fE6651A4835B1cBf26412f8bcbc04ffc15aC0a Both deployments verified on BaseScan with DEFAULT_ADMIN_ROLE properly assigned to deployer (0xBd53dA0eb0B80061dbF942D8CE98EfC4Dc0e0635). Cleaned repository: - Removed old upgrade-log.txt - Updated deployment JSON files with AccessControl metadata - Repository ready for production use
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.
Implement AccessControlUpgradeable with 4-tier role hierarchy.
Add emergency pause mechanism with comprehensive tests.
Deploy fresh verified contracts to Base Sepolia and Mainnet.