ZKsync Gateway settlement layer
ZKsync Gateway is an optional settlement layer for ZKsync chains, including both rollups and validiums. It is purpose-built to enhance interoperability, provide proof aggregation, and offer cost efficiencies for chains that wish to settle on top of it.
Learn more about ZKsync Gateway in the protocol documentation.
Running ZKsync Gateway locally
zkstackup
and the required system dependencies installed as detailed in the quickstart.- Update
foundry-zksync
to use the version from commit27360d4c8
:foundryup-zksync -C 27360d4c8
- Install the latest version of
zkstack
:zkstackup
- Create a new local ecosystem and chain, and start the containers with Docker running the background:
zkstack ecosystem create
- Move into the ecosystem folder and initialize the ecosystem:
cd <YOUR_ECOSYSTEM> zkstack ecosystem init --dev
- Create a new ZKsync chain that will become your local gateway chain:
zkstack chain create \ --chain-name gateway \ --chain-id 506 \ --prover-mode no-proofs \ --wallet-creation localhost \ --l1-batch-commit-data-generator-mode rollup \ --base-token-address 0x0000000000000000000000000000000000000001 \ --base-token-price-nominator 1 \ --base-token-price-denominator 1 \ --set-as-default false \ --evm-emulator false \ --ignore-prerequisites --update-submodules false
- Initialize
gateway
chain:zkstack chain init \ --deploy-paymaster \ --l1-rpc-url=http://localhost:8545 \ --server-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ --server-db-name=zksync_server_localhost_gateway \ --chain gateway --update-submodules false
- Setup the transaction filterer for
gateway
:zkstack chain gateway create-tx-filterer --chain gateway --ignore-prerequisites
- Transform
gateway
chain from rollup into a ZKsync Gateway settlement layer:zkstack chain gateway convert-to-gateway --chain gateway --ignore-prerequisites
- Start
gateway
chain server:zkstack server --ignore-prerequisites --chain gateway
Or to start the server in the background, use:mkdir zlogs zkstack server --ignore-prerequisites --chain gateway &> ./zlogs/gateway.log & zkstack server wait --ignore-prerequisites --verbose --chain gateway
- Migrate existing ZKsync chain to settle on
gateway
:zkstack chain gateway migrate-to-gateway --chain <YOUR_CHAIN_NAME> --gateway-chain-name gateway
- Start your chain server:
zkstack server --ignore-prerequisites --chain <YOUR_CHAIN_NAME>
Your chains will be running on the following ports:
- Your chain (271 or the chain ID you defined):
localhost:3050
- Gateway (506):
localhost:3150
Multichain Local Setup
Once you have completed the steps in the previous section, you may want to test interoperability across different chains. To add an additional chain that settles on Gateway, follow these steps:
- Create a new chain. You can change any details about the chain as needed.
zkstack chain create \ --chain-name zk_chain_2 \ --chain-id 5328 \ --prover-mode no-proofs \ --wallet-creation localhost \ --l1-batch-commit-data-generator-mode rollup \ --base-token-address 0x0000000000000000000000000000000000000001 \ --base-token-price-nominator 1 \ --base-token-price-denominator 1 \ --set-as-default false \ --evm-emulator true \ --ignore-prerequisites --update-submodules false
- Initialize the new chain. Make sure the chain name matches the one you created in the previous step.
zkstack chain init \ --deploy-paymaster \ --l1-rpc-url=http://localhost:8545 \ --server-db-url=postgres://postgres:notsecurepassword@localhost:5432 \ --server-db-name=zksync_server_localhost_zk_chain_2 \ --chain zk_chain_2 \ --update-submodules false
- Migrate the new chain to
gateway
:zkstack chain gateway migrate-to-gateway --chain zk_chain_2 --gateway-chain-name gateway
- Start the new chain server:
zkstack server --ignore-prerequisites --chain zk_chain_2
Now you should have three chains running on the following ports:
- Your first chain (271 or the chain ID you defined):
localhost:3050
- Gateway (506):
localhost:3150
zk_chain_2
(5328):localhost:3250
To get funds for testing, you can use the dev rich-account
command below to bridge testnet ETH to your new chain:
zkstack dev rich-account --chain zk_chain_2
Migrate existing ZKsync chain to Gateway on testnet or mainnet
ZKsync chains can be migrated to use ZKsync Gateway as their settlement layer by updating the chain's metadata and
coordinating the transition with off-chain services.
This migration is performed using the zkstack cli
tool.
Requirements
In order to migrate a chain, operators will need the following information:
- Tooling:
- zkstack CLI
- Foundry
- Credentials:
- Private key of the L2 network chain governor.
- RPC URLs for all the networks involved:
- Ethereum and L2 network to migrate.
- ZKsync Gateway: more info in ZKsync Gateway overview.
- Addresses:
L1_BRIDGEHUB_ADDRESS
: can be found in the ZKsync chains info pageREFUND_RECIPIENT_ADDRESS
: address that will receive gas refunds.VALIDATOR_1_ADDRESS
: address of the operator.VALIDATOR_2_ADDRESS
: address of the blob operator.NEW_SL_DA_VALIDATOR
: data availability contract validator deployed on Gateway. See data availability considerations for more info
- Chain identifiers:
L2_CHAIN_ID
: id of the L2 network to migrate.GATEWAY_CHAIN_ID
: more info in ZKsync Gateway overview.
- ZKsync Gateway configuration: the ZKsync Stack config file for the ZKsync Gateway, which contains relevant information of how the chain operates.
This file can be found in the zksync-era repository.
Save in
etc/ecosystem/gateway/<gateway>.yaml
.
Notify server about migration
Pause the ETH transaction sender on the server to avoid having unconfirmed transactions on L1:
zkstack chain gw notify-about-to-gateway-update-calldata \
<L1_BRIDGEHUB_ADDRESS> \
<L2_CHAIN_ID> \
<L1_RPC_URL> \
--l2-rpc-url=<L2_RPC_URL> \
--gw-rpc-url=<GATEWAY_RPC_URL>
Send migration calldata on L1
Send the generated migration calldata to L1
cast send <L1_BRIDGEHUB_ADDRESS> <CALLDATA> \
--rpc-url=<L1_RPC_URL> \
--private-key=<PRIVATE_KEY>
Generate calldata for migration
The following command will check the status of the migration to Gateway and will only output the calldata after the notification has passed
and the server is ready to migrate.
To prepare the calldata even before the server is ready (helpful for multisigs), please provide --no-cross-check
option.
Governor must have enough ZK to top up validators (min-validator-balance).
zkstack chain gw migrate-to-gateway-calldata \
--l1-rpc-url <L1_RPC_URL> \
--l1-bridgehub-addr <L1_BRIDGEHUB_ADDRESS> \
--max-l1-gas-price <MAX_L1_GAS_PRICE> \
--gateway-chain-id <GATEWAY_CHAIN_ID> \
--gateway-rpc-url <GATEWAY_RPC_URL> \
--refund-recipient <REFUND_RECIPIENT_ADDRESS> \
--l2-chain-id <L2_CHAIN_ID> \
--l2-rpc-url <L2_RPC_URL> \
--gateway-config-path <GATEWAY_CONFIG_PATH> \
--validator-1 <VALIDATOR_1_ADDRESS> \
--validator-2 <VALIDATOR_2_ADDRESS> \
--min-validator-balance <MIN_VALIDATOR_BALANCE> \
--new-sl-da-validator <NEW_SL_DA_VALIDATOR>
This will generate L1 → Gateway transaction. The L2 network server will restart 2 times:
- When the gateway status changed on L1.
- When the transaction is processed on ZKsync Gateway.
Submit final migration transaction
Send the output calldata from previous step to L1 to confirm migration:
cast send <TO_ADDRESS> <CALLDATA> \
--rpc-url=<L1_RPC_URL> \
--private-key=<PRIVATE_KEY>
Verify migration
Check that settlementLayer(chainId)
on the
Bridgehub contract
returns the ZKsync Gateway chain id:
506
(testnet) or 9075
(mainnet).
CLI Reference
For more information about commands and calldata generation details, refer to the official zkstack cli migration guide.