The _burn function at lines 158-180 in ERC20Internals.sol should validate that an account has sufficient balance before burning tokens. Similar to the _transfer function (lines 118-124) which correctly checks fromAmount >= value before performing a transfer, the _burn function should verify accountBalance >= value before subtracting from the balance. When the balance is insufficient, the function should revert with a proper ERC20InsufficientBalance error that includes the account address, current balance, and required amount.
The _burn function loads the account's balance but never validates that accountBalance >= value before performing the subtraction operation. When a user attempts to burn more tokens than they hold, the Yul assembly sub operation causes an arithmetic underflow that wraps around instead of reverting. This results in the account balance and total supply being set to a massive number (approximately 2^256 - (value - balance)) instead of reverting with a proper error. The function lacks the balance validation check that exists in _transfer, creating a critical security inconsistency in the codebase.
Likelihood:
High - The vulnerability occurs whenever a user or contract calls the burn function with an amount greater than their current balance. Since the function is public and can be called by any address that has access to a token contract inheriting from ERC20, this condition can be triggered intentionally or accidentally during normal operations.
High - The vulnerability manifests during token burn operations when the burn amount exceeds the account balance. The Yul assembly code performs unchecked arithmetic subtraction, causing the underflow wrap-around to occur immediately when value > accountBalance, without any validation to prevent it.
Impact:
Critical - Token supply inflation attack: An attacker can burn more tokens than they hold, causing the total supply to wrap around to a massive number (approximately 2^256 - difference). This effectively creates an infinite token supply, breaking the token's economic model and potentially causing all subsequent token operations to fail due to overflow in calculations.
Critical - State corruption: The account balance and total supply are permanently corrupted with wrap-around values. This breaks the token's accounting system, making it impossible to accurately track balances, perform transfers, or calculate the true token supply. The corrupted state persists and cannot be easily recovered without a contract upgrade or migration.
The proof of concept demonstrates that when attempting to burn more tokens than available, the Yul sub operation in unchecked assembly causes an arithmetic underflow that wraps around instead of reverting. The balance and total supply are set to a massive number (approximately 2^256 - (value - balance)) instead of reverting with a proper ERC20InsufficientBalance error.
The Yul assembly code uses sub(accountBalance, value) without checking if accountBalance >= value first. Unlike Solidity's checked arithmetic which would revert, the Yul operation wraps around, allowing the burn to succeed and corrupting the token state.
The fix adds balance validation before performing the burn operation, matching the pattern used in the _transfer function. The balance check (if lt(accountBalance, value)) compares the account's balance with the amount to be burned before any state changes occur. When insufficient balance is detected, the function reverts with the ERC20InsufficientBalance error (selector 0xe450d38c), encoding the account address, current balance, and required amount in the error data.
This prevents the arithmetic underflow wrap-around by validating balance before subtraction, ensures consistent error handling with _transfer, and provides clear error messages. The fix also adds the missing Transfer event emission for ERC20 compliance. After applying the mitigation, all POC tests should pass, with test_burnShouldRevertWithProperError() correctly reverting with the proper error.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.