Unchecked overflow in _mint() can corrupt totalSupply and user balances, potentially breaking token accounting and downstream integrations.
Normal behavior: A correct ERC20 _mint() implementation should increase totalSupply and the recipient’s balance, and revert if the operation would overflow uint256. In practice, totalSupply + value and balance + value must always remain within type(uint256).max.
Issue: The current _mint() implementation performs raw Yul add() operations on both totalSupply and accountBalance without any overflow checks. Since Yul arithmetic is modulo 2²⁵⁶, minting enough tokens causes both totalSupply and the recipient’s balance to silently wrap around to a much smaller value instead of reverting, breaking ERC20 invariants.
Likelihood:
Any derived token that exposes _mint() via a public mint() or uses it in token distribution logic can accidentally mint near the uint256 limit, especially for uncapped or governance-controlled tokens.
Developers may assume Solidity 0.8+ style overflow protection applies everywhere and forget that this low-level assembly bypasses it, making misuse likely in future extensions.
Impact:
totalSupply can overflow, wrapping from a large value back to a very small value (even 0), breaking supply-based logic, caps, and downstream protocols.
User balances can overflow, resetting balances or making accounting inconsistent across DEXes, lending protocols, and indexers that rely on ERC20 invariants.
The following Foundry test demonstrates how the _mint() function performs unchecked addition on both totalSupply and user balances. By setting these values close to uint256.max and calling mint(), both variables silently overflow and wrap to a small number instead of reverting.
Observed Results
The logs confirm that when both totalSupply and the attacker’s balance are set near uint256.max, calling _mint(attacker, 10) causes the following:
totalSupply + value overflows and wraps to 4
balanceOf(attacker) + value also wraps to 4
No revert occurs because _mint() uses raw Yul add() which does not check for overflow
This demonstrates a critical accounting flaw: minting tokens near the uint256 limit silently corrupts both balances and total supply, violating ERC20 invariants and risking downstream protocol failures.
The fix adds explicit overflow checks to both totalSupply and user balances before performing the Yul add() operation, which does not revert on overflow. By verifying that value does not exceed uint256.max - currentValue, the mint operation can only proceed when arithmetic stays within bounds. This prevents silent wrap-around that previously caused totalSupply and balances to reset to small numbers when near the limit. Additionally, the fix corrects zero-address error handling and adds the required Transfer(address(0), account, value) event for ERC20 compliance. As a result, minting can no longer corrupt supply or balances, ERC20 invariants remain intact, and the overflow exploit demonstrated in the PoC is fully mitigated.
Prevents overflow of totalSupply
Prevents overflow of user balances
Ensures ERC20-compliant event emission
Eliminates silent wrap-around demonstrated in the exploit
missing checks for overflow and underflow.
missing checks for overflow and underflow.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.