BriVault

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

LOW-01: require Statement Instead of if-revert Pattern

Root + Impact

The contract uses require() with error strings in some places while using custom errors with if-revert pattern elsewhere, creating inconsistency and wasting gas.

Description

Normal behavior for gas-optimized Solidity contracts expects consistent use of custom errors with the if-revert pattern, which is cheaper than require() with string messages.

The current implementation mixes both patterns, with require() statements appearing in critical functions while custom errors are defined but not used consistently.

// Custom errors defined (good)
error invalidCountry();
error eventNotEnded();
function setWinner(uint256 countryIndex) public onlyOwner returns (string memory) {
if (block.timestamp <= eventEndDate) {
revert eventNotEnded(); // ✓ Good - custom error
}
// @> Inconsistent - uses require with string
require(countryIndex < teams.length, "Invalid country index");
if (_setWinner) {
revert WinnerAlreadySet(); // ✓ Good - custom error
}
// ... rest ...
}
function deposit(uint256 assets, address receiver) public override returns (uint256) {
// @> Another require without custom error
require(receiver != address(0));
// ... rest ...
}

Risk

Likelihood:

  • Every function call with require() incurs extra gas cost

  • Multiple locations in contract use this pattern

  • Compounds across all user transactions

Impact:

  • Each require() with string costs ~50 extra gas vs custom error

  • Inconsistent code style reduces readability

  • Makes codebase harder to maintain

  • Custom errors provide better debugging but aren't used

  • String messages increase contract size

Proof of Concept

// Current implementation
require(countryIndex < teams.length, "Invalid country index");
// Gas cost:
// - String storage: ~50 gas
// - Condition check: ~10 gas
// - Revert with string: ~100 gas
// Total: ~160 gas on failure
// ----
// Optimized with custom error
error InvalidCountryIndex();
if (countryIndex >= teams.length) {
revert InvalidCountryIndex();
}
// Gas cost:
// - Condition check: ~10 gas
// - Revert with error selector: ~50 gas
// Total: ~60 gas on failure
// SAVINGS: ~100 gas per failed call

Recommended Mitigation

+// Add missing custom error
+error InvalidReceiver();
+error InvalidCountryIndex();
function setWinner(uint256 countryIndex) public onlyOwner returns (string memory) {
if (block.timestamp <= eventEndDate) {
revert eventNotEnded();
}
- require(countryIndex < teams.length, "Invalid country index");
+ if (countryIndex >= teams.length) {
+ revert InvalidCountryIndex();
+ }
if (_setWinner) {
revert WinnerAlreadySet();
}
// ... rest ...
}
function deposit(
uint256 assets,
address receiver
) public override returns (uint256) {
- require(receiver != address(0));
+ if (receiver == address(0)) {
+ revert InvalidReceiver();
+ }
if (block.timestamp >= eventStartDate) {
revert eventStarted();
}
// ... rest ...
}

Additional locations to fix:

  • Any other require() statements throughout the contract

  • Ensure all validation uses consistent if-revert pattern

  • Define custom errors for all failure cases

Benefits:

  • Consistent code style throughout contract

  • Reduced gas costs on all validations

  • Better error handling in external integrations

  • Smaller contract bytecode size

  • Follows modern Solidity best practices

Estimated Gas Savings: ~50-100 gas per validation that fails, adds up across all users

Updates

Appeal created

bube Lead Judge 21 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Gas optimizations

Gas optimizations are invalid according to the CodeHawks documentation.

Support

FAQs

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

Give us feedback!