Trusted by Professionals for 10+ Years | Flat 20% OFF | Code: SKILL
Blockchain Council
smart contracts7 min read

Integer Overflow and Underflow in Smart Contracts: Risks and Fixes

Suyash RaizadaSuyash Raizada
Integer Overflow and Underflow in Smart Contracts: Risks and Fixes

Integer overflow and underflow in smart contracts can turn a small arithmetic mistake into a direct loss of funds. Solidity 0.8.x made checked arithmetic the default, so new EVM contracts are safer than old ones. Still, the bug has not disappeared. It now hides in legacy contracts, unchecked blocks, custom math libraries, and non-EVM environments where arithmetic rules differ.

If you write, review, or manage smart contract systems, treat numeric behavior as part of your threat model. Balances, allowances, reward rates, vesting schedules, and supply caps are all just integers with money attached.

Certified Artificial Intelligence Expert Ad Strip

What Are Integer Overflow and Underflow?

An integer overflow happens when a calculation produces a value larger than the integer type can store. An integer underflow happens when a value drops below the minimum allowed value. For unsigned integers, that minimum is usually zero.

On systems with wrapping arithmetic, the value rolls around. A maximum value can become zero. Zero minus one can become the largest possible value. That sounds academic until the number represents a token balance.

Take an old Solidity version before 0.8.0. This pattern was dangerous:

pragma solidity ^0.7.6;

contract BadVault {
    mapping(address => uint256) public balance;

    function withdraw(uint256 amount) external {
        balance[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
    }
}

If balance[msg.sender] is zero and amount is greater than zero, the subtraction can underflow in legacy Solidity. The balance may wrap to a huge number instead of reverting. That breaks the core rule: you cannot withdraw more than you own.

Why This Still Matters After Solidity 0.8

Solidity 0.8.0 changed the default. Addition, subtraction, and multiplication now revert on overflow or underflow. Run a failing arithmetic operation in a Hardhat test and you may see an error like: reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block). That panic code is a useful signal. It means the compiler caught the arithmetic failure before state was corrupted.

Good change. Not a complete fix.

The current risk is concentrated in four places:

  • Legacy Solidity contracts compiled with versions before 0.8.0.
  • Unchecked arithmetic where developers intentionally disable compiler checks.
  • Custom math libraries used for fees, rewards, interest, AMMs, or fixed-point calculations.
  • Non-EVM platforms where overflow behavior may not match Solidity 0.8.x expectations.

OWASP lists SC09: Integer Overflow and Underflow in its Smart Contract Top 10. That is telling. Language improvements reduced the easy cases, but auditors still find numeric bugs in high-value code.

How Overflow and Underflow Break Smart Contracts

1. Corrupted balances

Token contracts, vaults, lending pools, and staking systems rely on balance accounting. Underflow in a balance decrement can create fake funds. Overflow in minting logic can distort total supply. In DeFi, that often means the attacker can drain a pool or claim rewards they never earned.

2. Bypassed limits

Many contracts enforce rules with integer comparisons: maximum withdrawal caps, minimum collateral ratios, cooldown periods, or per-wallet limits. If a counter wraps, a limit can become meaningless.

A simple quota bug can be enough. Suppose a user has one withdrawal left. A faulty decrement from zero may wrap the quota to a massive value, giving the attacker far more access than intended.

3. Excessive payouts

Reward formulas are especially risky. Multipliers, bonus tiers, and time-based interest can overflow if inputs are not bounded. The bug may not show up in ordinary tests because test values are usually small. Attackers do not use ordinary values.

4. Denial of service

Checked arithmetic can also cause availability problems if the contract design does not expect reverts. A loop counter, accumulator, or reward index that overflows may stop a critical function. In Solidity 0.8.x this is safer than silent corruption, but a locked protocol is still a serious incident.

A Real Attack Pattern: Underflow-Based Theft

A widely cited Ethereum underflow case let an attacker steal 866 Ether. The pattern was simple. An unsigned subtraction went below zero, wrapped to a very large value, and let the attacker withdraw more Ether than they had deposited.

This is why auditors obsess over plain-looking lines like:

balances[msg.sender] = balances[msg.sender] - amount;

In Solidity 0.8.x, that line reverts on underflow. In older contracts, it may not. If you audit legacy Solidity, check the pragma first. A file using pragma solidity ^0.7.0; should immediately push you to look for SafeMath, manual checks, and arithmetic around user-controlled values.

