Part 2

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

Vault can enter negative credit capacity state without proper validation (Vault.sol)

Summary

The vaultCreditCapacityUsdX18 value in the Vault.sol contract is not explicitly prevented from becoming negative. While the updateCreditDelegations function ensures credit delegation only occurs when the vault's credit capacity is positive, there is no safeguard to prevent it from reaching a negative state due to accumulated debt or market losses.

Vulnerability Details

  • The function getTotalCreditCapacityUsd(self) determines the vault’s credit capacity but does not enforce a non-negative return.

    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));
    }
  • The vaultCreditCapacityUsdX18 variable in _updateCreditDelegations()is updated as:

    592: vaultCreditCapacityUsdX18 = getTotalCreditCapacityUsd(self);

    If getTotalCreditCapacityUsd(self) returns a negative value, the vault enters an invalid credit state.

  • The condition in updateCreditDelegationsensures that delegation does not proceed if the value is negative but does not prevent the vault from becoming insolvent.

    596: UD60x18 newCreditDelegationUsdX18 = vaultCreditCapacityUsdX18.gt(SD59x18_ZERO)
    ? vaultCreditCapacityUsdX18.intoUD60x18().mul(creditDelegationShareX18)
    : UD60x18_ZERO;

Impact

  • A negative credit state can lead to unrecoverable debt scenarios.

  • If not handled, attempts to delegate credit may fail unpredictably.

  • Malicious actors could manipulate credit capacity through debt accumulation to destabilize the system.

Tools Used

  • Manual Review

Recommendations

  1. Enforce Non-Negative Credit Capacity:
    Modify getTotalCreditCapacityUsd(self) to ensure it never returns a negative value:

    SD59x18 totalCredit = computeTotalCreditCapacity();
    return totalCredit > SD59x18_ZERO ? totalCredit : SD59x18_ZERO;
  2. Require Non-Negative Value on Assignment:
    Before assigning vaultCreditCapacityUsdX18, add:

    require(vaultCreditCapacityUsdX18 >= 0, "Credit capacity cannot be negative");
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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