Tadle

Tadle
DeFi
30,000 USDC
View results
Submission Details
Severity: low
Invalid

payable(msg.sender).transfer(claimAbleAmount) Method in `TokenManager::withdraw` Function

Description

The payable(msg.sender).transfer(claimAbleAmount) method is used in the TokenManager::withdraw function to transfer native tokens (e.g., Ether) to the caller. While this method is simple and straightforward, it comes with certain limitations, especially regarding gas limits and the risk of unexpected reverts. The transfer method sends a fixed amount of 2300 gas to the recipient, which may not be sufficient if the recipient is a contract with a complex receive or fallback function. This could lead to failed transactions, even if the funds are available for transfer.

function withdraw(address _tokenAddress, TokenBalanceType _tokenBalanceType) external whenNotPaused {
uint256 claimAbleAmount = userTokenBalanceMap[_msgSender()][_tokenAddress][_tokenBalanceType];
if (claimAbleAmount == 0) {
return;
}
address capitalPoolAddr = tadleFactory.relatedContracts(RelatedContractLibraries.CAPITAL_POOL);
if (_tokenAddress == wrappedNativeToken) {
/**
* @dev token is native token
* @dev transfer from capital pool to msg sender
* @dev withdraw native token to token manager contract
* @dev transfer native token to msg sender
*/
_transfer(wrappedNativeToken, capitalPoolAddr, address(this), claimAbleAmount, capitalPoolAddr);
IWrappedNativeToken(wrappedNativeToken).withdraw(claimAbleAmount);
@>>>> payable(msg.sender).transfer(claimAbleAmount);
} else {
/**
* @dev token is ERC20 token
* @dev transfer from capital pool to msg sender
*/
_safe_transfer_from(_tokenAddress, capitalPoolAddr, _msgSender(), claimAbleAmount);
}
emit Withdraw(_msgSender(), _tokenAddress, _tokenBalanceType, claimAbleAmount);
}

Impact

Using the transfer method can result in:

  1. Failed Transactions: If the recipient is a contract that requires more than 2300 gas to execute its receive or fallback function, the transaction will revert, causing the withdrawal to fail.

  2. Unexpected Reverts: Even if the transaction appears valid, unexpected reverts can occur due to the gas limit, leading to a poor user experience.

  3. Limited Flexibility: The transfer method does not allow for custom error handling or dynamic gas management, reducing the control over how funds are transferred and how failures are managed.

Tools Used

Manual Review

Recommendations

Replace payable(msg.sender).transfer(claimAbleAmount) with payable(msg.sender).call{value: claimAbleAmount}(""). The .call method provides greater flexibility and control over gas usage and allows for more robust error handling. Specifically, it allows specifying the gas amount and capturing any returned data or errors, making it more suitable for interacting with complex contracts or handling large transfers.

if (_tokenAddress == wrappedNativeToken) {
_transfer(wrappedNativeToken, capitalPoolAddr, address(this), claimAbleAmount, capitalPoolAddr);
IWrappedNativeToken(wrappedNativeToken).withdraw(claimAbleAmount);
- payable(msg.sender).transfer(claimAbleAmount);
+ (bool success, ) = payable(msg.sender).call{value: claimAbleAmount}("");
+ require(success, "Transfer failed");
}
Updates

Lead Judging Commences

0xnevi Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

[invalid] finding-TokenManager-withdraw-transfer-2300-gas

Invalid, known issues [Medium-2](https://github.com/Cyfrin/2024-08-tadle/issues/1)

Support

FAQs

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