Skip to main content

Guide: Depositing funds L1 to L2

This guide provides a complete walkthrough for depositing funds from a L1 (Ethereum) to a L2 (ZKsync). We will use the @dutterbutter/zksync-sdk to simplify the process. The SDK intelligently handles the deposit flow, automatically selecting the correct contract and route based on the token being used.

Prerequisites

Before you begin, ensure you have the following:
  1. Node.js v20+ or Bun.sh installed.
  2. An L1 wallet (private key) with some ETH to pay for the deposit and gas fees.
  3. RPC endpoints for both the L1 and L2 you are targeting.
  4. A project set up with viem or ethers and @dutterbutter/zksync-sdk installed.
  5. An .env file in your project’s root directory with the following variables:

The Deposit Process: Step-by-Step

The process can be broken down into 5 key steps after initial setup.

Step 0: Setup and SDK Initialization

First, we need to connect to the L1 and L2 networks using your preferred library (viem or ethers) and then initialize the ZKsync SDK.

Step 1: Define Deposit Parameters

Next, define the parameters for your deposit in an object. You’ll specify the deposit amount, the token address — which can represent ETH, a chain’s Base Token (like L1_SOPH_TOKEN_ADDRESS), or any ERC-20 — and the recipient’s address on L2.
You can also specify advanced options for finer control over the transaction:
  • l2GasLimit: The gas limit for the L2 part of the transaction.
  • gasPerPubdata: The gas price per byte of public data.
  • operatorTip: A tip for the L2 operator.
  • refundRecipient: An address to receive any L1 gas refunds.

Step 2: Quote the Deposit

Before sending, it’s best practice to get a cost estimate using sdk.deposits.quote. This returns information about fees and the expected gas required.
Users can skip this step and go directly to create, but quoting helps avoid surprises.

Step 3: Prepare the Transaction

The sdk.deposits.prepare method builds the final transaction plan. This step is useful for inspecting the transaction details before execution.

Step 4: Create the Deposit

The sdk.deposits.create method executes the plan by sending the transaction to the L1 network. It returns a handle which is a unique identifier used to track the deposit’s progress.

Step 5: Track the Transaction Status

A deposit is a two-stage process: inclusion on L1 and then execution on L2. The SDK provides tools to track both stages.
  • sdk.deposits.status(handle): Check the current status of the deposit at any time.
  • sdk.deposits.wait(handle, options): Pause execution until the deposit reaches a specific stage.
Once the wait for L2 execution completes, your ETH has successfully been deposited to your L2 address.

Full Code Example

Here is the complete, runnable script for your reference.
For more detailed information on the methods used in this guide, see the official API reference: