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.
UncheckedVault
? ETH
Nudge
Show me the approach
Show me the code
Explain the exploit
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?
Check
A `uint8` holds 255. You add 1 with checked arithmetic. What happens?
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.