xanoutas/solidity-security-findings huggingface dataset:
There is a lack of uniformity in the overhead costs associated with publishing code.
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-03-zksync/blob/21d9a364a4a75adfa6f1e038232d8c0f39858a64/contracts/L1Messenger.sol#L29-L39
https://github.com/code-423n4/2023-03-zksync/blob/21d9a364a4a75adfa6f1e038232d8c0f39858a64/contracts/KnownCodesStorage.sol#L90-L103


# Vulnerability details

## Impact
When deploying new code, a string that's encoded using ABI (Application Binary Interface) is transmitted to Layer 1 (L1). In addition to the actual bytecode, this process necessitates an extra 64 bytes for managing the offset and length of the data.

## Proof of Concept
The provided code calculates the gas cost associated with transferring bytecode to Layer 1 (L1) in two different places, and there's a discrepancy in the calculations due to the use of different constants. In one case, it uses `BYTECODE_PUBLISHING_OVERHEAD` with a value of 100, and in the other, it uses a formula that involves 64 bytes for offset and length.
```
// Calculate how many bytes of calldata will need to be transferred to L1.
// We published the data as ABI-encoded `bytes`, so we pay for:
// - message length in bytes, rounded up to a multiple of 32
// - 32 bytes of encoded offset
// - 32 bytes of encoded length

uint256 pubdataLen;
unchecked {
    pubdataLen = ((_message.length + 31) / 32) * 32 + 64;
}
uint256 gasToPay = pubdataLen * gasPerPubdataBytes;
```
```
//  function _sendBytecodeToL1
uint256 gasToPay = (_l1PreimageBytesLen + BYTECODE_PUBLISHING_OVERHEAD) * pricePerPubdataByteInGas;
_burnGas(Utils.safeCastToU32(gasToPay));
```

## Tools Used
Manual / VsCode

## Recommended Mitigation Steps
The recommendation here is to standardize the overhead costs and utilize the `BYTECODE_PUBLISHING_OVERHEAD` constant in both calculations. This approach eliminates the presence of "magic numbers" and ensures consistency. 


The rationale behind the value of `BYTECODE_PUBLISHING_OVERHEAD` should be clearly documented where it's defined. This documentation should explain why the value is set to a specific number (e.g., 100), encompassing the 64 bytes for offset and length, as well as any additional buffer that might be involved. This clarification helps enhance code readability and maintainability.


## Assessed type

Other
Need to include proof that the verification keys aren't backdoored
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/tools/data/scheduler_key.json#L335


# Vulnerability details

##Impact
The codebase should include the TSS ceremony, or procedure used to generate the verification keys for the elliptic curve pairing verification. Particularly for the G2 elements, which should be unknown to everyone in order to keep the verification secure.

##Proof of concept
Need to checks that the data is not is not backdoored.
How were the original verificaiton keys generated? A TSS ceremony? This ceremony should be included with the key.json file so that users can trust no one backdoored the data with a known point on the elliptic (so that proofs can be forged).

https://github.com/code-423n4/2023-10-zksync/blob/main/code/contracts/tools/data/scheduler_key.json

Otherwise, trust assumptions can't be verified and the verification system could be backdoored.

For example, tornado cash includes their verification ceremony in the codebase, which can be double checked for consistency with the deployed contracts:
https://github.com/tornadocash/phase2-bn254/blob/397e170b4103045b417410afdb57e07d336cc65a/phase2/verify_tornado_ceremony/README.md?plain=1

(This is in the codebase:
https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/tools/README.md?plain=1#L1

but this is only a tool for generating the verification file, not the method used to generate the value in it.)

##Recommendations
Include the method used for generating G2 points and verification keys in the codebase. Allow other users to double check it. 




## Assessed type

Other
Unit difference between transaction encoding and bootloader memory constant
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/system-contracts/bootloader/bootloader.yul#L1847
https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/zksync/libraries/TransactionValidator.sol#L145


