zkSync Era - alexfilippov314's results

Future-proof zkEVM on the mission to scale freedom for all.

General Information

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

zkSync

Findings Distribution

Researcher Performance

Rank: 60/64

Findings: 1

Award: $95.22

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

95.2225 USDC - $95.22

Labels

bug
grade-b
QA (Quality Assurance)
Q-07

External Links

[[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));
}

https://github.com/code-423n4/2023-03-zksync/blob/21d9a364a4a75adfa6f1e038232d8c0f39858a64/contracts/DefaultAccount.sol#L102-L103

[[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");

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/system-contracts/contracts/L1Messenger.sol#L206C15-L206C15

[[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.

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/system-contracts/bootloader/bootloader.yul#L2516

[[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.

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/system-contracts/bootloader/bootloader.yul#L1428-L1437

[[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.

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/zksync/facets/Mailbox.sol#L254-L256

[[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))
}

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/system-contracts/bootloader/bootloader.yul#L3164C19-L3164C19

[[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))
}

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/system-contracts/bootloader/bootloader.yul#L3170

[[10]] It looks like this value can be precomputed.

bytes32 domainSeparator = keccak256(
    abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256("zkSync"), keccak256("2"), block.chainid)
);

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/system-contracts/contracts/libraries/TransactionHelper.sol#L138

#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.

[6], [7]

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.

[10]

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

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter