Tadle

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

Deny Of Service : Unable to receive native tokens

Summary

Possible DOS (Deny Of Service), contract unable to receive native tokens when using withdraw() function in TokenManager.sol, because there is neither :
a receive() external payable function, nor a fallback() external payablefunction in the TokenManager.sol contract.

Vulnerability Details

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

Those 2 lines of code cause problem :

IWrappedNativeToken(wrappedNativeToken).withdraw(claimAbleAmount);
payable(msg.sender).transfer(claimAbleAmount);

In the withdraw() function from TokenManager.sol :

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
);
}


withdraw(claimAbleAmount) will try to send native tokens (unwrapped native tokens) to the TokenManager contract, but since it doesn't have a receive() payable function nor a fallback() payable function, this will throw an error. This contract will not be able to receive the native tokens and won't get to the next line of code that was supposed to
send those native tokens to msg.sender.
This is a Deny Of Service.


Here is the "unwrapping" function from the wrappNative token contract:

function withdraw(uint wad) public {
require(balanceOf[msg.sender] >= wad);
balanceOf[msg.sender] -= wad;
msg.sender.transfer(wad);
Withdrawal(msg.sender, wad);
}

POC (Proof Of Concept)

1) Add an arbitrary amount of native tokens with :

function tillIn(address _accountAddress, address _tokenAddress, uint256 _amount, bool _isPointToken)

via createOffer()::PreMarkets.sol.

2) Try to withdraw the native tokens with :

function withdraw(address _tokenAddress, TokenBalanceType _tokenBalanceType)

=> Result : The transaction fails.

Impact

The user calling the withdraw() function won't be able to receive his native tokens because the contract is not able to receive native tokens. Deny Of Service.

Tools Used

Foundry, VisualCode.

Recommendations

Mitigation:

Add a receive() external payable function or a fallback() external payable function to fix the issue.

Updates

Lead Judging Commences

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

[invalid] finding-TokenManager-no-native-ETH-receive

Invalid, TokenManager is the implementation contract of 9the transparent upgradeable proxy, as can seen by the comments [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/proxy/UpgradeableProxy.sol#L15). The receive payable is implemented as seen [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/proxy/UpgradeableProxy.sol#L37)

Support

FAQs

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