Integer Overflow / Underflow

Every integer type in Solidity has a fixed size. A uint8, for example, can hold values from 0 to 255. If you add 1 to 255, it wraps back to 0 — this is overflow. Subtract 1 from 0 and you get 255 — this is underflow. Before Solidity 0.8.0, these operations happened silently with no error.

How it works

Attackers exploit overflow and underflow to bypass balance checks, manipulate token supplies, or unlock hidden paths in contract logic.

Vulnerable pattern (Solidity < 0.8.0)

// VULNERABLE — uint8 overflows at 255
function transfer(address to, uint8 amount) public {
    balances[msg.sender] -= amount;  // underflow if amount > balance
    balances[to] += amount;
}

// Attacker passes amount = 256, and balances[msg.sender] wraps to a huge number

Safe pattern

// SAFE — Solidity 0.8+ reverts on overflow/underflow by default
// Or use OpenZeppelin SafeMath for older compiler versions:
using SafeMath for uint256;
balances[msg.sender] = balances[msg.sender].sub(amount);
balances[to] = balances[to].add(amount);

Real-world exploits

  • BECToken (2018) — overflow in the batch transfer function allowed attackers to mint an astronomical number of tokens.
  • SmartMesh (2018) — similar overflow exploit used to generate unlimited tokens.

How to prevent it

  • Use Solidity 0.8.0 or later — arithmetic reverts on overflow/underflow by default.
  • For older code, use OpenZeppelin SafeMath.
  • Use unchecked { } blocks only when you are certain no overflow can occur (e.g., loop counters in known-bounded loops).
← Back to Glossary