Token-0x

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

Missing Transfer Event on `_mint`

Author Revealed upon completion

Description

  • The ERC20 standard requires that minting tokens MUST emit a Transfer event with from set to address(0). This is explicitly stated in EIP-20.

  • Token-0x's _mint function does not emit any events, making mints invisible to off-chain services.

function _mint(address account, uint256 value) internal {
assembly ("memory-safe") {
// ... minting logic ...
// @> NO EVENT EMITTED!
// Should emit: Transfer(address(0), account, value)
}
}

Risk

Likelihood:

  • Every mint operation will fail to emit events

  • This is 100% reproducible

Impact:

  • Block explorers (Etherscan) won't show mint transactions

  • Wallets won't detect incoming minted tokens

  • DeFi protocols indexing Transfer events will miss mints

  • The Graph and similar indexers will have incomplete data

  • Token tracking and analytics services will be broken

Proof of Concept

function test_mint_no_event() public {
vm.recordLogs();
token.mint(alice, 100e18);
Vm.Log[] memory logs = vm.getRecordedLogs();
// Token-0x emits 0 events
assertEq(logs.length, 0);
// OpenZeppelin emits 1 Transfer event
vm.recordLogs();
token2.mint(alice, 100e18);
logs = vm.getRecordedLogs();
assertEq(logs.length, 1);
}

Recommended Mitigation

Add the following lines at the end of the _mint function assembly block:

function _mint(address account, uint256 value) internal {
assembly ("memory-safe") {
if iszero(account) {
mstore(0x00, shl(224, 0xec442f05))
mstore(add(0x00, 4), 0x00)
revert(0x00, 0x24)
}
let ptr := mload(0x40)
let balanceSlot := _balances.slot
let supplySlot := _totalSupply.slot
let supply := sload(supplySlot)
sstore(supplySlot, add(supply, value))
mstore(ptr, account)
mstore(add(ptr, 0x20), balanceSlot)
let accountBalanceSlot := keccak256(ptr, 0x40)
let accountBalance := sload(accountBalanceSlot)
sstore(accountBalanceSlot, add(accountBalance, value))
+
+ // Emit Transfer(address(0), account, value)
+ mstore(ptr, value)
+ log3(ptr, 0x20, 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0, account)
}
}

Support

FAQs

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

Give us feedback!