The burnFaucetTokens(uint256 amountToBurn) function transfers the entire token balance held by the faucet contract to the owner, and only then burns amountToBurn from the owner’s balance. This sequence lets the owner retain any excess tokens (i.e., balanceOf(address(this)) - amountToBurn) in their personal account. It contradicts the faucet’s stated behavior that the owner cannot claim faucet tokens and that burning should reduce the faucet’s holdings, not enrich the owner.
Likelihood:
The vulnerable burnFaucetTokens() function is public and callable by the owner at any time, with no additional guardrails or timelocks. This means exploitation occurs as soon as the owner (or a compromised owner key) executes the function, regardless of system state.
The code path is directly incentivized, since the owner gains liquid faucet tokens instantly while only burning a fraction, making exploitation highly probable in real-world conditions or in the event of key compromise.
Impact:
The owner can extract all faucet tokens while only burning a negligible fraction.
Faucet loses its token reserves, halting all user claims.
Attack Scenario
Faucet holds the INITIAL_SUPPLY_MINTED.
Owner calls burnFaucetTokens(10e18).
Contract transfers all tokens to the owner, then burns only 10e18.
Result: owner keeps a **huge amount of **tokens; the faucet balance becomes zero.
Paste the following test in RaiseBoxFaucet.t.sol
Burn directly from the faucet’s balance without transferring to the owner:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
View preliminary resultsAppeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.