Token-0x

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

Missing Transfer Events from Address(0) in _mint() and _burn() – Breaks ERC20 Standard Compliance

Author Revealed upon completion

Normal Behavior

According to the ERC20 standard, the Transfer event must be emitted on every token balance change, including:

  • Minting: Transfer(address(0), account, value) (from zero address)

  • Burning: Transfer(account, address(0), value) (to zero address)

  • Transfers: Transfer(from, to, value)

specific issue

The _mint and _burn functions in the contract do not emit any Transfer events, while only the _transfer function correctly emits the event.

function _mint(address account, uint256 value) internal {
assembly ("memory-safe") {
// ... logic to increase supply and balance ...
//NO Transfer event emitted!
}
}

function _burn(address account, uint256 value) internal {
assembly ("memory-safe") {
// ... logic to decrease supply and balance ...
// NO Transfer event emitted!
}
}

https://github.com/CodeHawks-Contests/2025-12-token-0x/blob/7f9f55d58a485a36fb56284d8d0e8a415544bf9b/src/helpers/ERC20Internals.sol#L155

https://github.com/CodeHawks-Contests/2025-12-token-0x/blob/7f9f55d58a485a36fb56284d8d0e8a415544bf9b/src/helpers/ERC20Internals.sol#L179

// Root cause in the codebase with @> marks to highlight the relevant section

Risk

Likelihood: Certain

  • Every mint and burn operation will fail to emit required events

  • This violates the ERC20 standard explicitly

  • External tools rely on these events to track token supply changes

Impact: Medium

  • Broken Compliance: Contract is not ERC20 compliant

  • Audit Failure: Will fail any standard ERC20 compliance audit

Proof of Concept

// Deploy token
ERC20 token = new ERC20();
token._mint(alice, 1000);
// Check events - NO Transfer event emitted!
// External indexers see total supply increase but no Transfer from address(0)
// Burn 500 tokens from Alice
token._burn(alice, 500);
// Check events - NO Transfer event emitted!
// External indexers see total supply decrease but no Transfer to address(0)

Recommended Mitigation

function _mint(address account, uint256 value) internal {
assembly ("memory-safe") {
// ... existing mint logic ...
mstore(0x00, value)
log3(0x00, 0x20,
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, // Transfer event signature
0x00, // from = address(0) for mint
account)
}
}
function _burn(address account, uint256 value) internal {
assembly ("memory-safe") {
// ... existing burn logic ...
// ADD Transfer event for burning
mstore(0x00, value)
log3(0x00, 0x20,
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, // Transfer event signature
account, // from = account
0x00) // to = address(0) for burn
}
}

Support

FAQs

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

Give us feedback!