Summary
The FeeCollector contract incorrectly implements the SafeERC20 library function call in the emergencyWithdraw function, attempting to call safeTransfer as a static function. This implementation will fail to compile as it violates the intended usage pattern of the SafeERC20 library.
Vulnerability Details
The current implementation attempts to call SafeERC20's safeTransfer function directly:
function emergencyWithdraw(address token) external override whenPaused {
if (!hasRole(EMERGENCY_ROLE, msg.sender)) revert UnauthorizedCaller();
if (token == address(0)) revert InvalidAddress();
uint256 balance;
if (token == address(raacToken)) {
balance = raacToken.balanceOf(address(this));
raacToken.safeTransfer(treasury, balance);
} else {
balance = IERC20(token).balanceOf(address(this));
SafeERC20.safeTransfer(IERC20(token), treasury, balance);
}
emit EmergencyWithdrawal(token, balance);
}
The contract only declares using SafeERC20 for IRAACToken but attempts to use it with IERC20.
Impact
The emergencyWithdraw function for non-RAAC tokens is broken.
Recommendations
Add proper library usage declaration:
+ using SafeERC20 for IERC20;
Modify the emergencyWithdraw function to use the correct calling pattern:
function emergencyWithdraw(address token) external override whenPaused {
if (!hasRole(EMERGENCY_ROLE, msg.sender)) revert UnauthorizedCaller();
if (token == address(0)) revert InvalidAddress();
uint256 balance;
if (token == address(raacToken)) {
balance = raacToken.balanceOf(address(this));
raacToken.safeTransfer(treasury, balance);
} else {
balance = IERC20(token).balanceOf(address(this));
- SafeERC20.safeTransfer(IERC20(token), treasury, balance);
+ IERC20(token).safeTransfer(treasury, balance);
}
emit EmergencyWithdrawal(token, balance);
}