Platform: Code4rena
Start Date: 02/10/2023
Pot Size: $1,100,000 USDC
Total HM: 28
Participants: 64
Period: 21 days
Judge: GalloDaSballo
Total Solo HM: 13
Id: 292
League: ETH
Rank: 60/64
Findings: 1
Award: $95.22
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: erebus
Also found by: 0xTheC0der, Bauchibred, HE1M, Jorgect, Udsen, alexfilippov314, chaduke, evmboi32, hash, ladboy233, lsaudit, oakcobalt, rvierdiiev, ustas, wangxx2026, xuwinnie, zero-idea, zkrunner
95.2225 USDC - $95.22
[[1]] Function MsgValueSimulator._getAbiParams()
comment claims that the flag that determines whether or not the call should be a system one is stored in the first ABI param. But this flag is actually stored in the third ABI param.
/// @notice Extract value, isSystemCall and to from the extraAbi params. /// @dev The contract accepts value, the callee and whether the call should a system one via its ABI params. /// @dev The first ABI param contains the value in the [0..127] bits. The 128th contains /// the flag whether or not the call should be a system one. /// The second ABI params contains the callee. function _getAbiParams() internal view returns (uint256 value, bool isSystemCall, address to) { value = SystemContractHelper.getExtraAbiData(0); uint256 addressAsUint = SystemContractHelper.getExtraAbiData(1); uint256 mask = SystemContractHelper.getExtraAbiData(2); isSystemCall = (mask & MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT) != 0; to = address(uint160(addressAsUint)); }
[[2]] The require statement in the L1Messenger.publishPubdataAndClearState
doesn't check anything. But it seems that there is no way to utilize it somehow because of the chainedMessageHash
check.
require(numberOfL2ToL1Logs <= numberOfL2ToL1Logs, "Too many L2->L1 logs");
[[3]] The bootloader.yul
contains the string literal "Failed publish timestamp data to L1"
that exceeds the 32-byte limit for string literals in Yul. The attempt to compile bootloader.yul
with the solc
compiler leads to the following error:
Error: String literal too long (35 > 32) --> proved_batch.yul:2433:30: | 2433 | debugLog("Failed publish timestamp data to L1", 0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Consider making this string shorter to avoid any possible runtime issues and ensure that your codebase maintains as much compatibility with the Solidity compiler whenever possible.
[[4]] The bootloader.yul
contains the call to the ZKSYNC_NEAR_CALL_callPostOp
with the trailing comma. The attempt to compile this code with solc
leads to the compilation error since it is not correct according to Yul syntax.
pop(ZKSYNC_NEAR_CALL_callPostOp( // Maximum number of gas that the postOp could spend nearCallAbi, paymaster, txDataOffset, success, // Since the paymaster will be refunded with reservedGas, // it should know about it safeAdd(gasLeft, reservedGas, "jkl"), ))
Error: Literal or identifier expected. --> proved_batch.yul:1414:25: | 1414 | )) | ^ Error: Expected keyword "data" or "object" or "}". --> proved_batch.yul:1414:25: | 1414 | )) | ^
Consider removing the trailing comma and ensure that your codebase maintains as much compatibility with the Solidity compiler whenever possible.
[[5]] There is a typo in the following comment in the Mailbox.requestL2Transaction
. Words "the ability to provide"
appear twice.
// VERY IMPORTANT: nobody should rely on this constant to be fixed and every contract should give their users the ability to provide the // ability to provide `_l2GasPerPubdataByteLimit` for each independent transaction. // CHANGING THIS CONSTANT SHOULD BE A CLIENT-SIDE CHANGE.
[[6]] There are a couple of comments where ergs
is used instead of gas
. It can be confusing since these comments don't correspond to code.
[[7]] There are a lot of places in the docs where ergs
is used instead of gas
. It can be confusing since this text doesn't correspond to code.
[[8]] Function validateUint32
comment in the bootloader.yul
is misleading. The function accepts a uint256
. Also, this function is not being used.
/// @dev Accepts an uint32 and returns whether or not it is /// a valid uint64 function validateUint64(x) -> ret { ret := lt(x, shl(64,1)) }
[[9]] Function validateUint128
comment in the bootloader.yul
is misleading. The function accepts a uint256
and returns whether or not it is a valid uint128
.
/// @dev Accepts an uint32 and returns whether or not it is /// a valid uint64 function validateUint128(x) -> ret { ret := lt(x, shl(128,1)) }
[[10]] It looks like this value can be precomputed.
bytes32 domainSeparator = keccak256( abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256("zkSync"), keccak256("2"), block.chainid) );
#0 - bytes032
2023-10-30T10:21:58Z
2 l 7 nc
[[1]] Function MsgValueSimulator._getAbiParams() comment claims that the flag that determines whether or not the call should be a system one is stored in the first ABI param. But this flag is actually stored in the third ABI param. nc
[[2]] The require statement in the L1Messenger.publishPubdataAndClearState doesn't check anything. But it seems that there is no way to utilize it somehow because of the chainedMessageHash check. dup of https://github.com/code-423n4/2023-10-zksync-findings/issues/853
[[3]] The bootloader.yul contains the string literal "Failed publish timestamp data to L1" that exceeds the 32-byte limit for string literals in Yul. The attempt to compile bootloader.yul with the solc compiler leads to the following error: nc
[[4]] The bootloader.yul contains the call to the ZKSYNC_NEAR_CALL_callPostOp with the trailing comma. The attempt to compile this code with solc leads to the compilation error since it is not correct according to Yul syntax. dup of https://github.com/code-423n4/2023-10-zksync-findings/issues/952
[[5]] There is a typo in the following comment in the Mailbox.requestL2Transaction. Words "the ability to provide" appear twice. nc
[[6]] There are a couple of comments where ergs is used instead of gas. It can be confusing since these comments don't correspond to code. nc
[[7]] There are a lot of places in the docs where ergs is used instead of gas. It can be confusing since this text doesn't correspond to code. nc
[[8]] Function validateUint32 comment in the bootloader.yul is misleading. The function accepts a uint256. Also, this function is not being used. nc
[[9]] Function validateUint128 comment in the bootloader.yul is misleading. The function accepts a uint256 and returns whether or not it is a valid uint128. d
[[10]] It looks like this value can be precomputed. nc
#1 - lsaudit
2023-12-03T04:39:47Z
Hey, I checked this report and I think that two issues are invalid.
One of this is a duplicate.
(7) states, that docs contains ergs
instead of gas
. Since ergs
is in the docs, it's reasonable, that (6) uses ergs
instead of gas
in the code, to be compliant with the documentation.
I think that both issues should be merged into one, because both of them reporting that ergs
name may be confusing.
Imho, it's invalid. block.chainid
is being used to calculate domainSeparator. This value will be different on different chains, thus cannot be precomputed.
However, if I'm wrong, then it should be in Gas report and not in QA.
#2 - GalloDaSballo
2023-12-10T18:57:39Z
You can pre-compute the domain separator then compare against the cached, it's a common pattern
#3 - GalloDaSballo
2023-12-10T18:57:57Z
Keeping as is
#4 - c4-judge
2023-12-10T20:18:52Z
GalloDaSballo marked the issue as grade-b