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

Large Input for Withdrawal Causing Reverts in `AaveDIVAWrapperCore::_redeemPositionToken` Function

Summary

The contract allows users to specify an amount for redemption. If a user inputs type(uint256).max, the system correctly defaults to withdrawing their full balance. However, if the user enters a very large number close to uint256.max but higher than their actual balance, the transaction will fail due to insufficient balance. This results in a poor user experience, wasted gas fees, and unnecessary transaction failures.

Vulnerability Details

Affected code in AaveDIVAWrapperCore:

function _redeemPositionToken(
address _positionToken,
uint256 _positionTokenAmount,
address _recipient
) internal returns (uint256) {
// Query pool parameters to obtain the collateral token address associated with the
// provided short or long token address (_positionToken).
IDIVA.Pool memory _pool = IDIVA(_diva).getPoolParametersByAddress(_positionToken);
// Early check that the pool's collateral token is associated with a registered collateral token.
// This ensures an immediate and graceful revert.
if (_wTokenToCollateralToken[_pool.collateralToken] == address(0)) {
revert CollateralTokenNotRegistered();
}
IERC20Metadata _positionTokenContract = IERC20Metadata(_positionToken);
IERC20Metadata _collateralTokenContract = IERC20Metadata(_pool.collateralToken);
// Use the user's balance if `_positionTokenAmount` equals `type(uint256).max`.
@> uint256 _userBalance = _positionTokenContract.balanceOf(msg.sender);
@> uint256 _positionTokenAmountToRedeem = _positionTokenAmount;
@> if (_positionTokenAmount == type(uint256).max) {
@> _positionTokenAmountToRedeem = _userBalance;
}
// other code logic here
  • The logic correctly handles the type(uint256).max case by setting _positionTokenAmountToRedeem = _userBalance.

  • However, when a user enters a very large number less than type(uint256).max but greater than _userBalance, the contract proceeds with the entered number without checking if the balance is sufficient.

  • This leads to a transaction failure (revert) when the contract attempts to transfer more tokens than the user owns.

Impact

  • Failed transactions: If a user unknowingly enters a large number, they will experience failed transactions and lose gas fees.

  • Poor user experience: Users may assume they are redeeming all tokens but will face unnecessary reverts.

  • Gas inefficiency: The revert will cost gas, which could have been avoided with a proper check.

Tools Used

Manuel Review

Recommendations

Modify the logic to automatically cap the input to the user’s balance if the entered value exceeds the available balance.

Code Solution

function _redeemPositionToken(
address _positionToken,
uint256 _positionTokenAmount,
address _recipient
) internal returns (uint256) {
// Query pool parameters to obtain the collateral token address associated with the
// provided short or long token address (_positionToken).
IDIVA.Pool memory _pool = IDIVA(_diva).getPoolParametersByAddress(_positionToken);
// Early check that the pool's collateral token is associated with a registered collateral token.
// This ensures an immediate and graceful revert.
if (_wTokenToCollateralToken[_pool.collateralToken] == address(0)) {
revert CollateralTokenNotRegistered();
}
IERC20Metadata _positionTokenContract = IERC20Metadata(_positionToken);
IERC20Metadata _collateralTokenContract = IERC20Metadata(_pool.collateralToken);
// Use the user's balance if `_positionTokenAmount` equals `type(uint256).max`.
uint256 _userBalance = _positionTokenContract.balanceOf(msg.sender);
uint256 _positionTokenAmountToRedeem = _positionTokenAmount;
- if (_positionTokenAmount == type(uint256).max) {
- _positionTokenAmountToRedeem = _userBalance;
- }
+ if (_positionTokenAmount == type(uint256).max || _positionTokenAmount > _userBalance) {
+ _positionTokenAmountToRedeem = _userBalance;
+ }
// other code logic here

How It Works

Condition Old Behavior New Behavior
User enters type(uint256).max Withdraws all tokens (correct) Withdraws all tokens (correct)
User enters a number greater than their balance Transaction reverts Withdraws max available balance
User enters a valid amount within balance Works fine Works fine

This change ensures a smooth user experience, prevents unnecessary transaction failures, and reduces wasted gas fees.

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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