DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Gas-Inefficient External Calls

Summary

The _validatePrice function in KeeperProxy makes redundant external calls to the same contract interface, resulting in unnecessary gas costs for users.

Vulnerability Details

function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
// ...existing sequencer checks...
// Multiple interface instantiations
address market = IPerpetualVault(perpVault).market(); // First call
IVaultReader reader = IPerpetualVault(perpVault).vaultReader(); // Second call
MarketProps memory marketData = reader.getMarket(market);
// ...price validations...
}

The function creates multiple instances of IPerpetualVault interface to interact with the same contract, incurring unnecessary gas costs from repeated external calls.

Impact

Severity: Low

Effects:

  • Extra ~700 gas per redundant interface call

  • Increased transaction costs for users

  • Cumulative impact scales with protocol usage

  • No security risks, purely gas optimization

Tools Used

  • Manual code review

  • Gas profiler

  • Solidity compiler optimization analysis

Recommendations

Cache the interface instance to reduce gas costs:

function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
// ...existing sequencer checks...
// Cache the interface instance
IPerpetualVault vault = IPerpetualVault(perpVault);
// Use cached instance
address market = vault.market();
IVaultReader reader = vault.vaultReader();
MarketProps memory marketData = reader.getMarket(market);
// ...existing price validations...
}

Gas Savings

Operation Before After Savings
Interface Calls 2 1 ~700 gas
Total per TX ~1,400 ~700 ~700 gas

Test Cases

function testGasOptimization() public {
// Setup
MarketPrices memory prices = setupTestPrices();
// Measure gas before optimization
uint256 gasBefore = gasleft();
keeperProxy.run(vault, true, true, prices, new bytes[](0));
uint256 gasUsedBefore = gasBefore - gasleft();
// Implement optimization
// ... apply fix ...
// Measure gas after optimization
uint256 gasAfter = gasleft();
keeperProxy.run(vault, true, true, prices, new bytes[](0));
uint256 gasUsedAfter = gasAfter - gasleft();
assertLt(gasUsedAfter, gasUsedBefore, "Gas optimization failed");
}
Updates

Lead Judging Commences

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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