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

Insufficient Withdrawal Liquidity Due to Unaccounted WETH

Summary

The withdrawal mechanism in the strategy fails to account for WETH balances transformed from ALETH in the Transmuter. As a result, users(whales) may experience withdrawal blockage when a significant portion of ALETH has been transformed into WETH but remains unswapped. This forces users to either delay their withdrawal until a keeper calls claimAndSwap, creating a suboptimal and potentially harmful user experience.

Vulnerability Details

The Mechanism : Deposited ALETH is sent to the Transmuter, where it is transformed into WETH over time. The transformed WETH is later swapped back into ALETH via a router mechanism and the increasing ALETH actually means the yield. However, this causes some issues since the withdrawal mechanism in the strategy fails to account for WETH balances transformed from ALETH in the Transmuter.

Take withdraw for example:
During withdrawal, the availableWithdrawLimit calculates the maximum withdrawable amount as the sum of ALETH held in the strategy and the unexchangedBalance in the transmuter. However, the availableWithdrawLimit does not include the value of WETH that has been transformed but not yet swapped.

function availableWithdrawLimit(
address /*_owner*/
) public view override returns (uint256) {
// NOTE: Withdraw limitations such as liquidity constraints should be accounted for HERE
// rather than _freeFunds in order to not count them as losses on withdraws.
// TODO: If desired implement withdraw limit logic and any needed state variables.
// EX:
// if(yieldSource.notShutdown()) {
// return asset.balanceOf(address(this)) + asset.balanceOf(yieldSource);
// }
// NOTE : claimable balance can only be included if we are actually allowing swaps to happen on withdrawals
//uint256 claimable = transmuter.getClaimableBalance(address(this));
return asset.balanceOf(address(this)) + transmuter.getUnexchangedBalance(address(this));
}

The maxWithdraw function restricts withdrawals to the minimum of the calculated limit and the user’s balance.

maxWithdraw_ = Math.min(
_convertToAssets(S, _balanceOf(S, owner), Math.Rounding.Down),
maxWithdraw_
);

If significant ALETH has been transformed into WETH, the maxWithdraw function will return a reduced value, blocking large withdrawals until a keeper calls claimAndSwap. For users with large deposits (e.g., whales), this mechanism can prevent timely access to funds, especially during periods of high transformation rates where most ALETH is held as WETH.

Impact

If significant ALETH has been transformed into WETH, the maxWithdraw function will return a reduced value, blocking large withdrawals until a keeper calls claimAndSwap. For users with large deposits (e.g., whales), this mechanism can prevent timely access to funds, especially during periods of high transformation rates where most ALETH is held as WETH.

Tools Used

Manual

Recommendations

A possible way is to allow a partial swap of WETH back into ALETH.

Updates

Lead Judging Commences

inallhonesty Lead Judge
6 months ago

Appeal created

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
jesjupyter Submitter
6 months ago
jesjupyter Submitter
6 months ago
inallhonesty Lead Judge
6 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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