# Vulnerability details

## Impact
The overhead can be calculated incorrectly for some transactions and the user will get charged 32 times more in those cases than what he ought to be charged.

## Proof of Concept
The overhead is calculated as the maximum of:

1. overhead for slot
2. overhead for memory occupation in the bootloader
3. overhead for single instance circuits

`2.` is calculated like this:

$$ \text{MemoryOverhead} = \frac{\text{BatchOverhead} * \text{EncodingLength}}{\text{BootloaderMemory}} $$

In other words, the overhead for `2.` is proportional to the percentage of bootloader memory that the transaction will use. 

The issue is that in the actual implementation the units used for `EncodingLength` and `BootloaderMemory` are different. `EncodingLength` is denominated in bytes, while `BootloaderMemory` is denominated in words (32 bytes). 

Looking at the implementations:

```js
//TransactionValidator.getOverheadForTransaction
uint256 overheadForLength = Math.ceilDiv(_encodingLength * batchOverheadGas, BOOTLOADER_TX_ENCODING_SPACE);

//bootloader.getTransactionUpfrontOverhead
let overheadForLength := ceilDiv(
    safeMul(txEncodeLen, totalBatchOverhead, "ad"),
    BOOTLOADER_MEMORY_FOR_TXS()
)
```

`_encodingLength`/`txEncodeLen` are a result of `abi.encode(transaction).length` and are hence expressed in bytes. `BOOTLOADER_TX_ENCODING_SPACE/BOOTLOADER_MEMORY_FOR_TXS()` have the value `273132` in the current config. While the specific number may be subject to change, it is relevant that it is not expressed in bytes, but in words (32 bytes each). 