Solidity 0.8+ Fixes and Their Limits

For new EVM contracts, the first fix is straightforward:

pragma solidity ^0.8.20;

contract SafeVault {
    mapping(address => uint256) public balance;

    function withdraw(uint256 amount) external {
        require(balance[msg.sender] >= amount, 'Insufficient balance');
        balance[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
    }
}

Solidity checks the subtraction. The require also documents the business rule and gives a clear error. Use both. Compiler checks prevent numeric wraparound, and explicit validation makes intent obvious to reviewers.

Be careful with unchecked blocks

The unchecked keyword disables overflow and underflow checks inside a block:

unchecked {
    i++;
}

This can be reasonable in tight loops where you have already proven the bounds. Incrementing a loop counter under a condition like i < array.length is often safe. But do not use unchecked around balances, debt, collateral, shares, supply, or rewards unless you can prove the invariant on paper and in tests.

To be blunt: if the only reason is saving a little gas, it is usually the wrong trade-off for financial arithmetic.

What About SafeMath?

Before Solidity 0.8.0, OpenZeppelin SafeMath was the standard defense. It wrapped arithmetic operations with checks and reverted on invalid results. In legacy contracts, SafeMath is still valuable.

For new Solidity 0.8.x contracts, SafeMath is usually unnecessary for basic arithmetic because the compiler already checks it. You may still see it in older codebases, upgradeable systems that began pre-0.8, or teams that keep it for readability. Do not assume SafeMath makes a contract safe. It only addresses arithmetic wrapping. It does not fix bad formulas, missing access control, oracle manipulation, or flawed accounting.

Non-EVM Platforms Need Separate Review

Do not carry Solidity assumptions into every chain. Overflow behavior differs across non-EVM platforms. Some operations abort. Some wrap. Some languages have special cases. Move, for example, handles shift operations differently from what a developer might expect from checked arithmetic.

Rust-based smart contract environments, including Solana programs, also need care. In Rust, debug and release behavior, compiler settings, and methods such as checked_add, saturating_add, and wrapping_add matter. If you see plain arithmetic in financial logic, ask what happens at the boundary.

A Practical Checklist to Prevent Integer Bugs

Use this checklist during development and audit review:

  1. Compile with Solidity 0.8.x or later for new EVM contracts.
  2. Audit every unchecked block. Require a written reason and a test that covers the boundary.
  3. Validate inputs before arithmetic, especially user-controlled amounts, timestamps, multipliers, and oracle-fed values.
  4. Use appropriate integer sizes. In most Solidity contracts, uint256 is the safest default unless storage packing is clearly needed.
  5. Test edge values: zero, one, maximum supply, maximum withdrawal, full allowance, empty balance, and extreme reward duration.
  6. Fuzz critical functions with tools such as Foundry, Echidna, or Medusa.
  7. State invariants clearly. For example: total user shares must never exceed total shares, and total token balances must match tracked deposits.
  8. Review custom math libraries as high-risk code, not utility code.

Testing Example: Catch the Boundary, Not Just the Happy Path

A common beginner mistake is testing only a normal withdrawal, such as depositing 1 Ether and withdrawing 0.5 Ether. Add the failing path too:

function testCannotWithdrawMoreThanBalance() public {
    vm.expectRevert(bytes('Insufficient balance'));
    vault.withdraw(2 ether);
}

In Foundry, that test makes the business rule executable. You should also fuzz the amount. Let the test runner search for values you did not think of. This is where edge cases appear quickly.

Where Professionals Should Go Deeper

If your work involves production smart contracts, integer overflow and underflow should be part of a wider secure development process. That includes threat modeling, code review, static analysis, fuzzing, and independent audits.

For structured learning, connect this topic with paths such as the Certified Smart Contract Developer™, Certified Solidity Developer™, and Certified Blockchain Developer™ programs. Developers focused on audits should also study common vulnerability classes such as reentrancy, access control failures, oracle manipulation, and signature replay.

Final Takeaway

Integer overflow and underflow in smart contracts are no longer the everyday Solidity trap they were before version 0.8.0, but they remain high impact. The safest path is simple: use checked arithmetic by default, avoid unchecked math in financial logic, test numeric boundaries, and review platform-specific arithmetic rules before deployment.

Your next step: open one contract you maintain and search for unchecked, old Solidity pragmas, custom math, and balance updates. Those four searches catch a surprising amount of real risk.

Related Articles

View All

Trending Articles

View All