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

`AaveDivaWrapper` may revert when aave supply limit is reached or pool owner pause/froze the pool

Summary

AaveDivaWrapper interacts with the Aave v3 pool each time collateral tokens are deposited or withdrawn. This creates a single point of failure. If interactions with Aave fail due to reaching the supply limit or the pool being paused/frozen, users will be unable to deposit or redeem collateral tokens.

Vulnerability Details

In AaveDivaWrapper.sol, functions _claimYield, _handleTokenOperations, and _redeemWTokenPrivate interact with Aave v3 for withdrawing and supplying collateral tokens. These operations depend entirely on Aave’s availability:

https://github.com/Cyfrin/2025-01-diva/blob/1b6543768c341c2334cdff87b6dd627ee2f62c89/contracts/src/AaveDIVAWrapperCore.sol#L344

function _claimYield(address _collateralToken, address _recipient) internal returns (uint256) {
// Confirm that the collateral token is registered
if (_collateralTokenToWToken[_collateralToken] == address(0)) {
revert CollateralTokenNotRegistered();
}
if (_recipient == address(0)) revert ZeroAddress();
// Redeem aToken for collateral token at Aave Protocol and send collateral token to recipient.
@-> uint256 _amountReturned = IAave(_aaveV3Pool).withdraw(
_collateralToken, // Address of the underlying asset (e.g., USDT), not the aToken.
_getAccruedYieldPrivate(_collateralToken), // Amount to withdraw.
_recipient // Address that will receive the underlying asset.
);
emit YieldClaimed(owner(), _recipient, _collateralToken, _amountReturned);
return _amountReturned;
}

https://github.com/Cyfrin/2025-01-diva/blob/1b6543768c341c2334cdff87b6dd627ee2f62c89/contracts/src/AaveDIVAWrapperCore.sol#L431

function _handleTokenOperations(address _collateralToken, uint256 _collateralAmount, address _wToken) private {
// Transfer collateral token from the caller to this contract. Requires prior approval by the caller
// to transfer the collateral token to the AaveDIVAWrapper contract.
IERC20Metadata(_collateralToken).safeTransferFrom(msg.sender, address(this), _collateralAmount);
// Supply the collateral token to Aave and receive aTokens. Approval to transfer the collateral token from this contract
// to Aave was given when the collateral token was registered via `registerCollateralToken` or when the
// allowance was set via `approveCollateralTokenForAave`.
@-> IAave(_aaveV3Pool).supply(
_collateralToken, // Address of the asset to supply to the Aave reserve.
_collateralAmount, // Amount of asset to be supplied.
address(this), // Address that will receive the corresponding aTokens (`onBehalfOf`).
0 // Referral supply is currently inactive, you can pass 0 as referralCode. This program may be activated in the future through an Aave governance proposal.
);
// Mint wTokens associated with the supplied asset, used as a proxy collateral token in DIVA Protocol.
// Only this contract is authorized to mint wTokens.
IWToken(_wToken).mint(address(this), _collateralAmount);
}

https://github.com/Cyfrin/2025-01-diva/blob/1b6543768c341c2334cdff87b6dd627ee2f62c89/contracts/src/AaveDIVAWrapperCore.sol#L470

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;
}

Root Cause

Here are some possible scenarios:

  1. Aave v3 may reach deposit limit:

    https://github.com/aave/aave-v3-origin/blob/main/src/core/contracts/protocol/libraries/logic/ValidationLogic.sol#L80

    Currently, Aave Ethereum USDT market now accounts for 64.68% of the supply cap, Aave Ethereum USDC market now accounts for 66.98% of the supply cap. When market utilization increases, Aave/Compound users are incentivized to supply into the market, and is possible to reach the supply limit.

  2. Aave v3 may get paused or retired:

    https://github.com/aave/aave-v3-origin/blob/3aad8ca184159732e4b3d8c82cd56a8707a106a2/src/core/contracts/protocol/libraries/logic/ValidationLogic.sol#L76

    In Nov 2023, Aave paused several markets after reports of feature issue .

External Pre-conditions

  1. Aave governance/admin pause or freeze the pool – Aave v3 reserves can be paused due to governance decisions or emergency actions.

  2. Aave v3 supply cap reached – If the total supply of a particular asset in Aave v3 reaches its cap, new deposits will be blocked.

Attack Path

  1. Attackers or malicious actors could manipulate Aave governance to pause or freeze the pool, causing a denial of service (DoS) to AaveDiva.

  2. Large whales could deposit excessive amounts into Aave v3, reaching the supply cap and preventing further deposits from AaveDiva.

  3. If Aave retires certain collateral assets, the AaveDiva reserve may be unable to function properly due to its immutable nature.

Impact

AaveDiva reserve strategies can become a single point of failure:

  1. Aave governance can DoS AaveDivaWrapper – If Aave v3 is paused, no deposits or withdrawals can be made.

  2. Supply cap limits can DoS AaveDivaWrapper – If the supply cap is reached, new collateral cannot be deposited.

  3. Users cannot redeem collateral – Users relying on AaveDiva for liquidity may face withdrawal failures.

Tools Used

Manual review

Reference

https://solodit.cyfrin.io/issues/m-12-emptyset-reserve-strategies-may-revert-when-aavecompound-supply-limit-is-reached-or-pool-owner-pausefroze-the-pool-sherlock-perennial-v2-update-3-git

Recommendations

Implement a fail-safe mechanism – Wrap _claimYield, _handleTokenOperations, and _redeemWTokenPrivate in a try-catch block to prevent system-wide failures.

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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