Transaction Lifecycle

An in-depth guide on the transaction lifecycle within the ZK Stack, explaining the roles of the sequencer and prover, and detailing the transaction statuses and types in ZKsync Era.

The ZK Stack facilitates the launch of rollups, which require certain operators like the sequencer and the prover. These operators are responsible for creating blocks and proofs, and submitting them to the L1 contract.

Transactions are cryptographically signed instructions from accounts that aim to update the state of the Ethereum network. The simplest transaction involves transferring ETH from one account to another. Learn more about Ethereum transactions.


Workflow of Transactions

Users submit their transactions to the sequencer, whose role is to collect and execute these transactions using the zkEVM. The sequencer also provides a soft confirmation to users about the execution of their transactions. Users have the option to force the inclusion of their transactions by submitting them through L1. After execution, the sequencer forwards the block to the prover, who then creates a cryptographic proof of the block's execution. This proof, along with the necessary data, is submitted to the L1 contract. An L1 smart contract verifies the validity of the proof and the completeness of the data submission, thereby updating the rollup's state on the contract.

Components

The zkEVM plays a crucial role similar to, yet distinct from, the traditional EVM in Ethereum. Transactions can also be initiated via L1, which facilitates L1<>L2 communication, providing censorship resistance and enabling trustless bridges to L1.

The sequencer collects transactions into blocks and, to enhance user experience, ensures quick soft confirmations through small block sizes. Unlike Ethereum, zkEVM distinguishes between blocks and batches, where batches—collections of blocks—are processed by the prover.

Before submitting a proof, the data is sent to L1. The method optimizes data submission by detailing only the changes in blockchain state, termed 'state diff.' This approach makes transactions affecting the same storage slots more cost-effective.

At the final stage, proofs are generated and sent to L1 using our Boojum proof system, which operates efficiently on 16GB of GPU RAM, allowing for decentralization of proof generation.


Transaction data

Transactions in ZKsync Era are comparable to those on Ethereum, allowing the use of the same wallets. Minor differences exist, particularly regarding fee settings. For details on fees, refer to the fee model documentation.

Returned values from any RPC call outputting transaction details include:

  • is_l1_originated: bool
  • status: TransactionStatus, one of Pending, Included, Verified, or Failed. See Transaction statuses section below.
  • fee: U256. See the fee mechanism documentation for more information.
  • initiator_address: Address
  • received_at: DateTime<Utc>
  • eth_commit_tx_hash: Option<H256>
  • eth_prove_tx_hash: Option<H256>
  • eth_execute_tx_hash: Option<H256>

Contract Deployment Transactions

Contract deployment transactions interact with the ContractDeployer system contract and differ from standard transactions.

Learn more about contract deployment in ZKsync.


Transaction statuses

Transactions are always in one of the following statuses:

  • Pending: Awaiting inclusion in a block.
  • Included: Added to a block, but the block's batch is not yet committed.
  • Verified: Included and verified after batch commitment and execution on the Ethereum L1 network.
  • Failed: Transaction did not verify successfully.

For more on transaction completion and irrevocability, see the finality documentation.


Transaction types

ZKsync Era supports a range of transaction types that are compatible with Ethereum, yet they incorporate unique settings particularly around fee configurations. Here’s a detailed look at the transaction types, including legacy, EIP-2930, EIP-1559, and EIP-712, and how they are implemented in ZKsync Era.

When using RPC methods like eth_getTransactionByHash, the transaction type hex value is included in the output.

Legacy: 0x0

This is the original Ethereum transaction format used before the introduction of typed transactions.

EIP-2930: 0x1

Implemented to mitigate risks introduced by EIP-2929, EIP-2930: Optional access lists adds an accessList to transactions, which is an array of addresses and storage keys.

EIP-1559: 0x2

Introduced in Ethereum's London update, EIP-1559: Fee market change for ETH 1.0 chain modifies how transaction fees are handled, replacing gasPrice with a base fee and allowing users to set maxPriorityFeePerGas and maxFeePerGas.

  • maxPriorityFeePerGas: Maximum fee users are willing to pay miners as an incentive.
  • maxFeePerGas: Overall maximum fee, including the maxPriorityFeePerGas and the base fee determined by the network.
In ZKsync Era, while the EIP-1559 transaction format is supported, the maxFeePerGas and maxPriorityFeePerGas parameters are not utilized.

EIP-712: 0x71

EIP-712: Typed structured data hashing and signing enables structured data hashing and signing within transactions. ZKsync Era uses this for features like account abstraction and paymasters.

"gasPerPubdata": "1212",
"customSignature": "0x...",
"paymasterParams": {
  "paymaster": "0x...",
  "paymasterInput": "0x..."
},
"factoryDeps": ["0x..."]
  • gasPerPubdata: Specifies the maximum gas payable per byte of public data.
  • customSignature: For transactions where the account is not an externally owned account (EOA).
  • paymasterParams: Configuration for custom paymasters, including address and inputs.
  • factoryDeps: Includes bytecode of contracts for deployment, essential for factory contracts.

EIP-712 transactions are designated with a transaction_type of 113 due to the one-byte limit, differing from 712.

Instead of signing the RLP-encoded transaction, the user signs the following typed EIP-712 structure:

  • txType: uint256
  • from: uint256
  • to: uint256 -gasLimit: uint256
  • gasPerPubdataByteLimit: uint256
  • maxFeePerGas: uint256
  • maxPriorityFeePerGas: uint256
  • paymaster: uint256
  • nonce: uint256
  • value: uint256
  • data: bytes
  • factoryDeps: bytes32[]
  • paymasterInput: bytes

These fields are handled by our SDKs.

Priority: 0xff


Each of these transaction types ensures that while ZKsync Era remains closely aligned with Ethereum standards, it also optimizes for its Layer 2 specific needs and functionalities.


Made with ❤️ by the ZKsync Community