The claimFaucetTokens function performs a pre-transfer balance check to ensure the contract has enough tokens before proceeding with the claim. The check if (balanceOf(address(this)) <= faucetDrip) reverts with RaiseBoxFaucet_InsufficientContractBalance if the contract's balance is less than or equal to the amount to be dripped per claim (faucetDrip). While this prevents failed transfers when the balance is insufficient, the inclusion of equality (=) blocks the exact case where the balance matches faucetDrip precisely.
In ERC20 transfers, an exact match would succeed (leaving the balance at zero post-transfer), but this check prematurely reverts, leaving tokens stranded in the contract. This edge case becomes relevant after multiple claims deplete the balance to exactly faucetDrip, halting further usage without warning. The issue could be mitigated by using < to allow the exact equality case, relying on the internal ERC20 transfer logic to handle the final depletion safely.
Likelihood:
Medium: The exact equality case occurs naturally after a series of claims that deplete the balance precisely to faucetDrip, especially in low-activity faucets or after manual minting to specific amounts.
Automated or repeated claims (e.g., via scripts) increase the chance of hitting this edge case without developer awareness.
Impact:
Medium: Tokens become stuck in the contract, requiring owner intervention (e.g., minting more) to resume operations, leading to operational delays and potential token waste.
Poor user experience: Users receive misleading "insufficient balance" errors despite available tokens, eroding trust in the faucet system.
The following Foundry test demonstrates the issue: The contract balance is set to exactly faucetDrip, causing the claim to revert despite sufficient tokens. This confirms the check blocks the final claim, leaving the balance unchanged.
Add the following to the RaiseBoxFaucetTest.t.sol test:
Setup: The test uses the owner to burn all existing tokens (resetting balance to 0) and then mint exactly faucetDrip amount, ensuring the contract balance equals the drip amount.
Issue Demonstration: A user attempts to claim, triggering the <= check, which evaluates to true and reverts with RaiseBoxFaucet_InsufficientContractBalance.
Result: The balance remains unchanged (still exactly faucetDrip), confirming tokens are stuck and the claim fails despite available funds.
The test passes, proving the check prevents the final claim and highlights the unintended blocking of exact equality.
Change the comparison to < to allow claims when the balance exactly equals faucetDrip, relying on the ERC20 _transfer to handle the depletion safely. This ensures the last claim succeeds without stranding tokens.
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.