code-423n4 / 2023-10-zksync-findings

4 stars 0 forks source link

Unverified operator-provided base fee in the playground batch can be manipulated. #413

Closed c4-submissions closed 11 months ago

c4-submissions commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/bootloader/bootloader.yul#L3656 https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/bootloader/bootloader.yul#L3667 https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/bootloader/bootloader.yul#L3680

Vulnerability details

Impact

The operator provides the base fee in the playground batch. This is not verified and could be manipulated.

Proof of Concept

The design of the playground batch allowing unverified override of the base fee leaves it open to potential manipulation.

The unverified base fee provided by the operator in the playground batch. https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/bootloader/bootloader.yul#L3656

/// @notice The expected base fee by the operator. 
/// While calculated on the bootloader side,
/// the operator still provides it to make sure that its data is in sync.
let EXPECTED_BASE_FEE := mload(192)

In the playground batch, this EXPECTED_BASE_FEE is set as the base fee without further verification: https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/bootloader/bootloader.yul#L3667

https://github.com/code-423n4/2023-10-zksync/blob/72f5f16ed4ba94c7689fe38fcb0b7d27d2a3f135/code/system-contracts/bootloader/bootloader.yul#L3680

baseFee, GAS_PRICE_PER_PUBDATA := getBaseFee(L1_GAS_PRICE, FAIR_L2_GAS_PRICE)

unsafeOverrideBatch(NEW_BATCH_TIMESTAMP, NEW_BATCH_NUMBER, EXPECTED_BASE_FEE)

The unsafeOverrideBatch method allows the operator to arbitrarily override the base fee and other batch parameters.

In contrast, the proved batch enforces that the calculated base fee matches the expected base fee:

baseFee, GAS_PRICE_PER_PUBDATA := getBaseFee(L1_GAS_PRICE, FAIR_L2_GAS_PRICE)

if (baseFee != EXPECTED_BASE_FEE) {
  assertionError("baseFee inconsistent") 
}

setNewBatch(PREV_BATCH_HASH, NEW_BATCH_TIMESTAMP, NEW_BATCH_NUMBER, EXPECTED_BASE_FEE) 

So the playground batch allows the base fee to be manipulated while the proved batch verifies it on-chain. This could allow the operator to arbitrarily increase the base fee in the playground batch.

Tools Used

Manual review

Recommended Mitigation Steps

Assessed type

Governance

c4-pre-sort commented 1 year ago

bytes032 marked the issue as low quality report

miladpiri commented 1 year ago

It is playground.

c4-sponsor commented 1 year ago

miladpiri (sponsor) disputed

c4-judge commented 11 months ago

GalloDaSballo marked the issue as unsatisfactory: Invalid