A denial-of-service (DoS) vulnerability allows an attacker to make a contract permanently unusable. In smart contracts, the most common DoS patterns involve blocking critical functions by exploiting gas limits, reverting external calls, or exhausting storage.
// VULNERABLE — iterates users and sends ETH; one bad recipient blocks all
function distributeRewards() public {
for (uint i = 0; i < users.length; i++) {
// If any user's fallback reverts, the entire distribution reverts
payable(users[i]).transfer(rewards[users[i]]);
}
}
// Attacker adds a contract that reverts on receive:
receive() external payable { revert(); }
// Now distributeRewards() is permanently bricked
// SAFE — each user claims their own reward
mapping(address => uint) public pendingRewards;
function claimReward() public {
uint amount = pendingRewards[msg.sender];
pendingRewards[msg.sender] = 0;
(bool ok,) = msg.sender.call{value: amount}("");
require(ok, "Transfer failed");
// If this reverts, only the claimer is affected
}
// VULNERABLE — loop over unbounded array
function clearAll() public {
for (uint i = 0; i < allUsers.length; i++) {
delete balances[allUsers[i]];
}
// Attacker floods allUsers with 10,000 addresses — function runs out of gas
}
If a contract requires owner approval for critical actions but the owner key is lost or the owner is a compromised address, the contract can be permanently frozen.