DeFiFoundrySolidity
16,653 OP
View results
Submission Details
Severity: medium
Invalid

Strategies lack emergency withdraw functions risking the funds to be locked in the contract

Vulnerability Details

The strategy currently lacks an emergency withdrawal mechanism, which creates several risks. For instance: transmuter can be compromised, routers can become illiquid/compromised.

In such cases, there is no way to withdraw the funds from this strategy. Having an emergency withdrawal function is a best practice implemented in ERC4626 vaults.

Example: Beefy Finance:

https://github.com/beefyfinance/beefy-contracts/blob/1789196d53226c945a4932bfcd6fb4664cb1abb7/contracts/archive/strategies/Cake/StrategyCakeV2.sol#L121-L128

Also, notice that the BaseStrategyprovides this function in its interface, letting the implementation responsible to override and implement the logic for that.

The devs even added it as a comment in the code, but unfortunately this was not implemented(neither mentioned that is out of the scope)

https://github.com/Cyfrin/2024-12-alchemix/blob/82798f4891e41959eef866bd1d4cb44fc1e26439/src/StrategyMainnet.sol#L330-L336

/* * @param _amount The amount of asset to attempt to free.
*
function _emergencyWithdraw(uint256 _amount) internal override {
TODO: If desired implement simple logic to free deployed funds.
EX:
_amount = min(_amount, aToken.balanceOf(address(this)));
_freeFunds(_amount);
} */

Impact

  • Funds stuck in transmuter/strategy.

  • No way to bypass withdrawal process in emergencies.

  • Could force users to accept unfavorable swaps to exit positions.

Likelihood: Low, but impact is major if occurs.

Affected Users: All strategy depositors.

Tools Used

Manual Review

Recommendations

Implement the _emergencyWithdrawfunction for al the strategies so it can withdraw the funds from the transmuter. Additionally, implement a emergencyWithdraw function on transmuter where all the funds can be withdrawn(claimable, unexchangeable, etc.) by the strategy.

function _emergencyWithdraw(uint256 _amount) internal override {
// No need to check shutdown status - TokenizedStrategy handles this
// implement emergencyWithdraw in transmuter
uint256 inTransmuter = transmuter.emergencyWithdraw(address(this));
if (inTransmuter > 0) {
uint256 toWithdraw = Math.min(inTransmuter, _amount);
transmuter.withdraw(toWithdraw, address(this));
}
// @audit Note: We don't need to handle assets already in the strategy
// TokenizedStrategy handles those automatically.
}
Updates

Appeal created

inallhonesty Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
inallhonesty Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.