Raisebox Faucet

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

Gas Inefficiency in Faucet Contract

[L-03] Gas Inefficiency in Faucet Contract

Impact – High gas consumption for routine operations increases user costs and reduces network efficiency, particularly during frequent claims or owner operations, potentially discouraging faucet usage.


Description

  • Normal behavior:
    The faucet contract allows users to claim tokens and optionally Sepolia ETH, and the owner to mint, burn, or adjust limits. These operations should execute efficiently while maintaining security.

  • Issue:
    The original contract used redundant storage writes, non-immutable constants, and unnecessary public variables. Public variables generate automatic getter functions, which consume extra gas when accessed in other contracts. This caused extra gas consumption during claims, owner operations, and any external read access.

// Inefficient sections in the codebase
uint256 public faucetDrip; // @> changed to immutable in fixed contract
uint256 public dailySepEthCap; // @> changed to immutable
uint256 public blockTime = block.timestamp; // @> never used
address public faucetClaimer; // @> only needed locally
...
lastClaimTime[faucetClaimer] = block.timestamp; // @> storage write optimized with local variable
unchecked { dailyClaimCount++; } // @> reduces gas by avoiding SafeMath
  • Getter functions:
    Previously, making many state variables public created automatic getters in bytecode, which increases contract size and gas if called externally. Changing them to private and providing explicit view functions reduces unnecessary bytecode and allows more controlled, efficient access.


Risk

Likelihood:

  • High — Every call to claimFaucetTokens() triggers multiple unnecessary storage reads/writes and redundant getter code execution.

  • Frequent — Owner operations like minting, burning, and adjusting daily limits also write to storage inefficiently.

Impact:

  • Increased gas cost for every transaction.

  • Users may pay higher fees for token claims.

  • Potential cumulative network inefficiency for high-volume usage.

  • Contract size reduced, lowering deployment gas.


Proof of Concept

// Original call
raiseBoxFaucet.claimFaucetTokens();
// consumed ~120k gas per claim
// After optimizations:
raiseBoxFaucet.claimFaucetTokens();
// consumed ~90k gas per claim (example; ~25% reduction)
// Getter example:
// Old: balanceOf + public faucetDrip + public dailySepEthCap
// New: balanceOf + explicit getFaucetDrip(), getDailySepEthCap() calls
// reduces bytecode and gas if called externally

Recommended Mitigation

We replaced frequently accessed public variables with private immutable or private variables to reduce gas costs from automatic getters and unnecessary storage writes. Unused variables were removed, and critical state updates were optimized using local variables and unchecked arithmetic. Explicit getter functions were added for controlled access, reducing bytecode size and improving overall gas efficiency without changing functionality.

- uint256 public faucetDrip;
- uint256 public dailySepEthCap;
- uint256 public blockTime = block.timestamp;
- address public faucetClaimer;
+ uint256 private immutable i_faucetDrip;
+ uint256 private immutable i_dailySepEthCap;
+ address private faucetClaimer; // used locally
+ // remove unused storage entirely
+ unchecked { dailyClaimCount++; } // safe increment
+ // Explicit getter functions for previously-public variables
+ function getFaucetDrip() public view returns (uint256) { return i_faucetDrip; }
+ function getDailySepEthCap() public view returns (uint256) { return i_dailySepEthCap; }
+ function getClaimCooldown() public pure returns (uint256) { return CLAIM_COOLDOWN; }

Additional optimizations applied:

  • Local variables for claimer and contract token balance to avoid multiple storage reads.

  • Immutable variables for constants (i_faucetDrip, i_sepEthAmountToDrip, i_dailySepEthCap) to reduce SLOAD gas costs.

  • nonReentrant modifier added for security while keeping gas-efficient state updates.

  • Explicit getters replace automatic public getters, reducing bytecode size and gas.

Updates

Lead Judging Commences

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