Token-0x

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

Contract Should Be Abstract - Missing Public Mint/Burn Functions

Author Revealed upon completion

Root + Impact

Description

The ERC20 contract is not marked as abstract, yet it lacks public mint and burn functions. This means:

  • The contract can be deployed directly, but will have 0 total supply with no way to create tokens

  • The contract is essentially unusable when deployed standalone

  • This contradicts the intended design pattern (similar to OpenZeppelin's ERC20) where it should be used as a base class

For example: OpenZeppelin's ERC20 implementation is explicitly marked as abstract with documentation stating: "This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using {_mint}."

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

Risk

Likelihood:

  • Nothing preventing user to driectly deploy the contract expecting them to work standalone

Impact:

  • Users can deploy a useless token contract (0 supply, no way to mint)

  • Confusion about intended usage pattern

  • Inconsistency with industry standards (OpenZeppelin pattern)

Proof of Concept

This test verifies that a token can be deployed directly with 0 supply and there is no way to mint more tokens after deployment.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {Test} from "forge-std/Test.sol";
import {ERC20} from "../src/ERC20.sol";
contract Token0xTest is Test {
ERC20 public token;
function setUp() public {
token = new ERC20("Token0x", "TKN0x");
}
function test_metadataAndMintFunctionsExists() public {
assertEq(token.name(), "Token0x");
assertEq(token.symbol(), "TKN0x");
assertEq(token.decimals(), 18);
assertEq(token.totalSupply(), 0);
(bool success,) =
address(token).call(abi.encodeWithSignature("mint(address,uint256)", makeAddr("account"), 100e18));
assertEq(success, true);
}
}

Recommended Mitigation

Mark the contract as abstract, and extend the token documentation with the note: "This implementation is agnostic to the way tokens are created. This means that a supply mechanism has to be added in a derived contract using _mint."

- contract ERC20 is IERC20Errors, ERC20Internals, IERC20 {
+ abstract contract ERC20 is IERC20Errors, ERC20Internals, IERC20 {
// ... rest of implementation
}

Support

FAQs

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

Give us feedback!