Raisebox Faucet

First Flight #50
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Missing ETH Transfer and Accounting in `RaiseBoxFaucet::claimFaucetTokens` Prevents First-Time Claimer Rewards

The RaiseBoxFaucet::claimFaucetTokens function advertises a reward of 0.005 ETH for first-time claimers. However, the contract fails to guarantee this reward due to two critical issues:

1.No explicit ETH transfer declaration or enforcement: The ETH is sent using a low-level call:

(bool success,) = faucetClaimer.call{value: sepEthAmountToDrip}("");

This call is silent on failure and does not revert if the transfer fails. If the contract lacks ETH or the call fails, the user receives nothing — and the function continues as if the reward was delivered.

2.No tracking or accounting of ETH rewards: There is no mapping, event, or state variable to record how much ETH each user has received. This makes it impossible to audit ETH distribution, enforce limits, or detect abuse.

Impact:

Users may receive no ETH despite claiming for the first time.

Silent failures: No error or revert if ETH transfer fails.

No visibility into ETH distribution.

No enforcement of ETH caps or budget.

Undermines trust in the faucet’s reliability and fairness.

*Proof of Concept *

function testEthRewardIsUndeclaredAndUntracked() public {
uint256 balanceBefore = user.balance;
vm.prank(user);
faucet.claimFaucetTokens();
uint256 balanceAfter = user.balance;
uint256 received = balanceAfter - balanceBefore;
// Check that ETH was received
assertEq(received, 0.005 ether, "User should receive 0.005 ETH");
// Check that no tracking exists (this will fail if mapping is missing)
try faucet.ethReceived(user) returns (uint256 amount) {
fail("ETH reward tracking should not exist — mapping is missing");
} catch {
assertTrue(true); // expected behavior
}
}

Recommended Mitigation

1.Declare ETH reward constant:

uint256 public constant FIRST_CLAIM_ETH_REWARD = 0.005 ether;

2.Track ETH distribution per user:

mapping(address => uint256) public ethReceived;

3.Update tracking after successful transfer:

ethReceived[faucetClaimer] += FIRST_CLAIM_ETH_REWARD;

4.Emit event for transparency:

event EthRewardSent(address indexed recipient, uint256 amount);
emit EthRewardSent(faucetClaimer, FIRST_CLAIM_ETH_REWARD);

5.Add transfer failure handling:

require(success, "ETH transfer failed");
Updates

Lead Judging Commences

inallhonesty Lead Judge
12 days ago
inallhonesty Lead Judge 8 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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