Token-0x

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

Self-Transfer Logic Error in `_transfer` Allows Infinite Token Minting

Author Revealed upon completion

Description

  • The _transfer function is intended to move tokens from one address to another by decreasing the sender's balance and increasing the recipient's balance.

  • The implementation loads both balances into stack variables before writing any storage updates; in a self-transfer scenario where from equals to, the second storage write (the addition) overwrites the first (the subtraction), resulting in a net increase of the user's balance equal to the transfer amount.

/// File: src/helpers/ERC20Internals.sol:L112-L127
let fromAmount := sload(fromSlot) // Load 100
...
let toAmount := sload(toSlot) // Load 100
...
sstore(fromSlot, sub(fromAmount, value)) // Write 90
@> sstore(toSlot, add(toAmount, value)) // Write 110 (OVERWRITES 90)

Risk

Likelihood:

  • Any user executes a self-transfer transaction transfer(msg.sender, amount) to trigger this logic aliasing.

Impact:

  • A malicious user can infinitely mint tokens to their own address, completely destroying the token economy.

  • The protocol becomes insolvent immediately as total supply invariants are broken.

Proof of Concept

function test_SelfTransferInfiniteMoney() public {
// 1. Setup
// Mint 10 tokens to Alice to start
token.mint(alice, 10);
// 2. Exploit steps
// Alice transfers 10 tokens to herself
vm.prank(alice);
token.transfer(alice, 10);
// 3. Assertions (impact)
// Initial: 10. Logic: write (10-10=0) to slot, then write (10+10=20) to SAME slot.
// Result should be 20.
console.log("Alice Balance:", token.balanceOf(alice));
assertEq(token.balanceOf(alice), 20, "Alice duplicated her tokens!");
}

Recommended Mitigation

- let toAmount := sload(toSlot)
// ...
sstore(fromSlot, sub(fromAmount, value))
+ let toAmount := sload(toSlot) // Load AFTER writing from if separate
sstore(toSlot, add(toAmount, value))

Support

FAQs

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

Give us feedback!