HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: low
Invalid

Mismatch between function implementation and comments

Summary

The _redeemWTokenPrivate function is designed to allow users to redeem their wrapped tokens (wTokens) for the underlying collateral tokens by withdrawing from Aave and burning the corresponding wTokens. However, the function currently lacks logic to handle the case where _wTokenAmount is set to type(uint256).max, which is intended to represent the user's full balance. This omission could lead to unexpected behavior or errors when users attempt to redeem their entire wToken balance.

Vulnerability Details

The _redeemWTokenPrivate function does not implement the logic described in its comment, which states:

@param _wTokenAmount The amount of wTokens to withdraw. If `type(uint256).max`, the user's balance will be used.

Currently, the function does not check whether _wTokenAmount is type(uint256).max and does not dynamically adjust the redemption amount based on the user's balance.

function _redeemWTokenPrivate(
address _wToken,
uint256 _wTokenAmount,
address _recipient,
address _burnFrom
) private returns (uint256) {
if (_recipient == address(0)) revert ZeroAddress();
// Burn the specified amount of wTokens. Only this contract has the authority to do so.
// Reverts if `_wTokenAmount` exceeds the user's wToken balance.
IWToken(_wToken).burn(_burnFrom, _wTokenAmount);
address _collateralToken = _wTokenToCollateralToken[_wToken];
// Withdraw the collateral asset from Aave, which burns the equivalent amount of aTokens owned by this contract.
// E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC.
// Collateral token is transferred to `_recipient`.
// Reverts if the collateral token is not a registered wToken (first parameter will be address(0)).
uint256 _amountReturned = IAave(_aaveV3Pool).withdraw(
_collateralToken, // Address of the underlying asset (e.g., USDT), not the aToken.
_wTokenAmount, // Amount to withdraw.
_recipient // Address that will receive the underlying asset.
);
emit WTokenRedeemed(_wToken, _wTokenAmount, _collateralToken, _amountReturned, _recipient);
return _amountReturned;
}

This means that if a user passes type(uint256).max as the _wTokenAmount, the function will attempt to redeem an excessively large amount, which will likely revert due to insufficient balance.

Impact

Users expecting to redeem their full balance by passing type(uint256).max will encounter errors or unexpected behavior.

The impact is Low, the likelihood is Medium, so the severity is Low.

Tools Used

Manual Review

Recommendations

Consider following fix

function _redeemWTokenPrivate(
address _wToken,
uint256 _wTokenAmount,
address _recipient,
address _burnFrom
) private returns (uint256) {
if (_recipient == address(0)) revert ZeroAddress();
// If `_wTokenAmount` is `type(uint256).max`, use the user's balance
if (_wTokenAmount == type(uint256).max) {
_wTokenAmount = IERC20Metadata(_wToken).balanceOf(_burnFrom);
}
// Burn the specified amount of wTokens
IWToken(_wToken).burn(_burnFrom, _wTokenAmount);
// Get the collateral token address
address _collateralToken = _wTokenToCollateralToken[_wToken];
if (_collateralToken == address(0)) {
revert CollateralTokenNotRegistered();
}
// Withdraw collateral token from Aave and transfer to recipient
uint256 _amountReturned = IAave(_aaveV3Pool).withdraw(
_collateralToken, // Address of the underlying asset (e.g., USDT)
_wTokenAmount, // Amount to withdraw
_recipient // Address that will receive the underlying asset
);
emit WTokenRedeemed(_wToken, _wTokenAmount, _collateralToken, _amountReturned, _recipient);
return _amountReturned;
}
Updates

Lead Judging Commences

bube Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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