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

[M-02] Slippage Vulnerability in Collateral Token Operations

Summary

The AaveDIVAWrapper contract fails to account for potential slippage and rounding errors during collateral deposit/withdrawal operations, risking inaccurate wToken minting/burning and improper tracking of Aave positions.

Vulnerability Details

Affected Functions:

1. _handleTokenOperations (Collateral deposit)

2. _redeemWTokenPrivate (Collateral withdrawal)

Core Issues:

1. Unchecked Aave Supply (wToken Minting)

In _handleTokenOperations:

IAave(_aaveV3Pool).supply(
_collateralToken,
_collateralAmount, // Uses input amount directly
address(this),
0
);
IWToken(_wToken).mint(address(this), _collateralAmount);

Problem: Aave's supply() returns the actual aToken amount minted, which may differ from _collateralAmount due to:

  • aToken exchange rate fluctuations

  • Interest accrual timing

  • Rounding differences in aToken decimals

  1. Unverified Withdraw Amount (wToken Burning)

In _redeemWTokenPrivate:

IWToken(_wToken).burn(_burnFrom, _wTokenAmount);
uint256 _amountReturned = IAave(_aaveV3Pool).withdraw(
_collateralToken,
_wTokenAmount, // No minimum output check
_recipient
);

Problem: The actual collateral withdrawn from Aave may not match _wTokenAmount due to:

  • aToken exchange rate changes

  • Protocol-level rounding rules

  • Interest accrual since deposit

Impact

  1. Users may receive less collateral than expected when withdrawing

  2. Protocol could mint more wTokens than aToken reserves

  3. Yield calculations in _getAccruedYieldPrivate could become inaccurate

  4. Potential protocol insolvency if aToken/wToken balances diverge significantly

Tools Used

  • Manual code analysis

  • Aave V3 protocol documentation review

Recommendations

  • Use Actual aToken Amount for Minting

function _handleTokenOperations(...) private {
// ...
uint256 aTokenBalanceBefore = IERC20(aToken).balanceOf(address(this));
IAave(_aaveV3Pool).supply(...);
uint256 aTokensMinted = IERC20(aToken).balanceOf(address(this)) - aTokenBalanceBefore;
IWToken(_wToken).mint(address(this), aTokensMinted);
}
  • Add Slippage Protection for Withdrawals:

function _redeemWTokenPrivate(...) private returns (uint256) {
// ...
uint256 minExpected = _wTokenAmount * (10**18 - MAX_SLIPPAGE_BPS) / 10**18;
uint256 _amountReturned = IAave(_aaveV3Pool).withdraw(...);
if (_amountReturned < minExpected) {
revert InsufficientWithdrawalAmount();
}
}
  • Implement Rebase Mechanism:
    Consider making wTokens rebase tokens that track aToken balances directly, or implement periodic balance reconciliation functions.

  • Add Emergency Pause:
    Include circuit-breaker functionality to freeze operations if aToken/wToken balance discrepancies exceed safe thresholds.

Updates

Lead Judging Commences

bube Lead Judge 7 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.