Getting Started with ZK Chains

Create and run your first ZK chain.

In this tutorial, you will get familiar with the ZK Inception CLI. You will create a local Elastic Chain ecosystem and deploy a contract to a ZK chain. Next, you will create a new ZK chain that uses a custom ERC20 base token.

What you'll learn:

  • How to create and locally run an Elastic Chain ecosystem.
  • How to create a ZK chain and deploy a contract to it.
  • How to setup a ZK chain with a custom base token.
GitHub

Tools:

  • - zk_inception
  • - hardhat
  • - cast
  • - zksync-cli
  • - zksync-ethers
elastic chainzk chaintutorial
Last Updated: Aug 14, 2024

This tutorial shows you how to use the zk_inception CLI to run an Elastic Chain ecosystem and custom ZK chain locally:

  • You'll set up a local Elastic Chain ecosystem
  • You'll create a standard ZK chain
  • You'll deploy a smart contract to your local ZK chain
  • You'll create a second ZK chain that uses a custom ERC20 base token

Prerequisites

  • Make sure your machine satisfies the system requirements.
  • If you aren't already familiar with deploying smart contracts on ZKsync Era, please refer to the first section of the quickstart tutorial.
  • For background on the Elastic Chain or ZK chains, read the ZK chains section in our docs.
  • Install the dependencies for the zksync-era repo by following the instructions in the matter-labs/zksync-era project's Setup dev guide (you can skip the "Environment" section).
If you previously have foundry-zksync installed, reinstall the normal version of foundry for this tutorial.

Installing zk_inception CLI

To install the CLI globally, run this command in your root folder. You can use the Rust command cargo to install the CLI with the command below:

cargo install --git https://github.com/matter-labs/zksync-era/ \
--locked zk_inception --force
You can find a full reference for the zk_inception CLI in the zksync-era repo.

Setting up the Elastic Chain ecosystem

An Elastic Chain ecosystem is, in short, a system to manage multiple ZK chains. The vision for the Elastic Chain is an ever-expanding network of ZK rollups, secured by math and natively interoperable under a uniform, intuitive UX. New chains can be registered to the ecosystem to scale applications and communities as needed, making it "elastic".

There are two components needed for running a ZK chain locally:

  1. An Elastic Chain ecosystem to manage different chains
  2. At least one chain deployed within the ecosystem

To setup both of these components, use the zk_inception CLI.

The first step is to create a new ecosystem with the ecosystem create command.

Make sure Docker is running on your machine.

Move to a directory where you want your ecosystem folder to be, and run the command below to generate an ecosystem folder.

zk_inception ecosystem create

You will be prompted with a series of options to customize your ecosystem and generate a new chain within the ecosystem. For this tutorial, use the options shown below. If you choose different names for your ecosystem or chain, remember to update the names in the commands later on.

$ zk_inception ecosystem create

   ZKsync toolbox
  What do you want to name the ecosystem?
  my_elastic_chain
  Select the origin of zksync-era repository
  Clone for me (recommended)
  Select the L1 network
  Localhost
  What do you want to name the chain?
  zk_chain_1
  Whats the chain id?
  271
  Select how do you want to create the wallet
  Localhost
  Select the prover mode
  NoProofs
  Select the commit data generator mode
  Rollup
  Select the base token to use
  Eth
  Do you want to start containers after creating the ecosystem?
  Yes

By running this command and selecting these options, you just:

  • Created a new ecosystem called my_elastic_chain, which can contain many chains.
  • Cloned the zksync-era repository inside the my_elastic_chain folder.
  • Chose to use a local network to act as the L1. This means we'll have to run a local reth node as well (don't worry, the CLI will automatically set this up and run it for you!). We need to do this because our ecosystem contracts need to get deployed on an L1, so we can either use a local L1 chain or the Sepolia testnet. For development purposes, it's easier to use a local L1 chain.
  • Created a new chain called zk_chain_1 and set it as your default chain.
  • Set the chain id to 271.
  • Chose the default wallet configuration. This option will use known mnemonic phrases to generate the wallets.yaml configuration files for the ecosystem and chain. You can also choose random to randomly generate the wallets, empty to generate a config file with empty values for the wallets, or in-file to set the location of the config to an existing file.
  • Selected to not use proofs, which makes testing more lightweight.
  • Chose a standard rollup for the data availability. You can read more about data availability options for ZK chains in the ZK chains docs.
  • Selected ETH to use as the base token.
  • Started the containers for the ecosystem in Docker.

