Skip to content
Request an audit

‹ All findings

Potential ETH Loss Due to transfer Usage in Requestor Contract on zkSync

MediumPoolTogether Prize Layer·Sherlock · Raffle · 16th May 2024CodebaseM-7

Summary

  • The Requestor contract uses transfer to send ETH which has the risk that it will not work if the gas cost increases/decrease(low Likelihood), but it is highly likely to fail on zkSync due to gas limits. This may make users' ETH irretrievable.

Vulnerability Detail

  • Users (or bots) interact with RngWitnet to request a random number and start a draw in the DrawManager contract. To generate a random number, users must provide some ETH that will be sent to WitnetRandomness to generate the random number.
js
    function startDraw(uint256 rngPaymentAmount, DrawManager _drawManager, address _rewardRecipient) external payable returns (uint24) {
            (uint32 requestId,,) = requestRandomNumber(rngPaymentAmount);
            return _drawManager.startDraw(_rewardRecipient, requestId);
    }
  • The ETH sent with the transaction may or may not be used (if there is already a request in the same block, it won't be used). Any remaining or unused ETH will be sent to Requestor, so the user can withdraw it later.
  • The issue is that the withdraw function in the Requestor contract uses transfer to send ETH to the receiver. This may lead to users being unable to withdraw their funds .
js
 function withdraw(address payable _to) external onlyCreator returns (uint256) {
        uint256 balance = address(this).balance;
 >>       _to.transfer(balance);
        return balance;
 }
  • The protocol will be deployed on different chains including zkSync, on zkSync the use of transfer can lead to issues, as seen with 921 ETH Stuck in zkSync Era.since it has a fixed amount of gas 23000 which won't be anough in some cases even to send eth to an EOA, It is explicitly mentioned in their docs to not use the transfer method to send ETH here.
notice that in case msg.sender is a contract that have some logic on it's receive or fallback function the ETH is definitely not retrievable. since this contract can only withdraw eth to it's own addres which will always revert.

Impact

  • Draw Bots' ETH may be irretrievable or undelivered, especially on zkSync, due to the use of .transfer.

Code Snippet

Tool used

Manual Review , Foundry Testing

Recommendation

  • recommendation to use .call() for ETH transfer.