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 V3arrow-up-right

  • 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?