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

Precision loss due to div before multiplication in `PerpMarket::getMarkPrice`

Summary

There is a division before multiplication PerpMarket::getMarkPrice which will cause the protocol to use an incorrect price, due to a precision loss.

Vulnerability Details

When calling PerpMarket::getMarkPrice, priceImpactBeforeDelta and priceImpactAfterDelta calculation is done with division operation like below.

SD59x18 priceImpactBeforeDelta = skew.div(skewScale);
SD59x18 newSkew = skew\.add(skewDelta);
SD59x18 priceImpactAfterDelta = newSkew\.div(skewScale);

Then the same values are taken and multiplied in the calculation of priceBeforeDelta and priceAfterDelta to get the final mark price.

UD60x18 priceBeforeDelta =
cachedIndexPriceX18.add(cachedIndexPriceX18.mul(priceImpactBeforeDelta)).intoUD60x18();
UD60x18 priceAfterDelta =
cachedIndexPriceX18.add(cachedIndexPriceX18.mul(priceImpactAfterDelta)).intoUD60x18();
markPrice = priceBeforeDelta.add(priceAfterDelta).div(ud60x18Convert(2));

Impact

This precision loss has an impact on all functions using the mark price.

Tools Used

Manual review

Recommendations

function getMarkPrice(
Data storage self,
SD59x18 skewDelta,
UD60x18 indexPriceX18
)
internal
view
returns (UD60x18 markPrice)
{
SD59x18 skewScale = sd59x18(self.configuration.skewScale.toInt256());
SD59x18 skew = sd59x18(self.skew);
SD59x18 priceImpactBeforeDelta = skew.div(skewScale);
SD59x18 newSkew = skew.add(skewDelta);
SD59x18 priceImpactAfterDelta = newSkew.div(skewScale);
SD59x18 cachedIndexPriceX18 = indexPriceX18.intoSD59x18();
- UD60x18 priceBeforeDelta = cachedIndexPriceX18.add(cachedIndexPriceX18.mul(priceImpactBeforeDelta)).intoUD60x18();
- UD60x18 priceAfterDelta = cachedIndexPriceX18.add(cachedIndexPriceX18.mul(priceImpactAfterDelta)).intoUD60x18();
+ UD60x18 priceBeforeDelta = cachedIndexPriceX18.add(cachedIndexPriceX18.mul(skew).div(skewscale)).intoUD60x18();
+ UD60x18 priceAfterDelta = cachedIndexPriceX18.add(cachedIndexPriceX18.mul(newSkew).div(skewscale)).intoUD60x18();
markPrice = priceBeforeDelta.add(priceAfterDelta).div(ud60x18Convert(2));
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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