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

Incorrect Price Validation in KeeperProxy::_validatePrice Function

Summary

The _validatePrice function is responsible for validating market prices before allowing operations in the perpetual vault. However, the function incorrectly uses prices.indexTokenPrice for validating marketData.longToken, instead of using the correct prices.longTokenPrice.

This issue results in incorrect price validation and could lead to unsafe or invalid operations due to mismatched token prices.

Vulnerability Details

function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
// L2 Sequencer check
(
/*uint80 roundID*/,
int256 answer,
uint256 startedAt,
/*uint256 updatedAt*/,
/*uint80 answeredInRound*/
) = AggregatorV2V3Interface(sequencerUptimeFeed).latestRoundData();
bool isSequencerUp = answer == 0;
require(isSequencerUp, "sequencer is down");
// Make sure the grace period has passed after the sequencer is back up.
uint256 timeSinceUp = block.timestamp - startedAt;
require(timeSinceUp > GRACE_PERIOD_TIME, "Grace period is not over");
address market = IPerpetualVault(perpVault).market();
IVaultReader reader = IPerpetualVault(perpVault).vaultReader();
MarketProps memory marketData = reader.getMarket(market);
_check(marketData.indexToken, prices.indexTokenPrice.min);
_check(marketData.indexToken, prices.indexTokenPrice.max);
@> _check(marketData.longToken, prices.indexTokenPrice.min);
@> _check(marketData.longToken, prices.indexTokenPrice.max);
_check(marketData.shortToken, prices.shortTokenPrice.min);
_check(marketData.shortToken, prices.shortTokenPrice.max);
}

The function mistakenly applies prices.indexTokenPrice when validating marketData.longToken instead of using prices.longTokenPrice. The long token should be validated using prices.longTokenPrice.min and prices.longTokenPrice.max, but the function mistakenly references prices.indexTokenPrice.min and prices.indexTokenPrice.max.

Impact

If the index token price significantly differs from the actual long token price, the contract may allow invalid trades or reject valid ones.

This can result in incorrect liquidations or potential loss of funds.

Tools Used

Manual Review

Recommendations

Fix the incorrect price reference in _validatePrice by replacing:

function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
// L2 Sequencer check
(
/*uint80 roundID*/,
int256 answer,
uint256 startedAt,
/*uint256 updatedAt*/,
/*uint80 answeredInRound*/
) = AggregatorV2V3Interface(sequencerUptimeFeed).latestRoundData();
bool isSequencerUp = answer == 0;
require(isSequencerUp, "sequencer is down");
// Make sure the grace period has passed after the sequencer is back up.
uint256 timeSinceUp = block.timestamp - startedAt;
require(timeSinceUp > GRACE_PERIOD_TIME, "Grace period is not over");
address market = IPerpetualVault(perpVault).market();
IVaultReader reader = IPerpetualVault(perpVault).vaultReader();
MarketProps memory marketData = reader.getMarket(market);
_check(marketData.indexToken, prices.indexTokenPrice.min);
_check(marketData.indexToken, prices.indexTokenPrice.max);
- _check(marketData.longToken, prices.indexTokenPrice.min);
- _check(marketData.longToken, prices.indexTokenPrice.max);
+ _check(marketData.longToken, prices.longTokenPrice.min);
+ _check(marketData.longToken, prices.longTokenPrice.max);
_check(marketData.shortToken, prices.shortTokenPrice.min);
_check(marketData.shortToken, prices.shortTokenPrice.max);
}
Updates

Lead Judging Commences

n0kto Lead Judge 9 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.

Give us feedback!