Potential ETH Loss Due to transfer Usage in Requestor Contract on zkSync
Summary
- The Requestor contract uses
transferto sendETHwhich has the risk that it will not work if the gas cost increases/decrease(low Likelihood), but it is highly likely to fail onzkSyncdue to gas limits. This may make users'ETHirretrievable.
Vulnerability Detail
- Users (or bots) interact with RngWitnet to request a random number and start a draw in the
DrawManagercontract. To generate a random number, users must provide someETHthat will be sent to WitnetRandomness to generate the random number.
function startDraw(uint256 rngPaymentAmount, DrawManager _drawManager, address _rewardRecipient) external payable returns (uint24) {
(uint32 requestId,,) = requestRandomNumber(rngPaymentAmount);
return _drawManager.startDraw(_rewardRecipient, requestId);
}- The
ETHsent 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 unusedETHwill be sent to Requestor, so the user can withdraw it later. - The issue is that the
withdrawfunction in theRequestorcontract usestransferto sendETHto the receiver. This may lead to users being unable to withdraw their funds .
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, onzkSyncthe use oftransfercan lead to issues, as seen with 921 ETH Stuck in zkSync Era.since it has a fixed amount of gas23000which won't be anough in some cases even to send eth to anEOA, It is explicitly mentioned in their docs to not use thetransfermethod to sendETHhere.
notice that in casemsg.senderis a contract that have some logic on it's receive or fallback function theETHis definitely not retrievable. since this contract can only withdraw eth to it's own addres which will always revert.
Impact
- Draw Bots'
ETHmay 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()forETHtransfer.