Token-0x

First Flight #54
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: high
Likelihood: high

Infinite Token Minting via Self-Transfer

Author Revealed upon completion
# Critical Vulnerability: Infinite Token Minting via Self-Transfer
## Submission Details
**Title:** Infinite Token Minting via Self-Transfer
**Impact:** Critical
**Likelihood:** High
**Scope:** `src/helpers/ERC20Internals.sol`
## Description
**Root + Impact:**
The `_transfer` function uses Yul assembly to optimize gas. It loads the `from` and `to` balances into memory *before* updating storage. When `from` equals `to` (self-transfer), the function writes the decremented balance to the slot, but immediately overwrites it with the incremented balance in the subsequent `sstore` instruction. This allows a user to increase their balance by the transfer amount simply by transferring tokens to themselves.
**Solidity:**
```solidity
// src/helpers/ERC20Internals.sol
let fromAmount := sload(fromSlot) // Load sender balance
// ...
let toAmount := sload(toSlot) // Load recipient balance (same as sender)
// ... checks ...
sstore(fromSlot, sub(fromAmount, value)) // Write 1: balance - value
sstore(toSlot, add(toAmount, value)) // Write 2: balance + value (Overwrites Write 1)
```
## Risk
**Likelihood:** High
**Reason 1:** Any user can call `transfer` with their own address as the recipient.
**Reason 2:** No special privileges are required.
**Impact:** Critical
**Impact 1:** Malicious users can mint infinite tokens.
**Impact 2:** Total collapse of the token economy.
## Proof of Concept
```solidity
function testSelfTransferInfiniteMint() public {
token.mint(alice, 100);
assertEq(token.balanceOf(alice), 100);
vm.prank(alice);
token.transfer(alice, 100);
// Balance becomes 100 + 100 = 200 due to overwrite
assertEq(token.balanceOf(alice), 200);
}
```
## Recommended Mitigation
```diff
function _transfer(address from, address to, uint256 value) internal returns (bool success) {
assembly ("memory-safe") {
// ... checks ...
+ if eq(from, to) {
+ success := 1
+ leave
+ }
let ptr := mload(0x40)
// ...
```

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!