Part 2

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

Missing Asset Price Validation May Result in Lower Redemption Amounts

Description: Users redeem a given amount of index tokens in exchange for collateral assets from the provided vault after the withdrawal delay period has elapsed. The VaultRouterBranch::redeem function calculates the assets minus the redeem fee as shares, sends the vault shares to the user, and transfers the redeem fee to the recipient.

function redeem(uint128 vaultId, uint128 withdrawalRequestId, uint256 minAssets) external {
--SNIP--
@> ctx.sharesMinusRedeemFeesX18 =
getVaultAssetSwapRate(vaultId, ctx.expectedAssetsMinusRedeemFeeX18.intoUint256(), false);
ctx.sharesFees = ctx.shares - ctx.sharesMinusRedeemFeesX18.intoUint256();
--SNIP--
// Redeem shares previously transferred to the contract at `initiateWithdrawal` and store the returned assets
uint256 assets =
IERC4626(indexToken).redeem(ctx.sharesMinusRedeemFeesX18.intoUint256(), msg.sender, address(this));
// Get the redeem fee
if (ctx.sharesFees > 0) {
IERC4626(indexToken).redeem(
ctx.sharesFees, marketMakingEngineConfiguration.vaultDepositAndRedeemFeeRecipient, address(this)
);
}
--SNIP--
}

The getVaultAssetSwapRate function calculates the swap rate (in shares) for a given amount of collateral (assetsIn) when deposited into a specific vault.

// File: src/market-making/VaultRouterBranch/getVaultCreditCapacity
function getVaultAssetSwapRate(
...
)
public
view
returns (UD60x18 sharesOut)
{
--SNIP--
// get the vault's net credit capacity, i.e its total assets usd value minus its total debt (or adding its
// credit if debt is negative)
uint256 totalAssetsMinusVaultDebt = getVaultCreditCapacity(vaultId);
...
}

The getVaultCreditCapacity function returns the net credit capacity of the given vault, taking into account its underlying assets and debt.

function getVaultCreditCapacity(uint128 vaultId) public view returns (uint256) {
--SNIP--
// @audit There's no explicit check to ensure that the asset price is not zero, which could lead to a division by zero error.
// get collateral asset price
UD60x18 assetPriceX18 = vault.collateral.getPrice();
--SNIP--
}

The same issue applies to the fee recipient, who may also receive less than the expected fee.

Impact: 1. There is no explicit check to ensure that the asset price is greater than zero, which could lead to a division by zero error.

  1. Users may receive less redeemable assets than expected.

  2. The fee recipient might also get less than the expected fee due to this issue.

Recommended Metigation: A check should be added to ensure that the asset price is not zero before performing calculations.

// File: src/market-making/VaultRouterBranch::getVaultCreditCapacity
function getVaultCreditCapacity(uint128 vaultId) public view returns (uint256) {
--SNIP--
UD60x18 assetPriceX18 = vault.collateral.getPrice();
+ require(assetPriceX18.unwrap() > 0, "Asset price cannot be zero");
--SNIP--
}
Updates

Lead Judging Commences

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

Support

FAQs

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