Unchecked addition in _transfer allows receiver balance overflow, corrupting balances and breaking ERC20 invariants
In a correct ERC20 implementation, a transfer must decrease the sender’s balance and increase the receiver’s balance by the transferred amount. Both operations must preserve arithmetic safety: if the receiver’s balance is already at the maximum uint256 value, adding any positive amount must revert.
In this contract, _transfer is implemented in inline assembly and uses a raw add operation to update the receiver’s balance. This addition is not protected by any overflow check. When the receiver’s balance is already type(uint256).max, adding even a value of 1 causes an overflow and wraps the balance back to 0, silently corrupting state.
Likelihood:
This occurs whenever a transfer is made to an address whose balance is already close to or equal to type(uint256).max, which can be reached through unrestricted minting or prior overflows.
Any system that allows minting large values or interacts with this token without upper-bound checks can unintentionally trigger this condition.
Impact:
Receiver balances can overflow and wrap to zero or a low value, effectively destroying tokens and violating the invariant that transfers conserve total value.
Accounting corruption may cascade into other logic that relies on balances (governance, staking, collateralization), leading to denial of service or economic loss.
The following test shows that transferring tokens to an address with a maximum balance does not revert. Instead, the receiver’s balance silently overflows and wraps to zero.
Explanation:
The receiver is first minted type(uint256).max tokens. The sender is minted a single token and transfers it to the receiver. Inside _transfer, the receiver’s balance update uses add(max, 1), which wraps to 0 in unchecked assembly arithmetic. The transfer succeeds, but the resulting balance is invalid.
Add an explicit overflow check before increasing the receiver’s balance, or move arithmetic out of assembly to rely on Solidity’s checked arithmetic.
_transfer function:
This ensures that transfers to accounts at or near the maximum balance revert instead of corrupting state.
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.
The contest is complete and the rewards are being distributed.