56839 sc medium moonwell strategies fail to check compound error codes causing silent allocation failures

Submitted on Oct 21st 2025 at 06:00:53 UTC by @jayx for Audit Comp | Alchemix V3arrow-up-right

  • Report ID: #56839

  • Report Type: Smart Contract

  • Report severity: Medium

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

  • Impacts:

    • Temporary freezing of funds for at least 1 hour

Description

Brief/Intro

The MoonwellWETHStrategy and MoonwellUSDCStrategy contracts on Optimism fail to check return codes from Moonwell's mint() and redeemUnderlying() functions, which follow Compound's convention of returning 0 on success and non-zero error codes on failure without reverting. When Moonwell rejects operations (due to market pause, borrow cap, or comptroller policy), the strategies silently continue execution, reporting successful allocations to the vault while leaving underlying assets idle in the strategy contract. This creates an accounting discrepancy where the vault believes funds are allocated and earning yield, but realAssets() reports zero position, violating protocol invariants and preventing proper capital deployment.

Vulnerability Details

Moonwell inherits Compound v2's error handling system where mint() and redeemUnderlying() return uint error codes instead of reverting. According to Compound documentation and Moonwell's own audit findings, these functions return 0 for success and non-zero values (1-14) for various error conditions such as market paused (13), insufficient liquidity, comptroller rejection, or borrow cap reached.

Vulnerable Code in _allocate()

MoonwellWETHStrategy.sol:

MoonwellUSDCStrategy.sol:

Vulnerable Code in _deallocate()

MoonwellWETHStrategy.sol:

MoonwellUSDCStrategy.sol:

Failure Scenario

When Moonwell's market conditions prevent minting:

  1. Operator calls strategy.allocate(10 ETH)

  2. Strategy approves WETH to mWETH contract

  3. mWETH.mint(10 ETH) returns error code 13 (market paused) - does not revert

  4. Strategy ignores return value and continues

  5. Function returns amount = 10 ETH to vault

  6. Vault records successful allocation of 10 ETH

  7. realAssets() returns 0 (no mTokens minted)

  8. 10 WETH sits idle in strategy earning no yield

Impact Details

  • Allocations can falsely succeed while assets remain idle in the strategy, causing temporary withdrawal/rebalance failures and degraded liveness until retry or remediation.

  • Users may experience failed exits and zero yield on “allocated” funds during Moonwell pauses or caps, with no principal loss but clear service disruption.

References

https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/strategies/optimism/MoonwellWETHStrategy.sol#L49C6-L50C28

https://github.com/alchemix-finance/v3-poc/blob/a192ab313c81ba3ab621d9ca1ee000110fbdd1e9/src/strategies/optimism/MoonwellWETHStrategy.sol#L56C7-L58C52

Proof of Concept

Proof of Concept

Was this helpful?