Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

ZkSync Era does not have native support for transferring Ether

Summary

The protocol has multiple functions with low-level calls that are supposed to transfer Ether. However, ZkSync Era does not have native support for transferring Ether, so deployment to ZkSync requires additional considerations.

Vulnerability Details

Dussehra utilizes low-level calls (indicated with "@> below) to directly transfer Ether in the following functions:

function killRavana() public RamIsSelected {
if (block.timestamp < 1728691069) {
revert Dussehra__MahuratIsNotStart();
}
if (block.timestamp > 1728777669) {
revert Dussehra__MahuratIsFinished();
}
IsRavanKilled = true;
uint256 totalAmountByThePeople = WantToBeLikeRam.length * entranceFee;
totalAmountGivenToRam = (totalAmountByThePeople * 50) / 100;
@> (bool success, ) = organiser.call{value: totalAmountGivenToRam}("");
require(success, "Failed to send money to organiser");
}
function withdraw() public RamIsSelected OnlyRam RavanKilled {
if (totalAmountGivenToRam == 0) {
revert Dussehra__AlreadyClaimedAmount();
}
uint256 amount = totalAmountGivenToRam;
@> (bool success, ) = msg.sender.call{value: amount}("");
require(success, "Failed to send money to Ram");
totalAmountGivenToRam = 0;
}

However, ZkSync does not have support for such direct Ether transfers, see the documentation at:

  • https://docs.zksync.io/build/developer-reference/differences-with-ethereum.html#call-staticcall-delegatecall

  • https://docs.zksync.io/zk-stack/components/smart-contracts/system-contracts.html#l2ethtoken-msgvaluesimulator

  • https://docs.zksync.io/zk-stack/components/compiler/specification/system-contracts.html#ether-value-simulator

Instead, Ether transfers on ZkSync are handled by a special system contract called MsgValueSimulator.

Further details on how this work is available here: https://www.rollup.codes/zksync-era

"CALL Creates a new sub-context and executes the code of the given account. The OPCODE does not support sending ether natively If not compiled with zk-solc or zk-vyper, Ether must be sent using a system contract MsgValueSimulator prior to executing the CALL opcode. zk-solc and zk-vyper compilers inject the call to the system contract under the hood during compilation. ... "

Impact

The impact depends on the compilation:

  • if the contract is compiled with zk-solc or zk-vyper, there is no impact, as Ether transfer through CALL is handled automatically by the compiler, which injects calls to the MsgValueSimulator system contract.

  • if the contract is not compiled with zk-solc or zk-vyper, Dussehra::killRavana and Dussehra::withdraw will not work on ZkSync, provided that the code is not adjusted.

Tools Used

Manual review.

Recommendations

  • compile the contract using zk-solc for zkSync (so that you can use the CALL opcode directly without manually invoking the MsgValueSimulator,

or

  • to ensure compatibility across all environments, check the chainID and explicitly use the MsgValueSimulator for zkSync.

Updates

Lead Judging Commences

bube Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.