Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: high
Valid

Market credit capacity is not correctly calculated

Summary

Market credit capacity is not correctly calculated.

Vulnerability Details

Market's getCreditCapacityUsd() calculates the market's credit capacity by adding the market's credit delegated by vaults to the market's unrealized + realized debt.

function getCreditCapacityUsd(
UD60x18 delegatedCreditUsdX18,
SD59x18 totalDebtUsdX18
)
internal
pure
returns (SD59x18 creditCapacityUsdX18)
{
@> creditCapacityUsdX18 = delegatedCreditUsdX18.intoSD59x18().add(totalDebtUsdX18);
}

This function is called in CreditDelegationBranch's withdrawUsdTokenFromMarket().

CreditDelegationBranch::withdrawUsdTokenFromMarket():

// cache the market's total debt and delegated credit
SD59x18 marketTotalDebtUsdX18 = market.getTotalDebt();
UD60x18 delegatedCreditUsdX18 = market.getTotalDelegatedCreditUsd();
// calculate the market's credit capacity
@> SD59x18 creditCapacityUsdX18 = Market.getCreditCapacityUsd(delegatedCreditUsdX18, marketTotalDebtUsdX18);

As can be seen, the passed arguments are marketTotalDebtUsdX18 and delegatedCreditUsdX18. The marketTotalDebtUsdX18 is actually the market's realized debt (in v1, the unrealized debt is always 0), and the market's realized debt depends on the credit deposits and the net value of usd tokens minted and burned by this market.

function getRealizedDebtUsd(Data storage self) internal view returns (SD59x18 realizedDebtUsdX18) {
// prepare the credit deposits usd value variable;
UD60x18 creditDepositsValueUsdX18;
...
// finally after determining the market's latest credit deposits usd value, sum it with the stored net usd
// token issuance to return the net realized debt usd value
realizedDebtUsdX18 = creditDepositsValueUsdX18.intoSD59x18().add(sd59x18(self.netUsdTokenIssuance));
}

It's easy to tell that is the market has debts, then the debt value is positive, therefore, to calculate market's credit capacity, we should substract the debt from the market's delegated credit, instead of adding them together.

Impact

Market credit capacity is not correctly calculated.

Tools Used

Manual Review

Recommendations

function getCreditCapacityUsd(
UD60x18 delegatedCreditUsdX18,
SD59x18 totalDebtUsdX18
)
internal
pure
returns (SD59x18 creditCapacityUsdX18)
{
- creditCapacityUsdX18 = delegatedCreditUsdX18.intoSD59x18().add(totalDebtUsdX18);
+ creditCapacityUsdX18 = delegatedCreditUsdX18.intoSD59x18().sub(totalDebtUsdX18);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Market::getCreditCapacityUsd overestimates the credit capacity (it adds instead of substracting)

Support

FAQs

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