Tadle

Tadle
DeFi
30,000 USDC
View results
Submission Details
Severity: high
Valid

Reentrancy Vulnerability in `withdraw` function

Summary

The withdraw function in the TokenManager contract is susceptible to a reentrancy attack when handling native token withdrawals. The sequence of transferring the wrapped native token, unwrapping it, and then transferring the native token to the user creates a potential point of re-entry for malicious contracts.

Vulnerability Details

The withdraw function, when dealing with native tokens, performs the following steps:

  1. _transfer(wrappedNativeToken, capitalPoolAddr, address(this), claimAbleAmount, capitalPoolAddr);: Transfers the wrapped native token from the capitalPoolAddr to the TokenManager contract itself.

  2. IWrappedNativeToken(wrappedNativeToken).withdraw(claimAbleAmount);: Unwraps the specified amount of wrapped native tokens.

  3. payable(msg.sender).transfer(claimAbleAmount);: Transfers the unwrapped native tokens to the user (msg.sender).

The vulnerability lies in the potential for a malicious wrappedNativeToken contract to re-enter the withdraw function during the msg.sender.transfer call. This re-entry could allow the attacker to execute additional withdrawals or manipulate the contract's state before the original withdraw function completes.

https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/TokenManager.sol#L137-L189

Impact

If a malicious wrappedNativeToken contract is used, it could repeatedly re-enter the withdraw function, potentially draining the TokenManager contract's native token balance.

Tools Used

manual review

Recommendations

Add a reentrancy guard (e.g., a modifier or a state variable) to the withdraw function to prevent reentrant calls.

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract TokenManager is ... ReentrancyGuard { // Inherit from ReentrancyGuard
// ... (other code, constructor) ...
function withdraw(address _tokenAddress, TokenBalanceType _tokenBalanceType) external whenNotPaused nonReentrant {
// ... (rest of the function logic) ...
}
// ... (other functions) ...
}
Updates

Lead Judging Commences

0xnevi Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-TokenManager-withdraw-userTokenBalanceMap-not-reset

Valid critical severity finding, the lack of clearance of the `userTokenBalanceMap` mapping allows complete draining of the CapitalPool contract. Note: This would require the approval issues highlighted in other issues to be fixed first (i.e. wrong approval address within `_transfer` and lack of approvals within `_safe_transfer_from` during ERC20 withdrawals)

Support

FAQs

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