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

Potential division by zero in `getMarkPrice` function

Summary

The getMarkPrice function in PerpMarket.sol is susceptible to a division by zero error due to the absence of a check for zero in the skewScale variable.

Vulnerability Details

The getMarkPrice function calculates the mark price based on the skew and the skew scale. However, if the skewScale is zero, it will cause a division by zero error, leading to revert.

PerpMarket.sol#L98

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();
markPrice = priceBeforeDelta.add(priceAfterDelta).div(ud60x18Convert(2));
}

Here, skewScale is converted into a signed decimal type (SD59x18). If skewScale is zero or can be zero, this could be a potential issue in the subsequent division operation.

SD59x18 priceImpactBeforeDelta = skew.div(skewScale);

This check is correctly implemented in the getCurrentFundingVelocity function but is missing in getMarkPriceFunction.

function getCurrentFundingVelocity(Data storage self) internal view returns (SD59x18) {
SD59x18 maxFundingVelocity = sd59x18(uint256(self.configuration.maxFundingVelocity).toInt256());
SD59x18 skewScale = sd59x18(uint256(self.configuration.skewScale).toInt256());
SD59x18 skew = sd59x18(self.skew);
@> if (skewScale.isZero()) {
return SD59x18_ZERO;
}
SD59x18 proportionalSkew = skew.div(skewScale);
SD59x18 proportionalSkewBounded = Math.min(Math.max(unary(SD_UNIT), proportionalSkew), SD_UNIT);
return proportionalSkewBounded.mul(maxFundingVelocity);
}

Impact

getMarkPrice function will revert

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);
+ if (skewScale.isZero()) {
+ return SD59x18_ZERO;
+ }
SD59x18 priceImpactBeforeDelta = skew.div(skewScale);
SD59x18 newSkew = skew.add(skewDelta);
SD59x18 priceImpactAfterDelta = newSkew.div(skewScale);
....snip....
}
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.