Part 2

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

Absent/Incorrect Conversion Logic in ZlpVault’s _convertToAssets Function


Summary and Impact

The ZlpVault contract is designed to comply with the ERC4626 standard by converting deposited tokens (“assets”) to vault “shares” and vice versa. However, the vault’s override of the internal conversion function—_convertToAssets—is absent or improperly implemented. Instead of performing the correct conversion from shares to underlying assets, the function references an undefined variable (e.g. “assets”) and calls a market engine function in the wrong direction.

This deviation:

  • Breaks the invariant that share redemption must yield a predictable amount of underlying tokens.

  • Risks inconsistent accounting in deposit and redemption flows.

  • May lead to user confusion and potential downstream errors in credit, debt, or auto-deleveraging calculations.

While the current impact is assessed as low—since it does not immediately grant the ability to steal funds, and might be partially mitigated by off-chain or higher-level checks—it nonetheless represents a clear failure to meet ERC4626’s guarantees. This misalignment with documentation and expected behavior should be acknowledged and corrected.


Vulnerability Details

  • Description:
    The function _convertToAssets, responsible for converting vault shares back into the underlying asset amount, is either absent or contains flawed logic. Instead of computing the correct asset amount (typically by using the ratio of totalAssets to totalSupply), it mistakenly calls a market engine function intended for asset-to-share conversion. Moreover, it references an undefined variable (“assets”), which renders the conversion calculation invalid.

  • Code Snippet:

    function _convertToAssets(uint256 shares, Math.Rounding /**/ ) internal view override returns (uint256) {
    // load erc-7201 storage pointer
    ZlpVaultStorage storage zlpVaultStorage = _getZlpVaultStorage();
    // fetch the amount of assets out for the shares input value calling the `MarketMakingEngine`
    UD60x18 assetsOut = IMarketMakingEngine(zlpVaultStorage.marketMakingEngine).getIndexTokenSwapRate(
    zlpVaultStorage.vaultId, shares, false
    );
    return assetsOut.intoUint256();
    }

Tools Used

  • Manual Review


Recommendations

Implement Correct Conversion Logic:
Fully implement _convertToAssets and its counterpart _convertToShares such that:

  • The conversion functions accurately reflect the ratio of totalAssets to totalSupply.

  • They properly factor in any “offset” decimals and internal debt or credit accounting.


Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!