The UnwrapAndSendETH
contract is designed to receive WETH and unwrap it into ETH before sending it to a specified address.
Its a helper contract for Pipeline, although it can also be used by other contracts & users.
However, there are several issues:
The contract doesn't validate the to address, it lacks access control and it doesn't handle data properly if a contract
sends data with the WETH.
Additionally, there is a dev comment "
/// @dev Make sure to load WETH into this contract before calling this function
"
Which suggests there will be a balance of WETH in the contract before the unwrap function is called.
OK first, lets ascertain the importance of validating the to address. If the to address is a contract,
and its assumed the recipient is an EOA, then sending native tokens in this fashion is fine. However,
if the recipient is a contract, then the contract must be able to handle the incoming ETH. This is nullified
if the contract for example has been destroyed via self-destruct or not deployed. The call will return successful
even if no transfer was executed. This will lead to a loss of funds.
Ref the below Uniswap report under report 9.
https://github.com/Uniswap/v3-core/blob/main/audits/tob/audit.pdf
Another issue to be weary of is a returnbomb of gas placed on the UnwrapAndSendETH
contract. Without going into the
technical details of this, this essentially means that the to address can return a huge amount of data once invoked
by the low level .call method, which gets copied into memory. This can lead to a DOS attack.
Here is an example below
This can be mitigated by using this library for example:
https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol
The contract itself lacks access control, which means once, according to the dev comment, WETH is
loaded into the contract, an attacker can drain the entire balance, simply by viewing the balance of
address(this) before calling the unwrap function.
Finally, the contract doesn't handle data in transactions. If data is sent through to the UnwrapAndSendETH
function from the
Pipeline contract for example or even directly from another smart contract, the UnwrapAndSendETH
contract is designed to only receive
ETH via the receive() external payable {}
.
If a contract needs to send calldata
, you should facilitate this by implementing the fallback function, as detailed
in the solidity docs.
https://docs.soliditylang.org/en/v0.8.9/contracts.html?highlight=receive#receive-ether-function
Individually each of these components can lead to loss of funds due to lack of
contract existence or direct draining of funds, plus the additional DOS via returnbomb.
Manual Review
To deal with the lack of validation of the to address, you can implement a check to ensure the contract
is not self-destructed or not deployed. Make sure its also not the address(0).
Use the https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol
library to deal with the potential of a returnbomb gas attack.
Place appropriate access controls to prevent unauthorized access to the contract.
Consider implementing a fallback function to handle calldata
in transactions with sending ETH.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.