The number `273132` is derived from the current occupation of the word indices  `[250141...523261]` (difference is slightly off with `273120`). Note that this range is derived from my own tracing of the bootloaders memory slots with the current config, so there might be a minor error in either the configuration or my own attempt of enumerating the slots. The [docs](https://github.com/code-423n4/2023-10-zksync/blob/main/docs/Smart%20contract%20Section/System%20contracts%20bootloader%20description.md#the-actual-transactions-descriptions) state that `[252189..523261]` should be the range (difference `271072`). Either way the minor difference is negligible and does not affect the stated [#Impact](#impact). Due to the different units used, the denominator in above formula is 32 times smaller than it should be, hence calculating a 32 times larger overhead 

## Tools Used

Manual Review

## Recommended Mitigation Steps

Multiply `BOOTLOADER_TX_ENCODING_SPACE` and `BOOTLOADER_MEMORY_FOR_TXS()` by 32 when using them in the calculation. Alternatively, change those values
UNUSED RECEIVE() FUNCTION WILL LOCK ETHER IN CONTRACT
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-03-zksync/blob/01379615bc20c2926d81c0a182f1abb6e922b93a/contracts/DefaultAccount.sol#L230


# Vulnerability details

## Impact
If the intention is to make use of the Ether sent to the contract, the `receive()` function should be designed to call another function within the contract to handle and utilize the Ether. 

## Proof of Concept
However, if there is no intended use for the received Ether, it is advisable to include a `require` statement to revert the transaction, ensuring that any unexpected or unintentional Ether transfers are properly handled and don't result in Ether getting locked in the contract.

## Tools Used
Manual / VsCode

## Recommended Mitigation Steps
The `receive()` function should be structured in a way that either calls another function within the contract to utilize the received Ether or, if no such function is intended, it should include a `require` statement to revert the transaction. This ensures that all incoming Ether is handled in a controlled and intentional manner, preventing unintended consequences or locking of Ether within the contract.


## Assessed type

Other
USE SAFETRANSFER INSTEAD OF TRANSFER
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-03-zksync/blob/01379615bc20c2926d81c0a182f1abb6e922b93a/contracts/openzeppelin/token/ERC20/IERC20.sol#L41


# Vulnerability details

## Impact
Including a `require()` statement to verify the return value of token transfers is a good practice. Alternatively, utilizing mechanisms like OpenZeppelin's `safeTransfer` or `safeTransferFrom` is advisable unless there is a high level of certainty that the involved token will revert in case of transfer failure. Failing to implement these checks can result in unreported transfer failures, impacting token accounting within the contract and potentially leading to unexpected behavior.

## Proof of Concept
Certain tokens may not adhere to the ERC20 standard properly, yet they are commonly accepted by most code that is designed to work with ERC20 tokens. For instance, the "Tether (USDT)" token's `transfer()` and `transferFrom()` functions do not return boolean values as the ERC20 specification dictates. Instead, they have no return value. When these non-standard tokens are typecast to the ERC20 interface (`IERC20`), their function signatures do not align with the expected ERC20 functions, causing any calls made to them to result in reversion.

This discrepancy highlights the importance of confirming that tokens used in a contract conform to the ERC20 standard, as deviations can lead to contract failures and unintended consequences. Additionally, developers should exercise caution and adapt their code to account for these variations when interacting with non-standard tokens.

```
  function transfer(address to, uint256 amount) external returns (bool);

```

## Tools Used
Manual

## Recommended Mitigation Steps
Consider using safeTransfer/safeTransferFrom or require() consistently.


## Assessed type

Context
Unsafe use of `unwrap()` can provide with highly altered panic and further disruption at contract execution level
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/matter-labs/era-zkevm_circuits/blob/main/src/storage_application/mod.rs#L71-L75


# Vulnerability details

## Summary

The storage_application/mod.rs code makes use of the `unwrap()` method without checking if the underlying value is `None`. This could lead to a panic at runtime, terminating the CA's execution unexpectedly.

## Vulnerability Detail

The `unwrap()` method is used on the `Option` and `Result` types to extract their contained values. If the `Option` is `None` or the `Result` is an `Err`, `unwrap()` will cause a panic. Panicking in a CA can have unpredictable side-effects, including the risk of loss of funds or disruption of CA execution.

## Impact

Any user or CA that triggers a condition where an `unwrap()` call is made on a `None` or `Err` value could cause the CA to panic and stop execution. This can lead to unexpected behaviors and possible loss of funds.

## Proof of Concept

To reproduce this, one should input a block of data where the specified condition `(i + keccak256::LANE_WIDTH * j) < (keccak256::KECCAK_RATE_BYTES / keccak256::BYTES_PER_WORD)` does not hold true for any value of `i` and `j`. This will cause the `unwrap()` to panic when it encounters a `None` value.

## Tools Used

Manual review + GPT for further text enhancements.

## Recommended Mitigation Steps

Always check the value of an `Option` or `Result` before unwrapping. Consider using methods like `is_some()`, `is_none()`, `is_ok()`, or `is_err()` to ensure safety. Alternatively, use `unwrap_or()`, `unwrap_or_default()`, or pattern matching to handle eventual error conditions gracefully.

Given the structure of the surrounding code, specifically this condition:

```rust
if i + keccak256::LANE_WIDTH * j
 < (keccak256::KECCAK_RATE_BYTES / keccak256::BYTES_PER_WORD)
```

it appears the intention is to ensure that we don't attempt to unwrap if it's not safe to do so. However, relying solely on this condition may not be foolproof. 

To be safer, consider employing more direct error handling mechanisms. For instance, instead of using `unwrap()`, you could use pattern matching or other methods to handle the `Option` returned by `next()`:

```rust
if let Some(tmp) = block
.array_chunks::<{ keccak256::BYTES_PER_WORD }>()
.skip(i + keccak256::LANE_WIDTH * j)
.next() {
    // process the tmp value
} else {
    // handle the case where there's no next item
}
```

This approach allows to gracefully handle situations where there's no next item in the iterator, without causing a panic.








## Assessed type

Error
Low Impact Issues / QA report
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

##Low Impact issues

I'm putting together these low impact issues / typos that I found. 
I accidentally already submitted one, so I can't resubmit unless I mark them as medium (please fix).


##Issue 1
Specs incorrectly define change to affine coordinates.

https://github.com/code-423n4/2023-10-zksync/blob/main/docs/Smart%20contract%20Section/Elliptic%20curve%20precompiles.md#ecmul

The first transform is (homogenous to affine) is written as (x,y) = (X.Z^{-1} , Y.Z^{-1} ) but should involve 3 coordinates going from $(x,y,z) \to (x.z^{-1} , y.z^{-1})$ (no equal sign).

##Issue 2

Spec is incorrect - it is possible to distinguish the contract from an EOA from execution

https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/contracts/DefaultAccount.sol#L43

The check will produce extra gas consumption during execution. So it possible to distinguish the behavior from an EOA account through execution alone.

##Issue 3
No withdrawal limit corresponding to deposit limit.

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

Seems weird to have. If deposit limit is there for safety reasons, then withdrawal limit should be there as well.
Alternatively, if this is unecessary, then why do we need the deposit limit?

If anything is going to break in a negative way (bridge hack), than it is probably the withdrawal limit, so that should be included instead.




## Assessed type

Other
A malicious governance admin can instantly execute delayed proposals by manipulating Operations 
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/governance/Governance.sol#L167


# Vulnerability details

## Impact
There are 2 stakeholders in a governance contract -> 1. admin 2. Security Council. Key difference between the two is the ability to execute planned upgrades (admin) v/s the ability to make instant upgrades (security council). 

However, due to a lack of adequate validations, it is possible for an admin to usurp the rights of the security council and acquire the instant upgradeability power onto themselves. In effect, this would give the Zk Sync admin the power to execute instant upgrades, a big risk to the trustless ethos of the ZK Sync eco-system. 

Of course, the credibility of Zk-sync admin is at stake here but relying on that credibility just increases trust assumptions of the chain. The current back-door theoretically allows the admin to manipulate timelines of proposals, which is both risky and undesirable to users. Since this is an admin related trust assumptions issue, I have marked it as medium-risk


## Proof of Concept
Here is how the attack can be executed:

- Admin creates a proposal with a single call and minimum delay (say 1 day for this example)
- Create call with `target: address(governance), value: 0, data: abi.encodeWithSelector(bytes4(keccak256("updateSecurityCouncil(address)")), address(admin))`
- Create operation with above call, predecessor and salt as bytes(0)
- Call `scheduleTransparent` with delay = minimum allowed delay
- After the delay gets completed, call `Governance::execute`
- Now the security council is updated to `admin`, call `Governance::executeInstant` to pass all pending proposals instantly

Attached is a POC written in foundry. Run the `test_create_execute_updateCouncil` function

```
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console2} from "forge-std/Test.sol";
import {Governance} from "../src/Governance.sol";
import {IGovernance} from "../src/interfaces/IGovernance.sol";
import "forge-std/Test.sol";

contract GovernanceTest is Test {
    Governance public governance;

    address admin;
    address secCouncil;
    uint256 minDelay;


    function setUp() public {
        admin = address(678888888); //admin has delayed execution right
        secCouncil = address(76666666); // sec council has immediate execution right
        minDelay = 1 days; //-n delay for execution by admin
        governance = new Governance(admin, secCouncil, minDelay);
    }
    function test_create_execute_updateCouncil() public{
        bytes memory callData = abi.encodeWithSelector(bytes4(keccak256("updateSecurityCouncil(address)")), admin); 
        (bytes32 delayedOperationId, IGovernance.Operation memory operationInfo) = _scheduleDelayedOperation(address(governance), 1 days, callData);    //delay equal to minDelay

        vm.warp(1 days + 100); // roll forward 1 day + 100 days to exec
There is a discrepancy/mismatch between the parameters defined in the code that are not actually used.
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-03-zksync/blob/01379615bc20c2926d81c0a182f1abb6e922b93a/contracts/DefaultAccount.sol#L217
https://github.com/code-423n4/2023-03-zksync/blob/01379615bc20c2926d81c0a182f1abb6e922b93a/contracts/interfaces/IAccount.sol#L44


# Vulnerability details

## Impact
Unused parameters within the "DefaultAccount.sol" contract can potentially lead to issues if they were to be utilized in the future. In the provided code links, there are parameters defined in the contract at Line 217 and in the associated interface "IAccount.sol" at Line 44, but these parameters do not appear to be used in the current implementation.

## Proof of Concept
The problem with unused parameters lies in the possibility of future code modifications or maintenance. If someone inadvertently attempts to utilize these parameters or assumes they serve a specific function, it can result in unintended behavior, bugs, or even security vulnerabilities.

## Tools Used
Manual / VsCode

## Recommended Mitigation Steps
Replace _suggestedSignedHash to _possibleSignedHash.


## Assessed type

Context
Lack of Input Validation in SystemContractHelper Library and SystemContractHelper library functions
Audit: 2023-10-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-03-zksync//blob/main/contracts/libraries/SystemContractHelper.sol#L48
https://github.com/code-423n4/2023-03-zksync//blob/main/contracts/libraries/SystemContractHelper.sol#L94
https://github.com/code-423n4/2023-03-zksync//blob/main/contracts/libraries/SystemContractHelper.sol#L106
https://github.com/code-423n4/2023-03-zksync//blob/main/contracts/libraries/SystemContractHelper.sol#L147
https://github.com/code-423n4/2023-03-zksync//blob/main/contracts/libraries/SystemContractHelper.sol#L85


# Vulnerability details

## Impact
The SystemContractHelper library within a smart contract is deficient in input validation for certain functions, which exposes the contract to the risk of unintended behavior and security vulnerabilities.

## Proof of Concept
The absence of input validation in the functions within the SystemContractHelper library introduces several vulnerabilities. In the "toL1" function, there's a lack of validation for the "_isService" parameter, potentially leading to an incorrect value being assigned. Similarly, the "ptrAddIntoActive" and "ptrShrinkIntoActive" functions do not validate the "_value" and "_shrink" parameters, respectively, which could result in unexpected behavior if these values go beyond the allowed limits. Additionally, the "precompileCall" function doesn't validate the "_rawParams" parameter, creating the risk of out-of-bounds memory access and other vulnerabilities if an attacker supplies invalid values. These vulnerabilities should be addressed to enhance the security and robustness of the library's functions.

```
    function toL1(bool _isService, bytes32 _key, bytes32 _value) internal {
```

```
  function ptrAddIntoActive(uint32 _value) internal view {
```

```
  function ptrShrinkIntoActive(uint32 _shrink) internal view {
```

```
 function precompileCall(uint256 _rawParams, uint32 _gasToBurn) internal view returns (bool success) {
```

```
  function ptrPackIntoActivePtr(uint256 _farCallAbi) internal view {
```


## Tools Used
Manual / VsCode

## Recommended Mitigation Steps
A recommended course of action is to introduce input validation checks to the functions in the SystemContractHelper library. This is a proactive measure to avert unexpected behaviors and potential vulnerabilities. For instance, in the "toL1" function, it is advisable to validate the "_isService" parameter to ensure it's a boolean value. In a similar vein, the "ptrAddIntoActive" and "ptrShrinkIntoActive" functions should include validation for the "_value" and "_shrink" parameters to confirm they fall within the permissible range. Furthermore, the "precompileCall" function must have input validation for the "_rawParams" parameter to thwart the risk of out-of-bounds memory access and other potential vulnerabilities. Implementing these checks will fortify the security and reliability of the library's functions.


## Assessed type

Invalid Validation