58707 sc medium moonwell strategy allocate does not revert when mint fails which can result in a sudden drop in myt share price and consequently sever under collateralization

Submitted on Nov 4th 2025 at 07:32:46 UTC by @niroh for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #58707

  • Report Type: Smart Contract

  • Report severity: Medium

  • Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/strategies/optimism/MoonwellUSDCStrategy.sol

  • Impacts:

    • Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

Description

Brief/Intro

Both MoonwellUSDCStrategy and MoonwellWETHStrategy implement _allocate() by calling the moonwell mToken mint function with the allocated funds:

function _allocate(uint256 amount) internal override returns (uint256) {
    require(TokenUtils.safeBalanceOf(address(usdc), address(this)) >= amount, "Strategy balance is less than amount");
    TokenUtils.safeApprove(address(usdc), address(mUSDC), amount);
    // Mint mUSDC with underlying USDC
    mUSDC.mint(amount);
    return amount;
}

Moonwell MErc20's implementation of mint returns an error value instead of reverting for some error types that might occur during minting (such as the mint being rejected by the comptroller of math errors):

Vulnerability Details

Since the Moonwell strategies do not check the return value from mERC20::mint and revert when an error occurs, it might happen that the mToken does not mint any funds, returns an error, but the Strategy allocation transaction succeeds, leaving the USDC/Weth transffered in from the Myt vault as non-deposited balance of the Strategy.

A side-effect from such a scenario is that the strategy's realAssets() function will return 0 (inspite of the fact that it holds non-deposited funds), since realAssets() is based only on deposited funds:

Consequently, the Myt share price (which is calculated in convertToAssets based on the aggregated adapters' realAssets() plus the Myt vault balance) will experience a sudden drop.

Note that the USDC/Weth left in the strategy can easily be transffered back to the Myt vault by calling deallocate (which will deallocate from the strategy free balance even if it is not curretly depoloyed to Moonwell). However, while VaultV2 enables sudden drops in share price, it limits price increases through the maxRate setting (which can be set up to a maximum 200% APR), Which means it might take a very long time for the price to recuperate to it's real value.

This situation enables the following exploit path:

attack scenario

  1. Option A: An attacker who holds a privilaged Moonwell role that enables temporarily disabling mints for the Strategy, monitors for a large allocation and frontruns with a tx that disallows Strategy mints. Options B: An attacker who is aware of the issue monitors for a large allocation that is expected to fail naturally (due to temporary mint disabling, expeceted math error or other reason).

  2. Myth vault makes an allocation of 50% of total funds to the Moonwell vault. The allocation completes without revert even though no funds were deposited to Moonwell. As a result the Myt Vault share price immediately drops 50% (since the strategy, who now holds 50% of the Myth vault funds, report 0 realAssets).

  3. The sharp drop in Myt share price is likely to cause bad debt/make many CDPs liquidatable.

  4. The attacker batch liquidates as many CDPs as possible for the fees (Since AlchemistV3 is in high-ltv state, fees are maximized due to full liquidations, and are taken from the fee-vault).

  5. In addition, the attacker accumulates matured redemptions ahead of time (either buying their nfts or pre-submitting themselves)and redeems them.

  6. Since Myt vault share price is now artificially reduced, all redemptions benefit the redeemer on the account of CDP holders. This is because the low price is based on an underestimation of funds. The share price will inevidably crawl back up to its real value (at a rate limited by maxRate) until it represents the real totalAssets.

Impact Details

  1. Loss to CDP holders as their collateral is liquidated/redeemed for half it's real price.

  2. Likely also protocol insolvancy as a result of the sharp drop in Collateral value (as precieved by the system)

References

https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/strategies/optimism/MoonwellUSDCStrategy.sol#L48

Proof of Concept

Proof of Concept

How to run:

  1. Copy the code below into the MoonwellUSDCStrategyTest contract in /v3-poc/src/test/strategies/MoonwellUSDCStrategy.t.sol

  2. Add the following import and interface at the top of the file:

  1. Run with FOUNDRY_PROFILE=default forge test --fork-url https://optimism.gateway.tenderly.co --match-test testMoonwellMintFailure --isolate -vvv Note: the --isolate flag is required to properly see VaultV2 price changes since VaultV2 prevents multiple price changes within a single transaction, and calls made from a forge test appear as part of a single transaction (unless --isolate is specified)

Was this helpful?