Raisebox Faucet

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

Redundant `fallback` and `receive` Functions

Root + Impact

Both receive() and fallback() functions perform identical operations (emitting the same event), which is redundant and wastes deployment gas. One function can handle all ETH reception scenarios.

Description

  • Either receive() or fallback() alone can handle incoming ETH, making the other redundant.

  • Both functions on lines 258-260 and 263-265 do exactly the same thing: emit SepEthDonated event with msg.sender and msg.value.

/// @notice Accept ETH donations via `receive`
@>receive() external payable {
emit SepEthDonated(msg.sender, msg.value);
}
/// @notice Accept ETH donations via `fallback`
@>fallback() external payable {
emit SepEthDonated(msg.sender, msg.value);
}

Risk

Likelihood:

  • Both functions exist in every deployment

  • Code duplication is present in 100% of deployments

Impact:

  • Wastes deployment gas by duplicating identical functionality

  • Increases bytecode size unnecessarily, making the contract more expensive to deploy

Proof of Concept

Both functions perform the same action when the contract receives ETH:

const { expect } = require("chai");
describe("Redundant receive and fallback", function () {
it("Should show both functions do the same thing", async function () {
const [owner] = await ethers.getSigners();
const Faucet = await ethers.getContractFactory("RaiseBoxFaucet");
const faucet = await Faucet.deploy("Token", "TKN", ethers.parseEther("1000"), ethers.parseEther("0.005"), ethers.parseEther("1"));
// Sending ETH with empty data triggers receive()
const tx1 = await owner.sendTransaction({
to: await faucet.getAddress(),
value: ethers.parseEther("0.1")
});
// Sending ETH with data triggers fallback()
const tx2 = await owner.sendTransaction({
to: await faucet.getAddress(),
value: ethers.parseEther("0.1"),
data: "0x1234"
});
console.log("⚠️ Both functions emit the same event");
console.log("One function could handle both cases");
});
});

Recommended Mitigation

Remove the receive function and keep only fallback for ETH donations. As fallback method can handle all the scenrios:

  • ✅ Ether transfers with or without data → handled by fallback()

  • ✅ Unknown function calls → handled by fallback()

  • ✅ Calls to non-existing function → handled by fallback()

  • ✅ Plain ETH transfers → handled by fallback()

- receive() external payable {
- emit SepEthDonated(msg.sender, msg.value);
- }
fallback() external payable {
emit SepEthDonated(msg.sender, msg.value);
}

OR remove the fallback function and keep only receive for ETH donations. As receive method can handle almost possible scenrios:

  • ✅ Ether transfers without data → handled by receive()

  • ✅ Plain ETH transfers → handled by receive()

Updates

Lead Judging Commences

inallhonesty Lead Judge 8 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.