Summary
The Rescuable::rescue function in the smart contract allows the owner to recover tokens or native currency from the contract. However, the function does not include a check to ensure that the to address is non-zero. This omission can lead to funds being sent to the zero address, resulting in a loss of tokens or Ether.
Vulnerability Details
The rescue function is defined as follows:
function rescue(
address to,
address token,
uint256 amount
) external onlyOwner {
if (token == address(0x0)) {
payable(to).transfer(amount);
} else {
_safe_transfer(token, to, amount);
}
emit Rescue(to, token, amount);
}
The function allows the contract owner to transfer Ether or tokens from the contract to a specified to address. However, there is no check to ensure that the to address is valid and not the zero address (address(0x0)).
Proof Of Concept
If the to address is mistakenly set to the zero address, the following issues may arise:
@> Ether Transfer: If `token == address(0x0)`, the contract will attempt to transfer Ether to the zero address, effectively burning the Ether.
@> Token Transfer: If `token != address(0x0)`, the `_safe_transfer` function will attempt to transfer tokens to the zero address, which might be interpreted as burning the tokens depending on the token contract's implementation.
Impact
The absence of a zero address check in the rescue function could lead to a significant loss of assets:
@> Irrecoverable Loss: Ether or tokens sent to the zero address are effectively lost, as they cannot be recovered by any means.
@> Unexpected Behavior: Sending tokens to the zero address might trigger unintended behavior in certain token contracts, leading to further complications.
Tools Used
Recommended Mitigation
To prevent the loss of funds due to transfers to the zero address, the following mitigation should be implemented:
Add a Zero Address Check
Before proceeding with the transfer, add a check to ensure that the `to` address is not the zero address. If the check fails, the function should revert with an appropriate error message.
function rescue(
address to,
address token,
uint256 amount
) external onlyOwner {
+ require(to != address(0x0), "Invalid address: zero address");
if (token == address(0x0)) {
payable(to).transfer(amount);
} else {
_safe_transfer(token, to, amount);
}
emit Rescue(to, token, amount);
}