Part 2

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

Multiple instances where Vault's `totalAssets()` is not properly scaled to ZAROS precision

Note: there are several instances where vault's totalAssets() is interrogated and not properly scaled to ZAROS precision (18 decimal points, usually UD60x18 or UD59x18 representation).
Each of these instances have (most likely) high impact for the protocol and/or protocol's users.
This report describe only one such instance and links to the rest of them are added at the end.

Summary
Vault::getTotalCreditCapacityUsd returns a wrong USD amount for collateral assets with decimals < 18.
Vaults will report a highly diminished credit capacity.

Vulnerability Details

getTotalCreditCapacityUsd calculates the vault's credit capacity by multiplying vault's totalAssets by asset price.

/// @notice Returns the vault's total credit capacity allocated to the connected markets.
/// @dev The vault's total credit capacity is adjusted by its the credit ratio of its underlying collateral asset.
/// @param self The vault storage pointer.
/// @return creditCapacityUsdX18 The vault's total credit capacity in USD.
function getTotalCreditCapacityUsd(Data storage self) internal view returns (SD59x18 creditCapacityUsdX18) {
// load the collateral configuration storage pointer
Collateral.Data storage collateral = self.collateral;
// fetch the zlp vault's total assets amount
@> UD60x18 totalAssetsX18 = ud60x18(IERC4626(self.indexToken).totalAssets());
// calculate the total assets value in usd terms
UD60x18 totalAssetsUsdX18 = collateral.getAdjustedPrice().mul(totalAssetsX18);
// calculate the vault's credit capacity in usd terms
creditCapacityUsdX18 = totalAssetsUsdX18.intoSD59x18().sub(getTotalDebt(self));
}

Themul operation multiplies two UD60x18 numbers together, returning a new UD60x18 number.
The problem is that totalAssets is casted to ud60x18 type without scaling the amount to 18 decimal precision.
This will make the totalAssetsUsdX18 to be much smaller and the function will return a diminished credit capacity.

If the asset used is wBTC (8 decimals), the asset value will be diminished by 10**(18 - 8) times making the vault credit capacity close to zero.

Impact

Vault with tokens with decimal precision < 18 will not be used because their credit capacity is significantly reduced.

More instances of the same issue

  • StabilityBranch::initiateSwap
    ctx.vaultAssetBalance is in native decimals and ctx.expectedAssetOut is the returned of getAmountOfAssetOut . This function computes the amountOut with 18decimal precision.
    User can't swap usdToken for vault's asset.

  • StabilityBranch::getAmountOfAssetOut
    getPremiumDiscountFactor expects an UD60x18 type and makes operation with 18 decimal precision, but vaultAssetsUsdX18 has native decimals.
    DebtTvlRatio is heavely increased, decreasing the premiumDiscountFactorX18; The amuntOutX18 returned by getAmountOfAssetOut will be discounted.

Tools Used

Recommendations

Use convertTokenAmountToUd60x18 to convert total assets to ZAROS precision:

function getTotalCreditCapacityUsd(Data storage self) internal view returns (SD59x18 creditCapacityUsdX18) {
// load the collateral configuration storage pointer
Collateral.Data storage collateral = self.collateral;
// fetch the zlp vault's total assets amount
- UD60x18 totalAssetsX18 = ud60x18(IERC4626(self.indexToken).totalAssets());
+ UD60x18 totalAssetsX18 = collateral.convertTokenAmountToUd60x18(IERC4626(self.indexToken).totalAssets());
// calculate the total assets value in usd terms
UD60x18 totalAssetsUsdX18 = collateral.getAdjustedPrice().mul(totalAssetsX18);
// calculate the vault's credit capacity in usd terms
creditCapacityUsdX18 = totalAssetsUsdX18.intoSD59x18().sub(getTotalDebt(self));
}
Updates

Lead Judging Commences

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

`totalAssets()` is not properly scaled to ZAROS precision

Appeal created

bigsam Auditor
7 months ago
alexczm Submitter
7 months ago
inallhonesty Lead Judge
6 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

`totalAssets()` is not properly scaled to ZAROS precision

Support

FAQs

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