Track 7 · The Breach Lab · lesson 5

Overflow and the pre-0.8 world

13 min


Numbers on the EVM have a ceiling and a floor. Go past either and, in the wrong conditions, they wrap around instead of stopping.

A uint256 at zero, minus one, becomes the largest number the machine can hold.

Attacker.solAttacker
Loading editor…
Withdraw more than you put in.

UncheckedVault

? ETH

Nudge
You deposited almost nothing. The withdraw function subtracts the amount from your balance — but what happens when the amount is bigger than your balance and the maths is unchecked?
Show me the approach
An unsigned subtraction that goes below zero wraps around to a near-infinite number, and does not revert. So the vault never notices you overdrew.
Show me the code
In attack(): `vault.deposit{value: 1 wei}(); vault.withdraw(address(vault).balance);`.
Explain the exploit
Before Solidity 0.8, every contract worked like this and SafeMath was mandatory everywhere. 0.8 made checked maths the default — and `unchecked` is the one keyword that opts back into the danger. Use it only where you have proven overflow is impossible.

Why this is history, mostly

Before Solidity 0.8, every arithmetic operation could wrap silently. The entire ecosystem depended on a library called SafeMath, wrapped around every + and -, and forgetting it anywhere was a live vulnerability.

Solidity 0.8 made checked arithmetic the default. Overflow and underflow now revert automatically, and SafeMath is obsolete.

Which is exactly why the one keyword that turns the checks back off — unchecked — deserves suspicion. It exists for cases where you have proven overflow is impossible and want the gas saving. Used anywhere else, it reopens a class of bug the language had closed.

When you legitimately see unchecked

It is not always wrong. A loop counter that cannot exceed an array length, a subtraction guarded by a require on the line above — these are safe, and unchecked saves real gas in hot paths.

The rule: unchecked is a claim that overflow cannot happen here. Every use should come with the reason it is safe, and a reviewer should be able to check that reason.

Predict

You are auditing a contract on Solidity 0.8. Where do you look first for overflow bugs?

Choose one answer

Check

A `uint8` holds 255. You add 1 with checked arithmetic. What happens?

Choose one answer

Worth remembering

  • Unsigned integers wrap on overflow/underflow unless the maths is checked.
  • Before Solidity 0.8, wrapping was the default and SafeMath was mandatory everywhere.
  • 0.8 makes checked arithmetic the default, so overflow now reverts.
  • `unchecked` opts back into wrapping — legitimate for proven-safe gas savings, suspicious otherwise.
  • On 0.8, audit the `unchecked` blocks; below 0.8, audit everything.