Normal Behavior: When a user transfers tokens to themselves (from == to), the balance should remain unchanged since the same amount is subtracted and added.
Specific Issue: In _transfer, the code loads toAmount from storage before writing the updated fromAmount. When from == to, both slots are identical. The sstore(fromSlot, sub(fromAmount, value)) executes first, but sstore(toSlot, add(toAmount, value)) uses the old toAmount (loaded before the first sstore), effectively adding value to the original balance.
Likelihood:
High: Self-transfers are common UX patterns (e.g., "refresh" balance in wallets, testing, or accidental same-address input).
High: Any user can exploit this without special permissions.
Impact:
Critical: Users can mint infinite tokens by repeatedly self-transferring. Each self-transfer of X increases balance by X.
Economic Collapse: Token supply invariant is broken; attackers can drain liquidity pools or manipulate governance.
User starts with 100 tokens, self-transfers 50, ends with 150 tokens.
Add early return for self-transfers or reload toAmount after fromSlot write:
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.