SailGovernance & Timelock
SailGovernance is the protocol parameter store. It holds two categories of settings — constitutional caps that are immutable after deployment, and tunable parameters that the current governance address may change, always through a 48-hour timelock. License: GPL-2.0-or-later.
Constitutional caps (immutable; no procedure can raise them)
MAX_PROTOCOL_CUT_BPS
2500 (25%)
the protocol's share of any fee collection
MAX_PERMISSION_FEE_WEI
set at deploy, ≤ 0.01 ether
the per-permission registration fee
MAX_PERMISSIONS_CAP
100
the per-account permission limit
MAX_PERMISSION_FEE_WEI is immutable and the constructor itself reverts if it is set above the 0.01 ether bytecode ceiling. The other two are constant.
Tunable parameters (within the caps, via timelock)
currentProtocolCutBps
setProtocolCutBps
0
MAX_PROTOCOL_CUT_BPS
permissionRegistrationFee
setPermissionRegistrationFee
0
MAX_PERMISSION_FEE_WEI
maxPermissionsPerAccount
setMaxPermissionsPerAccount
20
1 … MAX_PERMISSIONS_CAP
Every setter is onlyTimelock: changes are scheduled on the timelock, wait 48 hours, then execute. The protocol cut and registration fee are zero at launch.
The injected timelock
SailGovernance does not build its timelock inline. A standalone OpenZeppelin TimelockController is deployed separately and injected via the constructor — this is what makes every constructor argument chain-independent and enables the same-address deployment. The constructor then validates the injected timelock and reverts if any invariant fails:
Minimum delay is exactly 48 hours
TimelockDelayMismatch
initialGovernance holds PROPOSER_ROLE
GovernanceNotProposer
initialGovernance holds EXECUTOR_ROLE (rejects open-executor timelocks)
GovernanceNotExecutor
The timelock self-administers its roles; the governance EOA does not hold the proposer-admin role
TimelockNotSelfAdministered
REQUIRED_TIMELOCK_DELAY is 48 hours; an exact match (not a lower bound) is required so the injected timelock reproduces the audited behaviour precisely.
Two-step governance transfer
Governance transfer is propose → accept to prevent loss from a mistyped successor:
Current governance calls
proposeGovernance(candidate)(via timelock).Current governance schedules + executes
rotateTimelockRoles(old, new)(via timelock) to handPROPOSER/EXECUTOR/CANCELLERroles to the candidate and revoke them from the outgoing governance.The candidate calls
acceptGovernance(). This reverts withRolesNotYetRotatedunless the candidate already holdsPROPOSER_ROLE— eliminating any window where old governance retains timelock keys after handoff.
Trusted allowlists
The kernel consults these governance-held allowlists at account creation and fee-policy changes:
trustedSafeFactory
which Safe proxy factories createAccount may use
trustedSafeSingleton
which Safe singletons createAccount may use
trustedModuleSetup
which helper may be the to of Safe.setup's delegatecall (blocks attacker setup delegatecalls)
trustedSafeProxyCodehash
which proxy runtime codehashes count as a genuine Safe
trustedFeePolicy
which fee policies may be attached (blocks upgradeable/metamorphic policies)
All five setters are onlyTimelock. The one exception is genesis: bootstrapAllowlists(...) lets the initial governance seed all five once, in the deployment transaction, bypassing the timelock — then allowlistBootstrapped latches true forever and every later change must go through the 48-hour timelock.
Emergency pause
A separate emergencyAdmin (rotatable only via timelock) may pause() the kernel without a timelock delay, for fast incident response:
The pause auto-expires after 72 hours (
pauseExpiry);isPaused()returnsblock.timestamp < pauseExpiry.A
PAUSE_COOLDOWNof 72 hours sits between consecutive pauses to prevent spam.unpause()lifts it early and clears the cooldown.
While paused, dispatch, dispatchBatch, collectFees, and permission registration revert — but revocation, session revocation, manager rotation, and clearing a fee policy stay available, so owners can always reduce exposure during an incident.
Continue to the MandateFactory, or the full fee model and governance pages.
Last updated

