Skip to main content
Sources: src/modules/ACLModule.sol · FundRoles.sol · FundSpokeACLModule.sol · FundACLModule.sol · FundManagerACLModule.sol · StrategyACLModule.sol

Two auth patterns

OpenZeppelin AccessControlEnumerable + Multicall, with batch grantRoles/revokeRoles (admin-only) and constructor seeding via RoleHolder[] {role, account}.Contracts that own role state:

Fund role table (FundRoles)

All identifiers are keccak256("<NAME>"). “Enforced by” shows where the guarded function lives.

Other role tables

Upgrade authority

Every contract is a TransparentUpgradeableProxy; upgrade rights belong to whoever owns each proxy’s auto-deployed ProxyAdmin — the proxyAdmin address chosen at tenant/fund creation.
Roles govern behavior; ProxyAdmin ownership governs code. An operator can hold operational roles without upgrade rights; upgrade authority need not hold operational roles.

Separation of duties

Prefer split keys over one account holding everything:
  • Reporter (SUBMIT_REPORT_ROLE) ≠ acceptor (ACCEPT_REPORT_ROLE)
  • Third party for reviewer veto (REJECT_REPORT_ROLE)
  • ACCEPT_SUSPICIOUS_REPORT_ROLE and EMERGENCY_PAUSE_ROLE on higher-security keys
  • DEFAULT_ADMIN_ROLE and ProxyAdmin ownership on the most protected keys