Raisebox Faucet

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

Coupling token claim to ETH drip transfer causes DoS leads tokens become unclaimable when ETH transfer fails

Coupling token claim to ETH drip transfer causes DoS leads tokens become unclaimable when ETH transfer fails

Description

  • Claimers should always be able to receive faucet tokens (when all checks have been passed). A failed ETH drip should not block token claims.

  • The function reverts the entire call when the ETH transfer fails, so any claimer with a reverting receive/fallback (or temporary transfer issues) cannot claim tokens at all.

if (dailyDrips + sepEthAmountToDrip <= dailySepEthCap && address(this).balance >= sepEthAmountToDrip) {
hasClaimedEth[faucetClaimer] = true;
dailyDrips += sepEthAmountToDrip;
(bool success,) = faucetClaimer.call{value: sepEthAmountToDrip}("");
if (success) {
emit SepEthDripped(faucetClaimer, sepEthAmountToDrip);
} else {
@> revert RaiseBoxFaucet_EthTransferFailed();
}
}

Risk

Likelihood:

  • Whenever the claimer is a contract whose receive/fallback reverts, the ETH transfer fails and every claim attempt reverts.

  • Operational hiccups (out-of-gas in receiver, temporary issues) also trigger the revert and block token claims.

Impact:

  • Denial of service: Users cannot claim tokens due solely to an ancillary ETH drip failure.

Proof of Concept

A claimer contract with a reverting receive() calls claimFaucetTokens(). The ETH drip attempt fails, causing a revert and preventing token distribution, proving that token claims are coupled to ETH transfer success.

Recommended Mitigation

Use a best-effort or pull pattern so token claims are never blocked by ETH transfer issues.

- hasClaimedEth[faucetClaimer] = true;
- dailyDrips += sepEthAmountToDrip;
- (bool success,) = faucetClaimer.call{ value: sepEthAmountToDrip }("");
- if (!success) {
- revert RaiseBoxFaucet_EthTransferFailed();
- }
+ (bool success,) = payable(claimer).call{ value: sepEthAmountToDrip }("");
+ if (success) {
+ hasClaimedEth[claimer] = true;
+ dailyDrips += sepEthAmountToDrip;
+ emit SepEthDripped(claimer, sepEthAmountToDrip);
+ } else {
+ // Best-effort: don’t block token claim; allow future retry/pull
+ emit SepEthDripSkipped(claimer, "Transfer failed");
+ // (Option) track credit for pull-withdrawal:
+ // ethCredit[claimer] += sepEthAmountToDrip;
+ }
Updates

Lead Judging Commences

inallhonesty Lead Judge 14 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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