SCWE-109: Unbounded Loops on Untrusted Input
Stable Version v1.0
This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Relationships¶
- CWE-834: Excessive Iteration
https://cwe.mitre.org/data/definitions/834.html
Description¶
Iterating over user-controlled arrays or mappings without bounds lets attackers submit large inputs that exhaust gas, causing denial of service. Functions like batch withdrawals, reward distribution, or liquidations may become permanently unusable.
Remediation¶
- Impose upper bounds on loop iterations or batch sizes.
- Use pagination/iterative processing with checkpoints.
- Avoid on-chain iteration over untrusted lists; rely on off-chain aggregation with verifiable proofs (Merkle leaves).
Examples¶
Vulnerable¶
pragma solidity ^0.8.0;
contract Distributor {
function airdrop(address[] calldata users) external {
for (uint256 i = 0; i < users.length; i++) {
(bool ok, ) = payable(users[i]).call{value: 1 ether}("");
require(ok, "Transfer failed"); // can run out of gas with large arrays
}
}
}
Fixed¶
pragma solidity ^0.8.0;
contract Distributor {
uint256 public last;
function airdrop(address[] calldata users, uint256 max) external {
uint256 end = last + max;
if (end > users.length) end = users.length;
for (uint256 i = last; i < end; i++) {
(bool ok, ) = payable(users[i]).call{value: 1 ether}("");
require(ok, "Transfer failed");
}
last = end;
}
}