Governance
Governance and safety
Governance timelock
2 days
Hard floor (MIN_DELAY_FLOOR)
Every parameter change, role grant, token approval and grant payment waits at least 2 days. updateDelay can lower the stored value, but getMinDelay never returns less than the floor.
- Proposers
- Governance multisig (later an ACC/L Governor)
- Canceller
- EmergencyGuardian (acting for the guardian)
- Executors
- Anyone, once the delay has passed
- Vault outflow roles
- +14 days, guardian can cancel
- Vault migration
- +14 days, guardian can cancel
Emergency guardian
Pause · revoke · cancel only
No asset, grant or parameter authority.
- Guardian
- not deployed
- Rotator
- not deployed
- Pending rotation
- —
Because the guardian can cancel timelock operations, it could try to block its own replacement. The rotator (the governance multisig acting directly) can therefore replace it after 7 days; the guardian cannot cancel a rotation.
Pausable modules
- not deployed
Fees
FeeCollector.harvest, distribute
- not deployed
Treasury
releaseForInvestment, releaseToStrategy, payGrant
- not deployed
Registry
register, registerFor
- not deployed
Allocation
proposeEpoch, finalize
- not deployed
Investment
InvestmentExecutor.execute
- not deployed
Strategy
StrategyManager deposits (no adapter registered)
- not deployed
Reinvestment
ReinvestmentController epochs
Guardian or governance can pause; only governance unpauses. Returning capital to the vault is never paused.
Parameters and their onchain bounds
Governance changes parameters through the timelock, and only inside bounds hard-coded in each contract.
| Parameter | Setter | Current | Onchain bounds | Launch value |
|---|---|---|---|---|
| Fee split | ||||
Investment bucket Four shares must sum to 100%. | FeeCollector.setSplit | — | ≥ 40%, ≤ 80%MIN_INVESTMENT_BPS / MAX_INVESTMENT_BPS | 65% |
Reserve bucket Receives rounding dust. | FeeCollector.setSplit | — | ≥ 10%, ≤ 40%MIN_RESERVE_BPS / MAX_RESERVE_BPS | 20% |
Grants bucket | FeeCollector.setSplit | — | ≥ 0%, ≤ 20%MAX_GRANTS_BPS | 10% |
Operations | FeeCollector.setSplit | — | ≥ 0%, ≤ 10%MAX_OPERATIONS_BPS | 5% |
| Allocation | ||||
Challenge window | AllocationController.setParams | — | ≥ 12 h, ≤ 7 daysMIN_CHALLENGE_WINDOW / MAX_CHALLENGE_WINDOW | 2 days |
Budget validity | AllocationController.setParams | — | ≥ 1 day, ≤ 30 daysMIN_BUDGET_VALIDITY / MAX_BUDGET_VALIDITY | 14 days |
Contribution weight Three weights must sum to 100%. | AllocationController.setParams | — | ≥ 30%, ≤ 70%MIN_CONTRIBUTION_WEIGHT_BPS / MAX_COMPONENT_WEIGHT_BPS | 50% |
Growth weight | AllocationController.setParams | — | ≥ 0%, ≤ 70%MAX_COMPONENT_WEIGHT_BPS | 30% |
Quality weight | AllocationController.setParams | — | ≥ 0%, ≤ 70%MAX_COMPONENT_WEIGHT_BPS | 20% |
Minimum Contribution Score | AllocationController.setParams | — | ≥ 100, ≤ 1,000MIN_CONTRIBUTION_FLOOR / MAX_SCORE | 400 |
Max project share of epoch | AllocationController.setParams | — | > 0, ≤ 50%MAX_PROJECT_SHARE_CEILING_BPS | 25% |
Max epoch budget Each proposal is also capped by the INVESTMENT bucket balance. | AllocationController.setParams | — | > 0 WHYPEmust be > 0 | 10,000 WHYPE |
| Risk limits | ||||
Max exposure per project Direct holdings + strategy underlying, full oracle price. | RiskController.setParams | — | > 0, ≤ 10%PROJECT_EXPOSURE_CEILING_BPS | 10% |
Max single LP position | RiskController.setParams | — | > 0, ≤ 5%LP_POSITION_CEILING_BPS | 5% |
Max exposure per external protocol | RiskController.setParams | — | > 0, ≤ 10%PROTOCOL_EXPOSURE_CEILING_BPS | 10% |
Minimum liquid reserves | RiskController.setParams | — | ≥ 10%, ≤ 50%MIN_RESERVE_FLOOR_BPS / MIN_RESERVE_CEILING_BPS | 15% |
| Investment execution | ||||
Max slippage vs oracle | InvestmentExecutor.setParams | — | > 0, ≤ 5%MAX_SLIPPAGE_CEILING_BPS | 1% |
Max tranche of project budget | InvestmentExecutor.setParams | — | > 0, ≤ 50%MAX_TRANCHE_CEILING_BPS | 20% |
Min interval between tranches | InvestmentExecutor.setParams | — | ≥ 10 minMIN_TRANCHE_INTERVAL_FLOOR | 2 h |
Max signed-order lifetime | InvestmentExecutor.setParams | — | > 0, ≤ 1 dayMAX_ORDER_TTL_CEILING | 15 min |
| Timelock | ||||
Timelock delay | GovernanceTimelock.updateDelay | — | ≥ 2 daysMIN_DELAY_FLOOR (getMinDelay never returns less) | 2 days |
| Registry | ||||
Project categories | ProjectRegistry.setCategoryCount | — | ≥ 1, ≤ 32MAX_CATEGORIES (can only grow) | 8 |
Launch values come from contracts/script/Deploy.s.sol. The dot shows where the current value sits inside its bounds.
Guardian powers
Every risk-reducing action the guardian multisig can take, from the access checks in the contracts.
Pause
EmergencyGuardian.pause(module)
Stops one module instantly.
EmergencyGuardian.pauseAll()
Stops every pausable module.
Revoke
revokeRole(role, account)
Removes a keeper, signer, allocator or reviewer key on any module.
InvestmentExecutor.setAdapter(adapter, false)
Revokes a swap adapter (approving one needs governance).
PriceOracle.disableFeed(asset)
Disables a price feed; dependent actions then fail closed.
StrategyManager.deactivateStrategy(id)
Stops new deposits into a strategy.
Cancel
EmergencyGuardian.cancelTimelockOperation(id)
Vetoes a queued governance operation (the guardian contract holds the canceller role).
TreasuryVault.cancelRoleGrant(role, account)
Cancels a pending 14-day grant of a vault outflow role.
AllocationController.veto(epochId)
Stops an epoch proposal before finalization.
InvestmentExecutor.cancelNonce(nonce)
Invalidates a signed order before execution.
TreasuryVault.cancelMigration()
Cancels a pending vault migration.
StrategyManager.emergencyExit(id)
Returns a strategy's capital to the vault, even while paused.
ProjectRegistry.suspend(projectId)
Suspends a project; only governance can reinstate it.
Cannot
- Unpause a module (governance only)
- Grant roles or approve adapters, feeds or project tokens
- Change any parameter
- Move treasury assets or pay grants
- Block its own replacement: the rotator can rotate it after 7 days
Other governance-only actions
- ProjectRegistry.setTokenApproval(projectId, token, approved)
Approves a reviewed token; reverts if the builder swapped the token while the vote was queued. - ProjectRegistry.forceRelease(projectId, reasonHash)
Clears a squatted or abusive registration: the domain (and the token, unless already funded) become available again. - TreasuryVault.payGrant(projectId, recipient, asset, amount, milestone)
Pays from the GRANTS bucket; reverts if the project's builder changed since the grant was queued. - TreasuryVault.proposeRoleGrant(role, account)
Outflow roles (investment executor, strategy manager) take 14 days more and the guardian can cancel.