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

Attackers Can Exploit the Lack of a Pause Mechanism to Drain Funds, Disrupt Operations, and Expose Users to Large-Scale Losses

Summary

The lack of an emergency pause mechanism presents significant risks, including the inability to halt operations in the event of a critical vulnerability. It is recommended to implement a pause function to protect user funds, provide time for fixes, and enhance contract resilience against potential exploits.

Vulnerability Details

The contract currently does not include a mechanism to halt operations in case of a severe security incident. This omission can lead to:

  • Inability to react quickly to vulnerabilities.

  • Continued exposure of user funds to exploits.

  • Potential large-scale financial losses if an issue is exploited before mitigation measures are deployed.

Without a pause function, the contract remains vulnerable in cases such as:

  • AAVE Protocol Exploits: If AAVE faces an unforeseen vulnerability, interactions with its contracts could expose users to risks.

  • DIVA Protocol Failures: A failure in the DIVA protocol could impact the integrity of liquidity and positions.

  • Unknown WToken Contract Bugs: Undiscovered vulnerabilities in the wrapped token contract could lead to unintended losses.

  • Collateral Token Attacks: If collateral assets are compromised (e.g., due to hacking or devaluation), users may suffer severe losses.

  • DOS attacks: attackers overload a smart contract with excessive transactions or computationally expensive operations, leading to increased gas consumption, failed transactions, and disruption of normal contract functionality.

contracts/src/AaveDIVAWrapper.sol:#L27-L77

/**
* @dev See {IAaveDIVAWrapper-createContingentPool}.
*/
function createContingentPool(PoolParams calldata _poolParams) external override nonReentrant returns (bytes32) {
return _createContingentPool(_poolParams);
}
/**
* @dev See {IAaveDIVAWrapper-addLiquidity}.
*/
function addLiquidity(
bytes32 _poolId,
uint256 _collateralAmount,
address _longRecipient,
address _shortRecipient
) external override nonReentrant {
_addLiquidity(_poolId, _collateralAmount, _longRecipient, _shortRecipient);
}
/**
* @dev See {IAaveDIVAWrapper-removeLiquidity}.
*/
function removeLiquidity(
bytes32 _poolId,
uint256 _positionTokenAmount,
address _recipient
) external override nonReentrant returns (uint256) {
return _removeLiquidity(_poolId, _positionTokenAmount, _recipient);
}
/**
* @dev See {IAaveDIVAWrapper-redeemPositionToken}.
*/
function redeemPositionToken(
address _positionToken,
uint256 _positionTokenAmount,
address _recipient
) external override nonReentrant returns (uint256) {
return _redeemPositionToken(_positionToken, _positionTokenAmount, _recipient);
}
/**
* @dev See {IAaveDIVAWrapper-redeemWToken}.
*/
function redeemWToken(
address _wToken,
uint256 _wTokenAmount,
address _recipient
) external override nonReentrant returns (uint256) {
return _redeemWToken(_wToken, _wTokenAmount, _recipient);
}

Impact

  • Security: Without a pause function, the contract remains vulnerable to critical threats that could compromise user assets.

  • Operational Risk: Developers have no immediate recourse to prevent further damage while working on a fix.

Tools Used

Manual Code Review

Recommendations

It is recommended to implement emergency pause functionality and integrate OpenZeppelin’s Pausable contract into AaveDIVAWrapper to enable emergency stops:

import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
contract AaveDIVAWrapper is AaveDIVAWrapperCore, ReentrancyGuard, Pausable {
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
}

And please consider to apply whenNotPaused to addLiquidity, removeLiquidity, redeemPositionToken, redeemWToken, batchAddLiquidity, createContingentPool functions etc., to modify key functions to ensure they cannot be executed when paused, for example:

function createContingentPool(PoolParams calldata _poolParams)
external
override
nonReentrant
whenNotPaused
returns (bytes32)
{
return _createContingentPool(_poolParams);
}
Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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