Raisebox Faucet

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

The `RaiseBoxFaucet::claimFaucetTokens` function prioritizes `sepolia ETH` drip over `faucetDrip` claim for new users, rejection of `sepolia ETH` by contract-based accounts causes denial of service (DoS) blocking users from claiming `RB` tokens

Root + Impact

Description

The RaiseBoxFaucet::claimFaucetTokens function prioritizes sepolia ETH drip over faucetDrip claim for new users, sending ETH to users before the faucetDrip tokens. The contract-based accounts that do not expect to receive sepolia ETH cause denial of service (DoS) reverting the transaction, blocking users from claiming RB tokens.

function claimFaucetTokens() public {
...
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();
}
} else {
emit SepEthDripSkipped(
faucetClaimer,
address(this).balance < sepEthAmountToDrip ? "Faucet out of ETH" : "Daily ETH cap reached"
);
}
...
}

Risk

Likelihood:

  • Since the main purpose of this contract is to distribute faucet RB tokens, it is quite probable that contracts would expect an ERC20 transfer instead of an ETH deposit.

  • Any contract-based account that claims the faucet for the first time is potentially affected by this issue.

Impact:

  • Denial of service (DoS) blocking users from claiming RB tokens.

  • Severely breaking the functionality of the protocol, as the distribution of faucet tokens is the main purpose of this protocol.

Proof of Concept

Add the following code snippet to the RaiseBoxFaucet.t.sol test file.

EthRejector contract:

contract EthRejector {
receive() external payable {
revert("Rejecting ETH");
}
fallback() external payable {
revert("Rejecting ETH");
}
}

This code snippet is designed to demonstrate the RaiseBoxFaucet::claimFaucetTokens function fails on ETH transfer causing denial of service (DoS)

function testSepEthTransferFailedCausesDoS() public {
// Create a contract that rejects ETH transfers
EthRejector rejector = new EthRejector();
// Try to claim with the rejector address - should fail on ETH transfer
vm.prank(address(rejector));
vm.expectRevert(RaiseBoxFaucet.RaiseBoxFaucet_EthTransferFailed.selector);
raiseBoxFaucet.claimFaucetTokens();
console.log("user balance of eth: ", address(rejector).balance);
console.log("user balance of faucet tokens: ", raiseBoxFaucet.balanceOf(address(rejector)));
}

Recommended Mitigation

Possible mitigation is to replace revert statement with emit of SepEthDripSkipped event, in order to allow users to claim RB tokens.

function claimFaucetTokens() public {
...
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();
+ emit SepEthDripSkipped(faucetClaimer, "Receiver has rejected ETH");
}
} else {
emit SepEthDripSkipped(
faucetClaimer,
address(this).balance < sepEthAmountToDrip ? "Faucet out of ETH" : "Daily ETH cap reached"
);
}
...
}
Updates

Lead Judging Commences

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

Appeal created

alexscherbatyuk Submitter
11 days ago
inallhonesty Lead Judge
11 days ago
alexscherbatyuk Submitter
10 days ago
inallhonesty Lead Judge
10 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.