For the complete documentation index, see llms.txt. This page is also available as Markdown.

56961 sc low incorrect balance snapshot check in deallocate logs false deallocation loss in morphoyearnogweth strategy

Submitted on Oct 22nd 2025 at 08:19:04 UTC by @Bluedragon for Audit Comp | Alchemix V3

  • Report ID: #56961

  • Report Type: Smart Contract

  • Report severity: Low

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

  • Impacts:

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Summary:

The _deallocate function in MorphoYearnOGWETH.sol measures WETH redeemed by taking a balance snapshot incorrectly (it reads the same balance twice after calling vault.withdraw). As a result, wethRedeemed is always zero, which causes the strategy to emit a StrategyDeallocationLoss event on successful deallocations.

Vulnerability Details:

In the _deallocate function, the code captures the WETH balance snapshot after calling vault.withdraw, leading to an incorrect calculation of wethRedeemed. Thus, the strategy always believes there is a loss during deallocation, even when there isn't and emits the StrategyDeallocationLoss event incorrectly.

Code Snippet:

    function _deallocate(uint256 amount) internal override returns (uint256) {
        vault.withdraw(amount, address(this), address(this));
        // @audit-insight incorrect logic: should check balance before and after withdraw
        // The wethRedeemed will always be 0, thus incorrect deallocation log is emitted.
        uint256 wethBalanceBefore = TokenUtils.safeBalanceOf(address(weth), address(this));
        uint256 wethBalanceAfter = TokenUtils.safeBalanceOf(address(weth), address(this));
        uint256 wethRedeemed = wethBalanceAfter - wethBalanceBefore;
        console.log("WETH Redeemed:", wethRedeemed);
        if (wethRedeemed < amount) {
            emit StrategyDeallocationLoss("Strategy deallocation loss.", amount, wethRedeemed);
        }
        require(wethRedeemed + wethBalanceBefore >= amount, "Strategy balance is less than the amount needed");
        require(
            TokenUtils.safeBalanceOf(address(weth), address(this)) >= amount,
            "Strategy balance is less than the amount needed"
        );
        TokenUtils.safeApprove(address(weth), msg.sender, amount);
        return amount;
    }

Impact

  • The strategy incorrectly emits StrategyDeallocationLoss events when no loss occurred.

  • May cause unnecessary reverts or alerts in event monitoring services.

  • Breaks accounting and invariants that depend on accurate deallocation events and reporting.

Proof of Concept

Proof of Concept:

  1. Add the following test case to the MorphoYearnOGWETHStrategy.t.sol

  2. Run the test using the command forge test --mt test_bluedragon_startegy_deallocation_always_fails_due_to_incorrect_logic -vvvv

  3. Observe that the StrategyDeallocationLoss event is emitted even when there is no actual loss.

POC Test Case:

Logs:

Correct the snapshot order. Capture wethBalanceBefore before calling vault.withdraw, and wethBalanceAfter after the withdraw.

Was this helpful?