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

Inability to Withdraw Converted Assets from transmuter Without claimAndSwap Invocation

01. Relevant GitHub Links

02. Summary

The strategy of the Strategy Contract is to deposit alETH into the transmuter so that it can later be converted to WETH. However, to withdraw WETH from the transmuter, you need to call transmuter.claim. This claim function is only called within the claimAndSwap function. If the conditions or path for a favorable swap are not met or the keeper call does not occur, the converted WETH will remain locked in the transmuter indefinitely.

This scenario results in a situation where the assets cannot be recovered, effectively freezing user funds.

03. Vulnerability Details

Within the StrategyMainnet contract, deposited alETH is sent into the transmuter. Inside the transmuter, alETH can be converted into WETH. However, the logic to actually withdraw these converted assets (WETH) is tightly coupled to the claimAndSwap function. Specifically, the transmuter.claim call—which releases WETH to the strategy—is performed solely within claimAndSwap:

function claimAndSwap(
uint256 _amountClaim,
uint256 _minOut,
uint256 _routeNumber
) external onlyKeepers {
transmuter.claim(_amountClaim, address(this));
uint256 balBefore = asset.balanceOf(address(this));
require(_minOut > _amountClaim, "minOut too low");
router.exchange(
routes[_routeNumber],
swapParams[_routeNumber],
_amountClaim,
_minOut,
pools[_routeNumber],
address(this)
);
uint256 balAfter = asset.balanceOf(address(this));
require((balAfter - balBefore) >= _minOut, "Slippage too high");
transmuter.deposit(asset.balanceOf(address(this)), address(this));
}

If claimAndSwap is never called, or cannot be called due to unfavorable market conditions (such as the requirement that _minOut > _amountClaim), the WETH inside the transmuter remains unreachable. This effectively locks the funds:

  • The claimAndSwap function attempts to ensure profit by requiring a premium on the swapped alETH relative to the claimed WETH. If alETH’s relative value drops or if there are routing/pool issues on the configured router, this condition might not be met.

  • Without satisfying these conditions, the keeper may never execute claimAndSwap.

  • Consequently, transmuter.claim never runs, leaving the converted WETH stuck indefinitely.

04. Impact

The impact is significant because it can lead to a permanent lock of the funds converted to WETH within the transmuter. Users’ deposits become illiquid and irretrievable, even if the underlying assets still technically exist. In a worst-case scenario—if market conditions or routing parameters never improve—these assets remain forever locked.

05. Tools Used

Manual Code Review and Foundry

06. Recommended Mitigation

Introduce an alternative mechanism for emergency withdrawal of WETH from the transmuter that does not rely solely on claimAndSwap. Specifically, allow authorized roles or emergency functions to call transmuter.claim directly without executing a swap. This ensures that, even under unfavorable conditions or route failures, the converted WETH can still be reclaimed and not permanently locked.

By decoupling the claim operation from the claimAndSwap process, the protocol can maintain user fund availability, preventing permanent asset lockups.

Updates

Appeal created

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
bshyuunn Submitter
10 months ago
inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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