DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: medium
Valid

The `MarketConfiguration::update` function does not update the `priceFeedHeartbeatSeconds` parameter, making it impossible to obtain the index price of a perpetual market

Summary

The MarketConfiguration::update function does not update the priceFeedHeartbeatSeconds parameter, making it impossible to obtain the index price of a perpetual market.

Vulnerability Details

The MarketConfiguration::update function fails to update the priceFeedHeartbeatSeconds parameter, leaving it set to 0 for all perpetual markets.

When the PerpMarket::getIndexPrice function is called, it invokes the ChainlinkUtil::getPrice function with the priceFeedHeartbeatSeconds parameter set to 0. This will most often cause a revert due to the check block.timestamp - updatedAt > priceFeedHeartbeatSeconds, which ensures that a stale price is not used for the index price. For this check to pass, block.timestamp - updatedAt == 0 must be true, meaning block.timestamp must equal updatedAt.

For this condition to be met, the index price must be retrieved at the exact second it is updated, making it nearly impossible to get the index price of a perpetual market.

Impact

This vulnerability causes the PerpMarket::getIndexPrice function to revert almost every time it is executed, which in turn causes any function that calls it (or calls another function that calls it) to revert as well. This includes:

  • LiquidationBranch::liquidateAccounts

  • OrderBranch::simulateTrade

  • OrderBranch::getMarginRequirementForTrade

  • TradingAccountBranch::getAccountMarginBreakdown

  • TradingAccountBranch::getAccountLeverage

  • TradingAccount::getAccountMarginRequirementUsdAndUnrealizedPnlUsd

  • TradingAccount::getAccountUnrealizedPnlUsd

  • LiquidationBranch::checkLiquidatableAccounts

  • SettlementBranch::fillMarketOrder

  • TradingAccountBranch::withdrawMargin

Tools Used

Manual Review.

Recommendations

To resolve this issue, update the priceFeedHeartbeatSeconds parameter in the MarketConfiguration::update function as follows:

function update(Data storage self, Data memory params) internal {
self.name = params.name;
self.symbol = params.symbol;
self.priceAdapter = params.priceAdapter;
self.initialMarginRateX18 = params.initialMarginRateX18;
self.maintenanceMarginRateX18 = params.maintenanceMarginRateX18;
self.maxOpenInterest = params.maxOpenInterest;
self.maxSkew = params.maxSkew;
self.maxFundingVelocity = params.maxFundingVelocity;
self.minTradeSizeX18 = params.minTradeSizeX18;
self.skewScale = params.skewScale;
self.orderFees = params.orderFees;
+ self.priceFeedHeartbeatSeconds = params.priceFeedHeartbeatSeconds;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

`MarketConfiguration::update` function lacks `priceFeedHeartbeatSeconds` argument

Support

FAQs

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