Inside the generated my_elastic_chain folder, you should now have the following contents:

  • ZkStack.yaml: a configuration file for the ecosystem.
  • chains: a folder with configurations for each chain created.
  • configs: configuration for the deployments and wallets.
  • volumes: dependencies for running local nodes.
  • zksync-era: a clone of the zksync-era repository.
  • docker-compose.yml: a Docker compose file to start up a local environment.

Deploying the ecosystem

You've just set up your ecosystem and chain, and have two Docker containers running: a postgres database for your chain, and a reth node for the local L1 chain.

The L1 chain is already running, but your ecosystem and chain aren't deployed yet. The next step is to deploy your ecosystem contracts to the L1 and register your chain to the ecosystem.

Move into the ecosystem folder:

cd my_elastic_chain

Next, run the ecosystem init command below to deploy the ecosystem:

zk_inception ecosystem init --dev

The --dev flag will choose the default options for development.

If you have any issues at this step, try reinstalling the dependencies at the top.

This process will take some time as there is a lot happening here. To see more detailed logs of what is happening at each step, you can add the --verbose flag to the command.

To summarize, the ecosystem init command:

  • Checks to see if your environment has the necessary dependencies.
  • Compiles and deploys all of the necessary contracts for the ecosystem.
  • Deploys zk_chain_1 to the ecosystem.
  • Sets up a database for the default chain (in this case zk_chain_1).
  • Deploys a paymaster contract and some test ERC20 contracts to use for development.

You can find the paymaster contract code deployed to your chain in the zksync-era repo in contracts/l2-contracts/contracts/TestnetPaymaster.sol, and the deployed address inside <my_elastic_chain>/chains/zk_chain_1/configs/contracts.yaml at l2:testnet_paymaster_addr.

For the ERC20 contracts, you can find the deployed addresses inside <my_elastic_chain>/configs/erc20.yaml.

Understanding the chain configs

Running the init command will also modify your chain configuration files in the ecosystem folder.

The main configuration file for zk_chain_1 can be found in <my_elastic_chain>/chains/zk_chain_1/ZkStack.yaml. It contains the most basic configurations for the chain.

Inside <my_elastic_chain>/chains/zk_chain_1/configs, you can find six more configuration files:

  1. contracts.yaml: configurations for all the L1 & L2 contracts.
  2. external_node.yaml: configurations for the chain's node server.
  3. general.yaml: general configurations.
  4. genesis.yaml: chain specific configurations with parameters that were used during genesis.
  5. secrets.yaml: secrets that are individual for every chain.
  6. wallets.yaml: all wallets that you are using for this chain.
Never commit your private keys or sensitive secrets.

Starting the chain server

The last step here is to start a server for zk_chain_1:

zk_inception server

With this, your L1 chain should be running at port 8545, and the zk_chain_1 node should be running at port 3050.

Funding a wallet on your chain

Because you chose to use a local reth node for your L1 and selected ETH as the base asset, you have access to several rich wallets on the L1 that you can use to bridge ETH to zk_chain_1.

You can find a full list of rich wallet addresses and their private keys in the ZKsync docs.

Never use these wallets in production or send real funds to them.

Open a new terminal and run the command below to bridge some ETH to zk_chain_1 using ZKsync CLI:

npx zksync-cli bridge deposit --rpc=http://localhost:3050 --l1-rpc=http://localhost:8545

For testing purposes, we'll use one of the rich wallets as both the sender and recipient:

? Amount to deposit 10
? Private key of the sender 0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110
? Recipient address on L2 0x36615Cf349d7F6344891B1e7CA7C72883F5dc049

To see that it worked, let's check the balance of that address on zk_chain_1:

npx zksync-cli wallet balance \
--address 0x36615Cf349d7F6344891B1e7CA7C72883F5dc049 \
--rpc http://localhost:3050

Now this address has ETH available on zk_chain_1 to use for testing.

Deploying a contract to chain 1

Now that your chain is deployed and your wallet is funded, let's create a template contract and deploy it to zk_chain_1:

Move out of your ecosystem folder and initialize a new hardhat project using ZKsync CLI:

npx zksync-cli@latest create --template zksync-101 zk-chain-test
cd zk-chain-test

Use the same private key for the rich wallet:

? Private key of the wallet responsible for deploying contracts (optional)
0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110

In the hardhat.config.ts file, change the default network on line 6 to dockerizedNode, which is already configured to connect to the local chain node running on port 3050:

defaultNetwork: "dockerizedNode",

Finally, compile the contract and run the deploy script:

yarn compile && yarn deploy:hello-zksync

Nice - you just deployed a contract to your own local ZK chain!

Next, let's take a look at customizing a chain.


Made with ❤️ by the ZKsync Community