zkSync Era - BARW'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: 18/64

Findings: 1

Award: $4,574.05

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: minhtrng

Also found by: BARW, HE1M, Koolex, rvierdiiev

Labels

bug
2 (Med Risk)
downgraded by judge
low quality report
satisfactory
edited-by-warden
duplicate-1108

Awards

4574.0453 USDC - $4,574.05

External Links

Lines of code

https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/zksync/libraries/TransactionValidator.sol#L36-L43

Vulnerability details

Impact

Transactions where the gasLimit is too low to cover both the overhead gas cost on L2 and the gas cost to execute the transaction on L2 will pass the safety checks on L1 and will be send to L2. On L2 the transaction will fail because the gasLimit is too low. This results in wasting the users gas on L1 and not accomplishing what the user wanted to do with the transaction in the first place, forcing him to send the transaction again and pay even more gas on L1.

Proof of Concept

When requesting a L2 Transaction in Mailbox.sol and thereby writing the PriorityOp, the function TransactionValidator ::validateL1ToL2Transaction() is called to ensure, amongst other things, that transaction.gasLimit is set high enough to cover both the overhead gas cost on L2 and the gas cost on L2 that accrue when the transaction is processed. For this purpose, first the overhead gas cost are deducted from transaction.gasLimit resulting in l2GasForTxBody, the gasLimit available for processing the transaction itself. Then the minimum cost for processing the transaction is calculated and compared to transaction.gasLimit.

require( getMinimalPriorityTransactionGasLimit( _encoded.length, _transaction.factoryDeps.length, _transaction.gasPerPubdataByteLimit ) <= _transaction.gasLimit, "up" );

The problem is that the amount of gas needed to execute the transaction itself is compared to the total gasLimit given by the user that also includes the gas cost for overhead. This means that as long as transaction.gasLimit is >= the cost for processing the transaction, this check will pass even if transaction.gasLimit is to low to cover both overhead gas cost and processing gas cost. Example: Transaction.gasLimit = 10 gasCostForOverhead = 5 gasCostForProcessingTxn = 10 totalGasCost = 10 + 5 = 15 => gasLimit to low to cover all gas cost but the check still passes becasue Transaction.gasLimit is >= gasCostForProcessingTxn.

This means that the transaction will be send to L2. There it will not be executed and fail since the gas limit will not be enough to cover both the gas cost for overhead and the gas cost for executing the transaction.

Tools Used

Manual review

Compare the gasCostForProcessingTxn ( MinimalPriorityTransactionGasLimit) to l2GasForTxBody

require( getMinimalPriorityTransactionGasLimit( _encoded.length, _transaction.factoryDeps.length, _transaction.gasPerPubdataByteLimit ) <= _l2GasForTxBody, "up" );

Assessed type

Other

#0 - c4-pre-sort

2023-11-01T08:02:06Z

bytes032 marked the issue as low quality report

#1 - miladpiri

2023-11-09T08:09:36Z

Duplicate.

#2 - c4-judge

2023-11-26T15:00:56Z

GalloDaSballo marked the issue as duplicate of #975

#3 - c4-judge

2023-11-28T12:43:41Z

GalloDaSballo changed the severity to 2 (Med Risk)

#4 - c4-judge

2023-11-28T15:54:08Z

GalloDaSballo marked the issue as satisfactory

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