There is a potential reentrancy risk in token transfers, especially when transferring tokens to external contracts such as Aave.
Although the contract AaveDIVAWrapperCore.sol uses the safeTransfer method for token transfers, some functions (like _redeemWTokenPrivate) may still be vulnerable to reentrancy attacks if external contracts or tokens are involved that can call back into the contract. If reentrancy occurs, an attacker could call back into the contract before state changes are finalized, potentially manipulating the contract's behavior.
Reentrancy attacks could lead to a malicious actor draining tokens from the contract by repeatedly calling back into the vulnerable functions before they are finished, bypassing safeguards and leading to significant loss of funds.
Proof of Concept for Reentrancy Risk in Token Transfers
The contract is vulnerable to reentrancy attacks when transferring tokens, allowing an attacker to repeatedly call back into the contract before the previous execution is completed. This could lead to unauthorized withdrawals, draining funds from the protocol.
Attacker: A malicious contract exploiting the reentrancy vulnerability.
Victim: The protocol or a user whose funds are at risk.
Protocol: The smart contract managing token transfers.
Working Test Case (PoC)
This PoC demonstrates how an attacker can exploit the reentrancy vulnerability.
Vulnerable Smart Contract
The vulnerable contract allows users to deposit and withdraw funds but does not follow the Checks-Effects-Interactions pattern.
Issue: The withdraw function first sends Ether before updating the user’s balance.
Risk: A malicious contract can re-enter the function before its balance is reduced.
2 Attacker Contract (Exploit)
This contract exploits the vulnerability by recursively calling withdraw() before the balance is updated.
3 Step-by-Step Exploit Scenario
The attacker deploys the ReentrancyAttacker contract.
The attacker deposits 1 ETH into the VulnerableTokenVault.
Attacker calls withdraw(1 ether) from the VulnerableTokenVault.
Vault sends 1 ETH to the attacker contract before updating the balance.
The attacker's fallback function is triggered (via receive() function).
Recursive reentrancy: Before the previous withdrawal is finalized, the attacker calls withdraw(1 ether) again.
Steps 2-4 repeat until the contract is drained.
The attacker repeatedly withdraws funds before their balance is updated.
The entire contract balance is stolen.
Manual code review
Recommended Mitigation
Modify withdraw() to update the balance before making the external call:
✅ Advanced Checks & Mitigation Plans
Use ReentrancyGuard from OpenZeppelin:
Use transfer() or send() Instead of call():
transfer() and send() limit gas to prevent reentrancy attacks.
But they are not always recommended due to gas limit issues.
Whitelist Trusted Contracts:
If interacting with contracts, verify they are trusted before allowing transactions.
Reentrancy Testing:
Use Hardhat’s expectRevert to test for reentrancy vulnerabilities.
Implement fuzz testing to explore unusual execution paths.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.