<!-- canonical: https://0xsimao.com/findings/superfluid-erc4626-yield-paused-stuck -->

# ERC4626YieldBackend.withdrawMax() silently succeeds when vault is paused, leaving funds stuck

Low/Info · Sherlock · Money streaming · 13th January, 2026

Finding L-3 of the Superfluid Yield Backends security review.

- Protocol: https://superfluid.org/
- Report: /reports/superfluid
- Codebase: https://github.com/0xsimao/protocol-monorepo/tree/d69e4b0394c38d2760b9b54f173a797b630c9ed1
- Source: https://github.com/superfluid-org/protocol-monorepo/blob/dev/packages/ethereum-contracts/audits/2026-01-27%20-%20Final%20-%20Superfluid%20Collaborative%20Audit%20Report%201769517931.pdf

---

## Summary

`ERC4626YieldBackend.withdrawMax()` silently succeeds when the vault is paused, leaving funds stuck after `disableYieldBackend()` is called.

## Vulnerability Detail

Per EIP-4626, when a vault is paused, `maxWithdraw()` should return 0 rather than revert. The `withdrawMax()` function checks if `balance > 0` before attempting withdrawal, so when a vault is paused, it simply does nothing and returns successfully.

The problem is that `SuperToken.disableYieldBackend()` calls `withdrawMax()` and then clears the yield backend reference. If the vault is paused at the time of disabling, the call succeeds but funds remain locked in the vault. Since the yield backend reference is cleared, there is no way to recover the funds afterward.

```solidity
function disableYieldBackend() external onlyAdmin {
    require(address(_yieldBackend) != address(0), "yield backend not set");
    address oldYieldBackend = address(_yieldBackend);

    _skipSelfMint = true;
    delegateCallChecked(address(_yieldBackend), abi.encodeCall(IYieldBackend.withdrawMax, ()));
    _skipSelfMint = false;

    delegateCallChecked(address(_yieldBackend), abi.encodeCall(IYieldBackend.disable, ()));
    _yieldBackend = IYieldBackend(address(0)); // Backend cleared, funds stuck!
    emit YieldBackendDisabled(oldYieldBackend);
}
```

## Impact

When `disableYieldBackend()` is called while the ERC4626 vault is paused, all funds deposited in the vault become permanently stuck. The yield backend is disabled and there is no mechanism to recover the funds.

## Code Snippet

https://github.com/sherlock-audit/2026-01-superfluid-update-jan-13th/blob/main/protocol-monorepo/packages/ethereum-contracts/contracts/superfluid/ERC4626YieldBackend.sol#L38-L43

```solidity
function withdrawMax() external {
    uint256 balance = VAULT.maxWithdraw(address(this));
    if (balance > 0) {
        VAULT.withdraw(balance, address(this), address(this));
    }
}
```

## Tool Used

Manual Review

## Recommendation

Add a check in `disableYieldBackend()` to verify that funds were actually withdrawn, or add a minimum expected amount parameter:

```solidity
function withdrawMax() external returns (uint256) {
    uint256 balance = VAULT.maxWithdraw(address(this));
    if (balance > 0) {
        VAULT.withdraw(balance, address(this), address(this));
    }
    return balance;
}
```

Then in `SuperToken.disableYieldBackend()`:

```solidity
function disableYieldBackend(uint256 minExpectedAmount) external onlyAdmin {
    // ... existing code ...
    uint256 withdrawn = delegateCallChecked(address(_yieldBackend), abi.encodeCall(IYieldBackend.withdrawMax, ()));
    require(withdrawn >= minExpectedAmount, "insufficient withdrawal");
    // ... rest of function ...
}
```

---

Related findings:

- [`totalEarnings` is incorrect when withdrawing after ending which will withdraw too many funds leaving the `Vault` insolvent](https://0xsimao.com/findings/saffron-lido-vaults-ending-withdraw-leaving-insolvent): Saffron Lido Vaults
- [Frozen/paused Market that is harvested from in StakedEXA will DoS deposits leading to loss of yield](https://0xsimao.com/findings/exactly-protocol-update-staking-contract-ii-paused-harvested-deposits-yield): Exactly Protocol Update - Staking Contract
- [Incorrect `ERC4626ExceededMaxRedeem` event on `ManagedLeveragedVault.sol:: cancelWithdrawalIntent()`](https://0xsimao.com/findings/beraborrow-i-erc4626-exceeded-redeem-withdrawal): Beraborrow Managed Dens
- [`PreDepositVault::maxDeposit/Mint()` are missing `maxDepositLimit` as per the ERC4626 spec](https://0xsimao.com/findings/gaib-deposit-mint-erc4626-spec): GAIB Pre-Vaults
