Lucene search

K
code423n4Code4renaCODE423N4:2023-03-ZKSYNC-FINDINGS-ISSUES-158
HistoryMar 19, 2023 - 12:00 a.m.

bootloader doesn't add tighter gas limit to the IAccount.validateTransaction call

2023-03-1900:00:00
Code4rena
github.com
4
bootloader
gas limit
dos threat
verification
transaction
operators

Lines of code

Vulnerability details

Impact

As mentioned in the competition details: *Important, while the bootloader is out of scope, we may reward an additional bounty for valid bugs found in it by our judgement!

As mentioned in the dev document, <https://era.zksync.io/docs/dev/developer-guides/aa.html#limitations-of-the-verification-step&gt;, there are some limitations of the verification are designed to protect the system from a DoS threat. The verification rules are not fully enforced right now. But at present, the tx verification step and the tx execution step share the same gas limit (max to the MAX_GAS_PER_TRANSACTION config).

Bootloader doesn’t add tighter gas limit to the verification, which is mainly IAccount.validateTransaction call. It will make all other limitation rules meaningless, because the attacker can force the bootloader to execute the garbage codes continuously in the verification process until the MAX_GAS_PER_TRANSACTION gas is used up. This makes it become possible to DOS the operators because any gas cost in the verification will be revert if the verification result is invalid.

Proof of Concept

The call flow for the transaction verification in the bootloader is:

processL2Tx -&gt; l2TxValidation -&gt; ZKSYNC_NEAR_CALL_validateTx -&gt; accountValidateTx -&gt; callAccountMethod -&gt; IAccount.validateTransaction

The gas limit passed to the IAccount.validateTransaction call is defined in the processL2Tx function by getGasLimitForTx:

                let gasLimitForTx := getGasLimitForTx(innerTxDataOffset, transactionIndex, gasPerPubdata, L2_TX_INTRINSIC_GAS(), L2_TX_INTRINSIC_PUBDATA())

The main logic is that:

let operatorTrustedErgsLimit := max(MAX_GAS_PER_TRANSACTION(), getOperatorTrustedGasLimitForTx(transactionIndex))
totalGasLimit := min(operatorTrustedErgsLimit, totalGasLimit)

And the getOperatorTrustedGasLimitForTx is like cal the estimateGas rpc call for a tx. So if your tx used for DOS attack is designed as reverting forever which make it return noting as trusted gas limit, or it has to cost huge amounts of gas which make it return a large enough gas limit, the final gas limit will be MAX_GAS_PER_TRANSACTION() - some intrinsic costs and overhead. The tx verification and the tx execution step share the same gas limit (max to the MAX_GAS_PER_TRANSACTION config).It’s 80000000 in the current SystemConfig.json, which is large enough to DOS the operator.

Tools Used

Manual review

Recommended Mitigation Steps

Bootloader should add tighter gas limit to the IAccount.validateTransaction call


The text was updated successfully, but these errors were encountered:

All reactions