Centralization risk in withdrawal
Description
The withdrawTokens
function is used to withdraw all of a user's tokens to claimManager
after deposits have stopped. The address of the claimManager
can be set by the owner using the setClaimManager
function.
There is a possibility that withdrawals may not be delivered to the user because the claimManager
can be changed at any time, even if the user has verified that it is set correctly before depositing.
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;
}
}
// ...
}
function setClaimManager(address _newClaimManager) external onlyOwner {
if (_newClaimManager == address(0)) {
revert ZeroAddress();
}
// Set the new claim manager
claimManager = _newClaimManager;
emit ClaimManagerSet(_newClaimManager);
}
Impact
A malicious or compromised owner could potentially drain the contract.
Recommendations
Ensure that the ownership of the contract and the reliability of the claimManager
are prominently documented, so users are aware of and accept the associated risks.
Remediation
According to Inference Labs's response, they plan to implement a withdraw method in a future claim-manager contract where users will be able to withdraw their funds. For now, the expected functionality for the deposit contract is to pass user funds up to the claim-manager contract, which will handle their tokens as per functionality implemented in the future.