Denial of Service (DoS) vulnerabilities allow attackers to block legitimate users from accessing contract functionality. Unlike financial exploits, DoS attacks disable operations: preventing withdrawals, freezing governance, or bricking key functions. Protocols have lost operational availability for weeks due to DoS vulnerabilities. Firepan's HOUND AI detects DoS vulnerabilities automatically during development and post-deployment monitoring, covering continuous analysis across the full contract lifecycle.
Denial of Service in smart contracts prevents legitimate users from executing intended actions. Common DoS vectors:
The vulnerability is critical because:
DoS exploitation involves:
// VULNERABLE — example only
// Demonstrates: Denial of Service
// Do NOT use in production
pragma solidity ^0.8.0;
contract VulnerablePaymentSplitter {
address[] public recipients;
mapping(address => uint256) public shares;
// VULNERABLE: Unbounded loop in distribution
function distributeRewards(uint256 reward) public {
// Loop over all recipients
for (uint i = 0; i < recipients.length; i++) {
uint256 share = (reward * shares[recipients[i]]) / 100;
// VULNERABLE: If any recipient's receive() reverts, entire transaction reverts
(bool success, ) = recipients[i].call{value: share}("");
require(success); // Reverts if ANY recipient reverts
}
}
}
contract VulnerableWithdrawal {
mapping(address => uint256) public balances;
// VULNERABLE: Withdrawal loop can be blocked
function withdrawAll(address[] memory users) public onlyOwner {
for (uint i = 0; i < users.length; i++) {
uint256 amount = balances[users[i]];
(bool success, ) = users[i].call{value: amount}("");
require(success); // Reverts if any user reverts
balances[users[i]] = 0;
}
}
}
contract VulnerableGovernance {
address[] public voters;
// VULNERABLE: Unbounded loop can be exploited for DoS
function executeVote(bytes memory proposal) public {
// Loop over all voters to check votes
for (uint i = 0; i < voters.length; i++) {
_checkVote(voters[i]);
}
// If attacker registers 10000+ voters, loop becomes expensive
// Subsequent votes become impossible (out of gas)
}
}
contract DoSAttacker {
VulnerablePaymentSplitter public target;
constructor(address _target) {
target = VulnerablePaymentSplitter(_target);
}
// STEP 1: Register as recipient
function registerAsRecipient() public {
target.registerRecipient(address(this));
}
// STEP 2: Revert on receive, blocking distribution
receive() external payable {
revert("Blocking distribution!"); // This blocks entire transaction!
}
function triggerDoS() public {
// Calling distributeRewards() now reverts because our receive() reverts
// Other recipients can't get paid
target.distributeRewards(100 ether);
}
}
contract UnboundedLoopDoS {
// Register 10000 voters
function registerManyVoters(address governance) public {
for (uint i = 0; i < 10000; i++) {
// Register dummy voter
// executeVote() now loops 10000 times, burning gas
// DoS subsequent votes
}
}
}
| Protocol | Date | Impact | Root Cause | |----------|------|--------|-----------| | SynapseBridge | 2021 | Week outage | Unbounded loop in distribution | | PolyNetwork | 2021 | Partial freeze | External call failures blocking withdrawals | | Generic Governance | 2020-2023 | Multiple incidents | Unbounded voter loops |
Manual detection requires flow analysis:
Red flags:
Firepan's HOUND AI performs DoS vulnerability analysis:
Firepan's HOUND AI engine identifies DoS vulnerabilities across all monitored contracts.
1. Pull Over Push Pattern
Let users withdraw instead of pushing to them:
// VULNERABLE: Push pattern can be blocked
function distributeRewards() public {
for (uint i = 0; i < recipients.length; i++) {
(bool success, ) = recipients[i].call{value: reward}("");
require(success); // Blocks entire distribution!
}
}
// SECURE: Pull pattern
mapping(address => uint256) public claimable;
function depositRewards(uint256 reward) public {
for (uint i = 0; i < recipients.length; i++) {
claimable[recipients[i]] += reward;
}
}
function claim() public {
uint256 amount = claimable[msg.sender];
claimable[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
}
2. Don't Require External Call Success in Loops
Allow individual failures without blocking others:
// VULNERABLE
for (uint i = 0; i < recipients.length; i++) {
(bool success, ) = recipients[i].call{value: share}("");
require(success); // Blocks entire loop!
}
// SECURE: Continue on failure
for (uint i = 0; i < recipients.length; i++) {
(bool success, ) = recipients[i].call{value: share}("");
// Don't require success; continue regardless
}
3. Use Pagination
Process data in chunks:
// SECURE: Paginated distribution
function distributeBatch(uint256 startIdx, uint256 endIdx) public onlyOwner {
require(endIdx - startIdx <= 100, "Batch too large");
for (uint i = startIdx; i < endIdx; i++) {
_distribute(recipients[i]);
}
}
4. Implement Emergency Pause
Allow circuit breaker for stuck operations:
bool public paused;
function pause() public onlyOwner {
paused = true;
}
function unpause() public onlyOwner {
paused = false;
}
function distribution() public {
require(!paused, "Paused");
// ...
}
5. Use Try-Catch for External Calls
Gracefully handle failures:
// SECURE: Try-catch
try target.call{value: amount}("") {} catch {
// Silently fail; continue
}
Q: What is denial of service in smart contracts?
A: Denial of Service exploits prevent legitimate users from accessing contract functionality. Attackers might cause loops to revert, block withdrawals, or freeze governance, making the contract unusable.
Q: Which protocols have been exploited via DoS?
A: SynapseBridge (2021) suffered week-long outage from unbounded loop. PolyNetwork (2021) had partial freeze from external call failures. Generic governance protocols regularly face DoS from unbounded voter loops.
Q: How does Firepan detect DoS?
A: Firepan identifies external calls in loops, verifies loop bounds, flags require() statements that block execution, constructs revert scenarios, detects state locks, and identifies single points of failure.
Q: Can DoS be exploited after deployment?
A: Yes, DoS is immediately exploitable post-deployment. Attackers can block withdrawals, freeze governance, or brick operations within hours of deployment.
Q: How do I prevent DoS?
A: Use pull pattern instead of push. Don't require external call success in loops. Use pagination for large datasets. Implement emergency pause. Use try-catch for external calls. Avoid single points of failure.
Denial of Service has impacted protocol availability for weeks, making it a critical vulnerability class. SynapseBridge's week-long outage demonstrated the impact. Using pull patterns, pagination, and try-catch for external calls prevents the vast majority of DoS vulnerabilities. Firepan's HOUND AI detects DoS-vulnerable patterns across all monitored contracts.
Start securing your smart contracts at https://app.firepan.com/
Firepan
Run a free surface scan — results in minutes, no credit card required.
Run Free Scan →Firepan monitors smart contracts on Ethereum using HOUND AI. Detect reentrancy, flash loan attacks, and 20+ vulnerability classes. Start scanning at app.firepan.com.
Firepan monitors smart contracts on Arbitrum using HOUND AI. Detect reentrancy, flash loan attacks, and 20+ vulnerability classes. Start scanning at app.firepan.com.
Learn how front-running (mev) works, see real DeFi exploits, and detect it automatically with Firepan HOUND AI across all monitored contracts. Automated dete...
Learn how integer overflow & underflow works, see real DeFi exploits, and detect it automatically with Firepan HOUND AI across all monitored contracts.
Learn how business logic error works, see real DeFi exploits, and detect it automatically with Firepan HOUND AI across all monitored contracts. Automated det...