Raisebox Faucet

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

# Code Standard and Optimization Issues in `RaiseBoxFaucet`

Description

Contract Reference: RaiseBoxFaucet.sol

The RaiseBoxFaucet contract contains several code standard and gas optimization issues that do not impact security or functionality but affect code clarity and deployment/runtime gas costs. These issues, identified by Slither, are related to suboptimal use of function visibility and state variable attributes:

  1. Public Functions Not Used Internally:

    • Eleven public functions are not called internally within the contract and could be marked external to optimize gas usage and clarify their intended use:

      • mintFaucetTokens(address, uint256) (line 110)

      • burnFaucetTokens(uint256) (line 128)

      • adjustDailyClaimLimit(uint256, bool) (line 143)

      • claimFaucetTokens() (line 162)

      • getBalance(address) (line 276)

      • getClaimer() (line 280)

      • getHasClaimedEth(address) (line 286)

      • getUserLastClaimTime(address) (line 292)

      • getFaucetTotalSupply() (line 297)

      • getContractSepEthBalance() (line 302)

      • getOwner() (line 307)

    • Code Example (for mintFaucetTokens):

      function mintFaucetTokens(address to, uint256 amount) public onlyOwner {
  2. State Variable Could Be Constant:

    • The state variable blockTime (line 42) is assigned block.timestamp at deployment but never updated, making it a candidate for the constant keyword to reduce gas costs.

    • Code:

      uint256 public blockTime = block.timestamp;
  3. State Variables Could Be Immutable:

    • Three state variables are set only in the constructor and never modified afterward, making them suitable for the immutable keyword to save gas:

      • faucetDrip (line 22)

      • sepEthAmountToDrip (line 34)

      • dailySepEthCap (line 40)

    • Code Example (for faucetDrip):

      uint256 public faucetDrip;

Slither References:

Severity

Informational
{ Impact — Negligible, Likelihood — N/A }

  • Impact: Negligible, as these issues do not affect contract functionality or security. They slightly increase deployment and runtime gas costs and may reduce code clarity.

  • Likelihood: N/A, as these are static code quality and optimization issues, not exploitable vulnerabilities.

Risk

  • Likelihood of Issue: N/A. These are static code issues present at deployment, not runtime vulnerabilities.

  • Potential Consequences:

    • Gas Costs: Public functions not marked external incur minor gas overhead (e.g., ~10–20 gas per external call). Non-constant/non-immutable state variables increase deployment gas costs (~20,000 gas per storage slot) and runtime read costs (negligible).

    • Code Clarity: Public visibility on functions not used internally may mislead developers about their purpose. Non-constant/non-immutable variables suggest mutability, reducing code readability.

    • Operational Impact: No runtime impact in a testnet faucet, but suboptimal code may hinder maintenance or audits.

  • Contextual Factors: In a Sepolia testnet faucet, where gas costs and asset value are minimal, these issues are minor and primarily affect code maintainability and developer experience.

Impact

  • Gas Costs: Public functions not marked external add slight gas overhead for external calls. Non-constant (blockTime) and non-immutable (faucetDrip, sepEthAmountToDrip, dailySepEthCap) variables increase deployment gas costs (e.g., ~20,000 gas per variable) and minor runtime read costs.

  • Code Clarity: Unnecessary public visibility and mutable state variables may confuse developers or auditors, suggesting incorrect usage patterns.

  • Testnet Context: In a Sepolia faucet, these issues do not affect user experience or security, as assets have no real value, but they reflect suboptimal code practices.

  • Limited Scope: No security or functional impact; purely code standard and optimization concerns.

Tools Used

  • Manual Review.

Recommended Mitigation

  1. Mark Public Functions as External:

    • Change the visibility of the eleven listed functions from public to external to optimize gas usage and clarify they are not used internally.

    • Example Fix (for mintFaucetTokens):

      // Change from
      function mintFaucetTokens(address to, uint256 amount) public onlyOwner {
      // To
      function mintFaucetTokens(address to, uint256 amount) external onlyOwner {
    • Apply to all listed functions: burnFaucetTokens, adjustDailyClaimLimit, claimFaucetTokens, getBalance, getClaimer, getHasClaimedEth, getUserLastClaimTime, getFaucetTotalSupply, getContractSepEthBalance, getOwner.

  2. Make blockTime Constant or Remove:

    • If blockTime is used only for initialization, declare it constant:

      // Change from
      uint256 public blockTime = block.timestamp;
      // To
      uint256 public constant blockTime = 0; // Set to deployment timestamp
    • If blockTime is unused, remove it entirely to save storage:

      // Remove
      uint256 public blockTime = block.timestamp;
  3. Make State Variables Immutable:

    • Declare faucetDrip, sepEthAmountToDrip, and dailySepEthCap as immutable since they are set only in the constructor:

      // Change from
      uint256 public faucetDrip;
      uint256 public sepEthAmountToDrip;
      uint256 public dailySepEthCap;
      // To
      uint256 public immutable faucetDrip;
      uint256 public immutable sepEthAmountToDrip;
      uint256 public immutable dailySepEthCap;
    • Ensure these variables are initialized in the constructor:

      constructor() ERC20("RaiseBox", "RBX") Ownable(msg.sender) {
      faucetDrip = 100 * 10**18; // Example value
      sepEthAmountToDrip = 0.01 ether; // Example value
      dailySepEthCap = 1 ether; // Example value
      _mint(address(this), 1000000 * 10**18);
      }
  4. Considerations:

    • Verify that the listed functions are not called internally by other contract functions or inherited contracts.

    • Confirm blockTime is unused or only used for initialization; if used dynamically, consider a view function (function getBlockTime() public view returns (uint256) { return block.timestamp; }).

    • Ensure faucetDrip, sepEthAmountToDrip, and dailySepEthCap are only set in the constructor by reviewing the full contract code.

    • Compile and test the contract after applying changes to confirm no unintended side effects.

Proof of Concept

  1. Public Functions Not Used Internally:

    • Observation: The functions mintFaucetTokens, burnFaucetTokens, adjustDailyClaimLimit, claimFaucetTokens, getBalance, getClaimer, getHasClaimedEth, getUserLastClaimTime, getFaucetTotalSupply, getContractSepEthBalance, and getOwner are marked public but not called internally, as confirmed by code inspection.

    • Impact: Public visibility adds minor gas overhead (~10–20 gas per external call) compared to external.

    • Fix: Changing to external reduces gas costs and clarifies intent.

  2. Non-Constant State Variable:

    • Observation: blockTime (line 42) is set to block.timestamp at deployment and never updated, as verified by code review.

    • Impact: Uses a storage slot (~20,000 gas for deployment) instead of a constant, which would be embedded in bytecode.

    • Fix: Declaring constant or removing (if unused) saves gas.

  3. Non-Immutable State Variables:

    • Observation: faucetDrip, sepEthAmountToDrip, and dailySepEthCap (lines 22, 34, 40) are set in the constructor and never modified, as confirmed by inspection.

    • Impact: Each variable uses a storage slot (~20,000 gas per variable for deployment) instead of being embedded in bytecode as immutable.

    • Fix: Declaring immutable reduces gas costs.

These issues can be verified by compiling the contract with and without the fixes, observing gas savings (e.g., using forge build to compare deployment costs).

Updates

Lead Judging Commences

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