Smart Contract Security

Integer Overflow and Underflow: The Silent Killers in Smart Contract Math

Kennedy OwiroJanuary 25, 20268 min read

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., uint256 to uint128) 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

ProtocolYearImpactBug
BeautyChain (BEC)2018Token worthlessbatchOverflow — infinite mint
SMT Token2018Token worthlessproxyOverflow — multiplication overflow
PoWHC2018$1M+Division underflow in fee calculation
YAM Finance2020$750KRebase overflow — minted excess governance tokens

Prevention

  • ✅ Use Solidity 0.8+ for automatic overflow protection
  • ✅ Audit every unchecked block — ensure overflow is truly impossible
  • ✅ Multiply before dividing for precision: a * b / c not a / c * b
  • ✅ Use safe casting libraries for type conversions
  • ✅ Test with boundary values (0, 1, MAX_UINT256)

How Vultbase Detects Arithmetic Issues

  1. Slither — Detects unchecked blocks, unsafe casts, and division-before-multiplication
  2. Pattern DB — 27 arithmetic patterns including precision loss, truncation, and rounding attacks
  3. 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.

integer overflowunderflowarithmeticSafeMathSoliditysmart contract bugs
Share

Written by

Kennedy Owiro

Founder & CTO, Vultbase

14+ years building security and QA systems at scale. Background in fintech security and Web3 smart contract testing. Built Vultbase's Intelligence Engine with 1,200+ exploit patterns from $40B+ in historical DeFi losses.

Protect your protocol before launch.

Submit your smart contracts for automated security analysis powered by 1,200+ real exploit patterns.

Start Your Audit →