Token-0x

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

Insufficient access control in mint and burn functions

Author Revealed upon completion

Root + Impact

Description

  • The _mint and _burn functions are marked as internal but have no access control mechanisms in the base contract. Any contract that inherits from this ERC20 implementation can expose these functions publicly without restrictions. There's no built-in role-based access control, ownership pattern, or any mechanism to prevent unauthorized minting or burning. This violates the principle of defense in depth and could lead to severe economic attacks if not properly restricted in inheriting contracts.

function _mint(address account, uint256 value) internal {
// No access control - any inheriting contract can call this
assembly ("memory-safe") {
// ... minting logic ...
}
}
function _burn(address account, uint256 value) internal {
// No access control - any inheriting contract can call this
assembly ("memory-safe") {
// ... burning logic ...
}
}

Risk

Likelihood:

  • Medium

Impact:

  • If a developer inheriting this contract accidentally or intentionally exposes mint/burn functions without proper access control, attackers could mint unlimited tokens or burn other users' tokens, leading to complete economic failure of the token.

Proof of Concept

Declare another contract,and we can call functions from it

// Vulnerable implementation by developer
contract VulnerableToken is ERC20 {
constructor() ERC20("Vulnerable", "VULN") {}
// Developer exposes mint without access control
function mint(address to, uint256 amount) public {
_mint(to, amount); // Anyone can call this!
}
// Developer exposes burn without proper checks
function burn(address from, uint256 amount) public {
_burn(from, amount); // Anyone can burn anyone's tokens!
}
}
// Attack:
VulnerableToken token = VulnerableToken(tokenAddress);
token.mint(attacker, 1000000 * 10**18); // Mint 1M tokens
token.burn(victim, victimBalance); // Burn victim's tokens

Recommended Mitigation

Implement a base access control mechanism in the ERC20 contract itself, such as OpenZeppelin's Ownable or AccessControl patterns. At minimum, add internal flags or modifiers that force inheriting contracts to explicitly implement access control

+ add this code
contract ERC20 is IERC20Errors, ERC20Internals {
// Force inheriting contracts to implement access control
modifier onlyMinter() {
require(_canMint(msg.sender), "Not authorized to mint");
_;
}
modifier onlyBurner() {
require(_canBurn(msg.sender), "Not authorized to burn");
_;
}
// Abstract functions that must be implemented
function _canMint(address account) internal view virtual returns (bool);
function _canBurn(address account) internal view virtual returns (bool);
function _mint(address account, uint256 value) internal onlyMinter {
// ... existing logic ...
}
function _burn(address account, uint256 value) internal onlyBurner {
// ... existing logic ...
}
}

Support

FAQs

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

Give us feedback!