Lack of Circuit Breakers
id: LS55H
title: Lack of Circuit Breakers
baseSeverity: H
category: emergency-control
language: solidity
blockchain: [ethereum]
impact: Uncontrollable protocol drain or failure under duress
status: draft
complexity: low
attack_vector: external
mitigation_difficulty: easy
versions: [">=0.5.0", "<latest"]
cwe: CWE-693
swc: SWC-131
π Description
- Lack of circuit breakers for secondary features refers to the absence of conditional
pause,disable, oremergencyStopmechanisms in non-core contract functions such as: - Claim, redeem, migrate, swap, vote, bid, etc.
- While these features are not directly responsible for fund custody, their failure or abuse can:
- Lock user interactions
- Enable spam, bot abuse, or gas griefing
- Prevent recovery during upgrades, and
- Amplify damage when paired with other vulnerabilities.
- Without selective pause control, contracts lack the ability to quickly respond to partial threats.
π¨ Vulnerable Code
contract FeatureHeavy {
function redeem() external {
// Logic to calculate and send tokens
}
function vote(uint256 proposalId) external {
// Record user vote
}
// β No way to disable redeem or vote during bugs/emergencies
}
π§ͺ Exploit Scenario
Step-by-step impact:
- A logic bug is discovered in redeem() allowing users to withdraw excess rewards.
- There is no circuit breaker or pause() mechanism tied to this function.
- Attackers continue to exploit the feature while core functions remain intact.
- Protocol cannot patch without full upgrade or redeploy.
Assumptions:
- Contract has auxiliary features with state impact.
- No fine-grained control to disable only specific functions.
β Fixed Code
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract SafeFeatureControl is Pausable, Ownable {
bool public redeemPaused;
bool public votePaused;
function pauseRedeem() external onlyOwner {
redeemPaused = true;
}
function redeem() external {
require(!redeemPaused, "Redeem paused");
// Safe redeem logic
}
function vote(uint256 proposalId) external {
require(!votePaused, "Voting paused");
// Voting logic
}
function pauseVote() external onlyOwner {
votePaused = true;
}
}
π§ Contextual Severity
- context: "Default"
severity: H
reasoning: "Without pause, any bug may drain the protocol irreversibly."
- context: "Governance-controlled DeFi protocol"
severity: C
reasoning: "Failure to halt critical operations can lead to systemic loss."
- context: "Private contract with limited usage"
severity: L
reasoning: "Lower risk due to trusted actors and limited exposure."
π‘οΈ Prevention
Primary Defenses
- Add feature-specific circuit breakers (e.g., redeemPaused, swapPaused) instead of global pause() only.
- Use require(!XPaused) in each critical function logic.
- Combine with OpenZeppelinβs Pausable or modular access control.
Additional Safeguards
- Emit FeaturePaused(string feature) events for observability.
- Define protocol-wide governance procedures to toggle critical and secondary functions separately.
- Create monitoring bots to alert based on misuse rates of auxiliary functions.
Detection Methods
- Slither: missing-feature-pause, no-emergency-guard, feature-overexposed detectors.
- Manual audit of all externally callable functions to verify whenNotPaused or equivalents exist.
- Coverage reports for require(!paused) or emergency triggers.
π°οΈ Historical Exploits
- Name: The DAO Hack
- Date: 2016-06-17
- Loss: Approximately $60 million
- Post-mortem: Link to post-mortem
π Further Reading
- SWC-136: Unexpected Behavior / Missing Checks
- Solidity Docs β Pausable Pattern
- OpenZeppelin β Circuit Breakers
β Vulnerability Report
id: LS55H
title: Lack of Circuit Breakers
severity: H
score:
impact: 4
exploitability: 2
reachability: 4
complexity: 2
detectability: 5
finalScore: 3.3
π Justifications & Analysis
- Impact: Affects protocol recovery and integrity during active threats.
- Exploitability: Needs bug in feature logic but no defense mechanism.
- Reachability: Very common in protocols with redeem, vote, claim, or migrate.
- Complexity: Low β fix involves simple boolean flags and require guards.
- Detectability: High β caught easily with Slither or checklist-based audits.