Partial token malfunction could disrupt the entire withdrawal process
Description
The withdrawTokens
function is used to withdraw all of a user's tokens to claimManager
after deposits have stopped. Each token in the allWhitelistedTokens
array is transferred in an iterating loop.
In this case, all token transfers must be successful to withdraw tokens. If any token transfer fails during the withdrawal process, none of the tokens can be withdrawn.
Additionally, withdrawTokens
is the only method to withdraw tokens from the contract. This means that the entire fund could be locked in the contract if withdrawTokens
does not work correctly.
function withdrawTokens(
address _userAddress
)
external
nonReentrant
whenNotPaused
onlyClaimManager
onlyAfterDepositStop
returns (uint256[] memory withdrawnAmounts)
{
// ...
! for (uint256 i; i < allWhitelistedTokens.length; ) {
// ...
IERC20 token = IERC20(allWhitelistedTokens[i]);
! token.safeTransfer(claimManager, userBalance);
unchecked {
++i;
}
}
// ...
}
Impact
If the transfer of one of the allWhitelistedTokens
is reverted — for example, if the token is paused by its owner, the withdrawTokens
function will not work correctly. In this case, all tokens could be locked in the contract.
Recommendations
Consider implementing a function that allows users to withdraw each token individually from the contract. This approach could prevent a partial malfunction in a single token from locking up a user's entire funds.
Remediation
This issue has been acknowledged by Inference Labs, and a fix was implemented in commit 380f977a↗.