Emergency pause and incident response
Quorum contracts do not currently implement Pausable (per audit M-04). Mainnet
remediation will add a PausableUpgradeable mixin or equivalent guard. Until then,
incident response relies on owner-gated parameter changes and off-chain coordination.
Current incident response surface
Pre-mainnet, the owner (Sepolia: single EOA, mainnet: Safe + Timelock) can:
| Action | Contract | Function | Effect |
|---|---|---|---|
| Stop new bounty creation | ForumExecutor | (no surface — see planned remediation) | n/a |
| Stop new chamber commits | ChamberRegistry | setDealer(address(0)) | dealer-locked, no new commits |
| Stop new idea deploys | IdeaFactory | setDeployer(address(0)) | factory-locked, no new deploys |
| Redirect treasury | BondingEscrow.setProtocolTreasury | new address | next flush goes elsewhere |
| Change slash rate | BondingEscrow.setProtocolSlashBps | new value (0..3000) | applies to next settlement |
| Re-point ForumExecutor | BondingEscrow.setForumExecutor | new contract | settle calls re-route |
These are owner-gated and (on mainnet) timelock-delayed by 24h. A 24h delay is fine for
operational changes but insufficient for active exploits — by design, that’s the
incident-response window for the multisig to call cancel on a compromised proposal.
Planned mainnet emergency surface
Pre-mainnet remediation adds:
PausableonBondingEscrow,ForumExecutor,FeeRouter,IdeaFactory.- A
GUARDIAN_ROLEseparate fromownerthat can pause without timelock delay. - A 7-day max pause duration (auto-unpause to prevent indefinite freeze).
- A “soft pause” mode that blocks only state-mutating entry points, leaves view functions live.
// Planned addition to BondingEscrow (post-remediation):
function pause() external onlyGuardian { _pause(); _pausedAt = block.timestamp; }
function unpause() external onlyOwner { _unpause(); }
modifier whenNotPausedOrExpired() {
if (paused() && block.timestamp <= _pausedAt + MAX_PAUSE_DURATION) revert ContractPaused();
_;
}The Guardian role would be held by a hot-wallet rotation pool (3 independent operators) so a single compromised operator cannot brick the protocol indefinitely.
Incident classes
Class A — direct loss of funds (critical)
Examples:
- Reentrancy enabling withdrawal of escrowed bounty.
- Token-shape exploit (e.g. fee-on-transfer token bricking
BondingEscrow.claimso a winner can drain via reverting their own claim — H-02 variant). - Owner key compromise with active draining.
Response:
- Guardian calls
pause()on affected contracts (when available). - Operator team convenes on Telegram / Discord war room within 1h.
- Postmortem draft within 24h.
- Fix deployed within 72h or pause extended (max 7 days).
- Public disclosure within 14 days.
Class B — sustained DoS
Examples:
- H-03 1-wei AGAINST short-circuit (a finalize-front-runs everyone variant).
- H-01 voters locked out of dispute rounds.
- M-06 FeeRouter recipient blocking flush forever.
Response:
- Investigate and confirm the DoS pattern.
- If user funds are locked (not lost), notify users and plan migration.
- Deploy fix on Sepolia first, run E2E, then mainnet.
- Public postmortem within 14 days.
No emergency pause required for Class B issues — they degrade functionality but do not steal.
Class C — protocol parameter mis-use
Examples:
- Owner key compromise without active draining (visible attempt to redirect treasury).
- Mis-configured BPS on a new idea (sum != 10000 — actually caught by
BpsMismatchrevert).
Response:
- Multisig cancels the malicious timelock proposal within the 24h window.
- Rotate owner keys.
- Postmortem within 7 days.
Class D — operational degradation
Examples:
- forum-API outage (fly.io machine down).
- Relayer EOA out of ETH.
- RPC provider degradation.
Response:
- Status page banner.
- Operator on-call resolves within SLA (4h business, 12h off-hours).
- Postmortem only for outages > 4h.
Not a protocol-level incident — does not affect on-chain state, only off-chain coordination.
Status page
A live status page will publish at https://status.quorum.sh (pending domain registration). It
will show:
- forum-API health (latency, error rate)
- RPC provider health
- Relayer wallet balance
- Pending timelock proposals
- Multisig signer activity in the last 24h
- Open incidents
For now, the deployments page in the repo is the canonical state.
Postmortem policy
Every Class A / B incident produces a public postmortem with:
- Timeline (UTC).
- Root cause (technical + organizational).
- Impact: users affected, funds affected, downtime.
- Resolution: what was fixed, when, how.
- Prevention: changes to process, code, monitoring.
- Acknowledgements: researchers credited, team members responsible.
Postmortems live in docs/postmortems/ in the repo. No private postmortems.