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

Incorrect Token Price Validation in KeeperProxy

Summary

The KeeperProxy contract contains a critical issue in its price validation logic, where the longToken price is validated against the indexToken price, not the corresponding longToken price. This mismatch in price validation can lead to invalid trades.

Vulnerability Details

The issue exists in the _validatePrice function where price validation for longToken incorrectly uses indexTokenPrice instead of longTokenPrice:

function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
// ...
MarketProps memory marketData = reader.getMarket(market);
_check(marketData.indexToken, prices.indexTokenPrice.min);
_check(marketData.indexToken, prices.indexTokenPrice.max);
_check(marketData.longToken, prices.indexTokenPrice.min); // Issue
_check(marketData.longToken, prices.indexTokenPrice.max); // Issue
_check(marketData.shortToken, prices.shortTokenPrice.min);
_check(marketData.shortToken, prices.shortTokenPrice.max);
}

The problem stems from using indexTokenPrice to validate longToken, This can lead to inaccurate price validation. Using prices.indexTokenPrice instead of prices.longTokenPrice to validate long token prices, thus breaking the integrity of the price validation mechanism.

Impact

  • Positions may be opened/closed at incorrect prices

  • Unfair liquidations due to incorrect price validation

Tools Used

  • Manual review

Recommendations

Correct price validation.

function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
// L2 Sequencer check...
address market = IPerpetualVault(perpVault).market();
IVaultReader reader = IPerpetualVault(perpVault).vaultReader();
MarketProps memory marketData = reader.getMarket(market);
// Correct price validation
_check(marketData.indexToken, prices.indexTokenPrice.min);
_check(marketData.indexToken, prices.indexTokenPrice.max);
_check(marketData.longToken, prices.longTokenPrice.min); // FIXED
_check(marketData.longToken, prices.longTokenPrice.max); // FIXED
_check(marketData.shortToken, prices.shortTokenPrice.min);
_check(marketData.shortToken, prices.shortTokenPrice.max);
// Additional safety check
require(
prices.longTokenPrice.min <= prices.longTokenPrice.max,
"Invalid long token price range"
);
}
Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_validatePrice_no_check_for_longTokenPrice

Likelihood: None/Very Low, everytime the keeper send a price via run/runNextAction (sent by the Gamma keeper). Impact: Medium/High, does not check the longTokenPrice, it could go out of range. Keep in mind indexToken == longToken, an error from the keeper could be considered informational.

Support

FAQs

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