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

`priceFeedHeartbeatSeconds` is not added to the `PerpMarket` data

Github
https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/leaves/MarketConfiguration.sol#L32-L49
https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/branches/GlobalConfigurationBranch.sol#L379-L441

Summary

The createPerpMarket function in the GlobalConfigurationBranch contract is responsible for creating and configuring a new perpetual futures market. It is a critical function that allows the owner of the contract to define the parameters of a new market, which includes various financial and operational settings. The creation flow is such. GlobalConfigurationBranch:createPerpMarket calls PerpMarket.create function which then calls MarketConfiguration.update with all the data sent as params.

Vulnerability Details

Now the issue is MarketConfiguration.update is adding all other values to the self but missing one field and value which is priceFeedHeartbeatSeconds. This field is never added anywhere in the whole creation flow. The priceFeedHeartbeatSeconds is very crucial for getting updated and correct prices.

POC

Add the following event to the MarketConfiguration contracts:

event LogConfigurePriceFeedHeartbeatSeconds(uint32 priceFeedHeartbeatSeconds);

Then log this event in the MarketConfiguration:update function i.e:

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;
emit LogConfigurePriceFeedHeartbeatSeconds(self.priceFeedHeartbeatSeconds);
}

Now run the following command to test it:

forge test --match-test test_WhenPriceFeedHearbeatSecondsIsNotZero -vvvv

It will emit a zero value for priceFeedHeartbeatSeconds variable and no matter what value is set in test_WhenPriceFeedHearbeatSecondsIsNotZero function, it will still be 0 . Which proves that the actual value is never added to the self variable during any step of the whole creation flow.

Impact

The priceFeedHeartbeatSeconds parameter defines how often the price feed updates occur. With this parameter being 0, it will always cause DOS wherever this price is required in the code. Accurate pricing is critical for the proper valuation of assets and for calculating margins, liquidations, and other financial metrics. If the price feed isn't updated responsive enough, it could lead to permanent DOS and potentially cause issues in margin calculations and trade executions.

Recommendations

To resolve this issue, add the following line to the MarketConfiguration:update function:

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.