Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: low
Valid

Incorrect Faucet Balance Comparison Prevents Last Valid Claim

Root + Impact

Description

The claimFaucetTokens() function currently checks:

// @> use <= inseat of <
if (balanceOf(address(this)) <= faucetDrip) {
revert RaiseBoxFaucet_InsufficientContractBalance();
}

This condition prevents users from claiming tokens when the faucet balance equals exactly one faucetDrip amount — even though there are just enough tokens remaining for one more valid claim.

As a result, the faucet may appear “out of tokens” prematurely, leaving leftover tokens (equal to faucetDrip) permanently unclaimable.

Risk

Likelihood: High

  • The condition will always trigger when the faucet reaches exactly one drip remaining.

Impact: Low

  • No funds are lost or stolen, but faucet usability is degraded.

  • Users are unable to claim the last valid drip, leaving stranded tokens.

Proof of Concept

The test deploys a fresh instance of the RaiseBoxFaucet contract with the total faucet token balance (INITIAL_SUPPLY) equal to exactly one faucetDrip amount.
This simulates the final stage of the faucet’s lifecycle — where only one valid claim’s worth of tokens remains.

function test_RevertOnLastDrip() public {
// Initialize the contract such as
// total faucet token balance (`INITIAL_SUPPLY`) equal to exactly one `faucetDrip` amount.
RaiseBoxFaucet faucet = new RaiseBoxFaucet(
"raiseboxtoken",
"RB",
1000000000 * 10 ** 18,
0.005 ether,
0.5 ether
);
// Confirm the faucet has exactly one drip left
assertEq(faucet.getFaucetTotalSupply(), faucet.faucetDrip());
// Try to claim when faucet has exactly one drip left
vm.startPrank(user1);
vm.expectRevert(RaiseBoxFaucet.RaiseBoxFaucet_InsufficientContractBalance.selector);
faucet.claimFaucetTokens();
vm.stopPrank();
}

Recommended Mitigation

This PoC clearly demonstrates that:

  • The faucet incorrectly becomes unusable when one drip remains.

  • A simple change from <= to < in the balance check would fix the issue and allow the last claim to proceed normally.

- if (balanceOf(address(this)) <= faucetDrip) {
+ if (balanceOf(address(this)) < faucetDrip) {
revert RaiseBoxFaucet_InsufficientContractBalance();
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 9 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Off-by-one error in `claimFaucetTokens` prevents claiming when the balance is exactly equal to faucetDrip

Support

FAQs

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