Tadle

Tadle
DeFiFoundry
27,750 USDC
View results
Submission Details
Severity: high
Invalid

Wrong receiver for wrapped native token in the TokenManager::withdraw

Summary

TokenManager::withdraw function transfers wrapped native tokens to the TokenManager contract instead of the caller (msg.sender).

Vulnerability Details

In the TokenManager::withdraw function, if the token to be withdrawn is the native token, the wrapped native tokens are transferred to the address(this) (TokenManager contract). However, the documentation stipulates that those funds should be transferred to the msg.sender from capitalPoolAddr to msg.sender.

File: src/core/TokenManager.sol#L153-L170
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 {

Below is the TokenManger::_transfer function :

File: src/coreTokenManager.sol#L233-L262
function _transfer(
address _token,
address _from,
address _to,
uint256 _amount,
address _capitalPoolAddr
) internal {
uint256 fromBalanceBef = IERC20(_token).balanceOf(_from);
uint256 toBalanceBef = IERC20(_token).balanceOf(_to);
if (
_from == _capitalPoolAddr &&
IERC20(_token).allowance(_from, address(this)) == 0x0
) {
ICapitalPool(_capitalPoolAddr).approve(address(this));
}
@--> _safe_transfer_from(_token, _from, _to, _amount);
uint256 fromBalanceAft = IERC20(_token).balanceOf(_from);
uint256 toBalanceAft = IERC20(_token).balanceOf(_to);
if (fromBalanceAft != fromBalanceBef - _amount) {
revert TransferFailed();
}
if (toBalanceAft != toBalanceBef + _amount) {
revert TransferFailed();
}
}

This means that when withdrawing users withdraw tokens, wrapped native tokens are sent to the TokenManager contract instead of the caller.

Impact

When calling the TokenManager::withdraw function, if the token to be withdrawn is the native token, the caller will not receive their wrapped native tokens. Those funds will be stuck in the TokenManger contract.

Tools Used

Manual review.

Recommendations

Change the receiver to msg.sender instead of address(this) at TokenManager#L163.

Updates

Lead Judging Commences

0xnevi Lead Judge
12 months ago
0xnevi Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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