In April 2018, an attacker minted 115 quattuordecillion tokens (that's a number with 57 zeros) of BeautyChain (BEC) using a single integer overflow — a number so large it wrapped around to look like a reasonable amount. The "batchOverflow" bug affected dozens of ERC-20 tokens and led to exchanges delisting tokens overnight.
How Integer Overflow/Underflow Works
Solidity's uint256 stores numbers from 0 to 2²⁵⁶-1. When you add 1 to the maximum value, it wraps back to 0 (overflow). When you subtract 1 from 0, it wraps to the maximum value (underflow).
// Pre-Solidity 0.8: VULNERABLE
uint8 max = 255;
max + 1; // = 0 (overflow!)
uint8 zero = 0;
zero - 1; // = 255 (underflow!)
// The batchOverflow exploit
function batchTransfer(address[] memory receivers, uint256 value) public {
uint256 amount = receivers.length * value; // Can overflow to small number
require(balances[msg.sender] >= amount); // Passes due to overflow!
balances[msg.sender] -= amount;
for (uint i = 0; i < receivers.length; i++) {
balances[receivers[i]] += value; // Mints huge amounts
}
}
Solidity 0.8+ Changed Everything (Almost)
Since Solidity 0.8, arithmetic operations revert on overflow/underflow by default. This eliminated the most common bugs. But there are exceptions:
unchecked { }blocks bypass overflow checks for gas optimization- Casting between types (e.g.,
uint256touint128) silently truncates - Division truncation rounds toward zero, losing precision
- Multiplication before division can overflow intermediate values
// STILL VULNERABLE in Solidity 0.8+
function dangerousCalc(uint256 a, uint256 b) external pure returns (uint256) {
unchecked {
return a * b; // Developer used unchecked for gas savings — overflow possible!
}
}
// Precision loss
function getShare(uint256 userAmount, uint256 totalAmount) external pure returns (uint256) {
return userAmount / totalAmount * 1e18; // Division first = precision loss!
// Should be: userAmount * 1e18 / totalAmount
}
Major Arithmetic Exploits
| Protocol | Year | Impact | Bug |
|---|---|---|---|
| BeautyChain (BEC) | 2018 | Token worthless | batchOverflow — infinite mint |
| SMT Token | 2018 | Token worthless | proxyOverflow — multiplication overflow |
| PoWHC | 2018 | $1M+ | Division underflow in fee calculation |
| YAM Finance | 2020 | $750K | Rebase overflow — minted excess governance tokens |
Prevention
- ✅ Use Solidity 0.8+ for automatic overflow protection
- ✅ Audit every
uncheckedblock — ensure overflow is truly impossible - ✅ Multiply before dividing for precision:
a * b / cnota / c * b - ✅ Use safe casting libraries for type conversions
- ✅ Test with boundary values (0, 1, MAX_UINT256)
How Vultbase Detects Arithmetic Issues
- Slither — Detects unchecked blocks, unsafe casts, and division-before-multiplication
- Pattern DB — 27 arithmetic patterns including precision loss, truncation, and rounding attacks
- Challenge Execution — Tests with extreme values to trigger edge cases
Even in Solidity 0.8+, arithmetic bugs lurk in unchecked blocks and precision errors. Get your math audited.