# Basic Concepts

# Operations

There are two types of operations in zkSync:

  1. Priority operations
  2. Transactions

# Priority operations

Priority operations are initiated directly on the Ethereum mainnet. For example, the user creates a deposit transaction to move funds from Ethereum to zkSync. A priority operation can be identified with a numeric ID or hash of the ethereum transaction that created it.

Currently, there are the following types of priority operations:

  • Deposit: Moves funds from the Ethereum network to the designated account in the zkSync network. If the recipient account does not exist yet on the zkSync network, it will be created and a numeric ID will be assigned to the provided address.
  • FullExit: Withdraws funds from the zkSync network to the Ethereum network without interacting with the zkSync server. This operation can be used as an emergency exit in case of detected censorship from the zkSync server node, or to withdraw funds in the situation where the signing key for an account in zkSync network cannot be set (e.g. if the address corresponds to a smart contract).

# Transactions

Transactions must be submitted via zkSync operator using the API.

Transactions are identified by the hash of their serialized representation.

Currently, there are the following types of transactions:

  • ChangePubKey: Sets (or changes) the signing key associated with the account. Without a signing key set, no operation (except for priority operations) can be authorized by the corresponding account.
  • Transfer: Transfers funds from one zkSync account to another zkSync account. If the recipient account does not exist yet on the zkSync network, it will be created and a numeric ID will be assigned to the provided address.
  • Swap: Atomically swaps funds between two existing zkSync accounts.
  • Withdraw: Withdraws funds from the zkSync network to the Ethereum network.
  • ForcedExit: Withdraws funds from the "target" L2 account that doesn't have a signing key set, to the same "target" address on the Ethereum network. This operation can be used to withdraw funds in the situation where the signing key for account in zkSync network cannot be set (e.g. if address corresponds to a smart contract).
  • MintNFT: Mints an NFT based on provided content hash to the provided "recipient".
  • WithdrawNFT: Withdraw an NFT from the zkSync network to the Ethereum network.

# Blocks

All operations inside zkSync are arranged in blocks. After zkSync operator creates a block, it is pushed to the zkSync smart contract on the Ethereum mainnet with a Commit transaction. When a block is committed, its state is not yet final. After a couple of minutes, the ZK proof for the correctness of this block is produced. This proof is published on Ethereum using the Verify transaction. Only after the Verify tx was mined, the new state is considered final. Multiple blocks can be committed but not verified yet.

However, the execution model is slightly different: in order to not make users wait for the block finalization, transactions are grouped into "mini-blocks" with a much smaller timeout. So, the blocks are being partially applied with a small interval, so that shortly after receiving the transaction it is executed and L2 state is updated correspondingly.

It means that after sending a transaction, the user has to wait for neither block commitment nor verification, and transferred funds can be used immediately after corresponding transaction execution.

# Flow

This section describes typical use-cases of zkSync in a sequential manner.

# Creating an account

Accounts in zkSync can be created by either doing a deposit of funds from Ethereum or by transferring funds in zkSync to the desired address. Any of these options will create a new account in the zkSync network if it doesn't exist.

However, newly created accounts are not capable of authorizing any transactions from it yet. In order to do so, the account owner must set the signing key for their account.

# Setting the signing key

By default, the signing key for each account is set to the zero value, which marks account as "unowned". It's a requirement because of the following reasons:

  • If a transfer to some address is valid in Ethereum, it's also valid in zkSync.
  • Not every address can have a private key (e.g. some smart contracts).
  • Transfers to a user's account may happen before they've been interested in zkSync.

Thus, in order to make an account capable of initiating L2 transactions, the user must set a signing key for it via ChangePubKey transaction.

This transaction has to have two signatures:

  • zkSync signature of the transaction data, so that it won't be possible to mutate transaction contents.
  • Ethereum signature proving account ownership.

Ethereum signature should be a signature of some pre-defined message. Also, it is possible to authorize ChangePubKey operation on-chain by sending a corresponding transaction to the zkSync smart contract. Ownership of account will be checked by both zkSync server and smart contract for better security guarantees.

The zkSync signature on all transaction fields must correspond to the public key provided in the transaction.


To keep the default Layer-2 private key different among different networks, the message that the user signs depends on the network of the Ethereum provider of the user's wallet.

That's why if your solution supports multiple chains (for example mainnet & goerli), please make sure that the user is signing ChangePubKey only after the transition to the correct network. Otherwise, the user will have ChangePubKey-related errors when he'll try to use zkWallet or other zkSync products and may pay for CPK one more time.

# Example of network validation

try {
    await window.ethereum.request({
        method: "wallet_switchEthereumChain",
        params: [{ chainId: ethereumChainId }],
} catch (e) {
    throw new Error("Wrong chain. Cannot sign in.");

# Transferring funds

As mentioned above, any transfer that is valid in Ethereum, is also valid in zkSync.

Users may transfer any amount of funds in either Ether or any supported ERC-20 token. A list of supported tokens can be found on the corresponding explorer page (opens new window). It is also exposed via API.

However, transfer to a non-existent account requires slightly more data to be sent on the smart contract (we have to include information about the new account), thus the fee for such transfers is slightly higher than the fee for transfers to existing accounts.

# Fees

zkSync requires fees for transactions in order to cover expenses for network maintenance.

Fees for each kind of transaction are calculated based on three main factors:

  • Amount of data that will be sent to the Ethereum network.
  • Current gas price.
  • Cost of computational resources to generate a proof for a block with the transaction.

Since we include many transactions in one block, the cost is amortized among all the included transactions, which results in very small fee values.

Additionally, our API provides all the input data used for fee calculation via corresponding API method.

# Withdrawing funds

Currently, there are three ways to withdraw funds from zkSync to an Ethereum account.

First one is Withdraw transaction.

It is an L2 transaction that can be used to request a withdrawal from your account to any Ethereum address. Same way as transfers, it has to be signed by the correct zkSync private key.

This method is preferred for situations when you own your account and have a private key for it.

Second one is ForcedExit transaction.

It is an L2 transaction that can be used to request a withdrawal from any unowned account (one that does not have a signing key set). Neither Ethereum address nor amount can be chosen in this transaction: the only option is to request a withdrawal of all available funds of a certain token from the target L2 address to the target L1 address.

Also, the transaction initiator should cover the fee, which is exactly the same as for Withdraw operation.

This method is preferred if funds should be withdrawn from an account that cannot set the signing key (i.e. smart contract account), and there exists an L2 account which can send this type of transaction.

Third one is FullExit priority operation.

This kind of operation is called a "priority operation" since it's initiated from L1 and the smart contract provides guarantees that either this request will be processed within a reasonable time interval, or network will be considered compromised / dead, and the contract will enter an exodus mode.

This method is preferred if the user will ever experience censorship from the network operator.