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

The two auth patterns

OpenZeppelin AccessControlEnumerable + Multicall, plus batch grantRoles/revokeRoles (admin-only) and constructor-time role seeding via RoleHolder[] {role, account}.Used directly by contracts that own their 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.The two are deliberately independent: an operator can hold rich behavioral roles without any ability to change contract code, and the upgrade authority can change code without holding any operational role.

Separation-of-duties guidance

Because roles can be split across parties and keys, funds should distribute them rather than concentrating everything in one account. Common splits:
  • Keep the reporter (SUBMIT_REPORT_ROLE) separate from the acceptor (ACCEPT_REPORT_ROLE).
  • Give a third party the reviewer veto (REJECT_REPORT_ROLE).
  • Hold ACCEPT_SUSPICIOUS_REPORT_ROLE and EMERGENCY_PAUSE_ROLE on more secure keys.
  • Keep DEFAULT_ADMIN_ROLE and ProxyAdmin ownership on the most protected keys of all.