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

`MarketConfiguration::update()` does not set `priceFeedHeartbeatSeconds`

Summary

The createPerpMarket() and updatePerpMarketConfiguration() functions passes the priceFeedHeartbeatSeconds parameter, but the MarketConfiguration::update() function does not utilize it, leading to an incomplete market configuration update.

Vulnerability Details

createPerpMarket() calls PerpMarket::create() to set the configuration variables of the given perp market id.
Within it, it calls MarketConfiguration::update() as follows:

self.configuration.update(
MarketConfiguration.Data({
name: params.name,
symbol: params.symbol,
priceAdapter: params.priceAdapter,
initialMarginRateX18: params.initialMarginRateX18,
maintenanceMarginRateX18: params.maintenanceMarginRateX18,
maxOpenInterest: params.maxOpenInterest,
maxSkew: params.maxSkew,
maxFundingVelocity: params.maxFundingVelocity,
minTradeSizeX18: params.minTradeSizeX18,
skewScale: params.skewScale,
orderFees: params.orderFees,
>> priceFeedHeartbeatSeconds: params.priceFeedHeartbeatSeconds
})
);

However, the MarketConfiguration::update() function does not utilize the priceFeedHeartbeatSeconds provided above:

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;
>> //@audit-info `priceFeedHeartbeatSeconds` field is not included here
}

Issue:
The priceFeedHeartbeatSeconds parameter is passed but not set in MarketConfiguration::update(). This same issue persists in updatePerpMarketConfiguration()

Impact

The priceFeedHeartbeatSeconds remains unset i.e 0, leading to potential inconsistencies in the market configuration.
Setting the oracle heartbeat to 0 effectively disables the time-based validation of oracle updates.
---> Code will execute with prices that don’t reflect the current pricing. Decisions based on stale data can result in incorrect pricing, margin calculations, and liquidations, causing financial losses to users and the platform.

Tools Used

Manual Review

Recommendations

Modify the MarketConfiguration::update() function to include the priceFeedHeartbeatSeconds parameter:

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.