burnFaucetTokens(uint256 amountToBurn) currently transfers the entire token balance held by the faucet contract to the owner, then burns only amountToBurn from the owner’s balance. This leaves the owner with (contractBalance - amountToBurn) tokens instead of burning exactly amountToBurn from the contract.
The function is intended to let the owner burn a specified amount of faucet tokens from the contract’s balance. Instead, the implementation transfers the contract’s full ERC20 token balance to the owner and then calls _burn(msg.sender, amountToBurn). This sequence results in only amountToBurn being removed from supply while most of the contract tokens end up in the owner’s wallet.
This behavior contradicts the parameter name. burnFaucetTokens(100) should burn 100 tokens from the faucet, not give the owner the remainder of the faucet balance.
Likelihood:
The _transfer call moves the entire contract balance instead of the intended amountToBurn, then _burn removes only amountToBurn from the owner. The net effect: owner keeps balanceOf(contract) - amountToBurn.
Impact:
Owner (or attacker who controls the owner key) can move the contract’s entire token balance to themselves and burn only the requested amount - effectively exfiltrating almost all contract-held tokens.
Run the above POC using the following command:
Explanation:
contractBalBefore = X (e.g. initial supply minted to contract).
After call: contractBalAfter = 0 (bug: contract emptied).
ownerBalAfter = ownerBalBefore + X - amountToBurn (owner keeps nearly all tokens).
totalSupply reduced by only amountToBurn (not X).
Burn directly from the contract balance - no transfer to owner:
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.