NAV Navbar
typescript

Overview

ZK Sync is a scaling and privacy engine for Ethereum. Its current functionality scope includes low gas transfers of ETH and ERC20 tokens in the Ethereum network. This document is a description of the JS library that can be used to interact with ZK Sync.

ZK Sync is built on ZK Rollup architecture. ZK Rollup is an L2 scaling solution in which all funds are held by a smart contract on the mainchain, while computation and storage are performed off-chain. For every Rollup block, a state transition zero-knowledge proof (SNARK) is generated and verified by the mainchain contract. This SNARK includes the proof of the validity of every single transaction in the Rollup block. Additionally, the public data update for every block is published over the mainchain network in the cheap calldata.

This architecture provides the following guarantees:

In other words, ZK Rollup strictly inherits the security guarantees of the underlying L1.

Getting started

To use ZK Sync, users need funds in the ZK Sync network. There are two ways to obtain funds:

  1. Depositing from Ethereum network using a transaction to the ZK Sync smart contract on the mainchain.
  2. Receiving funds from anyone that already has funds in the network.

All transactions in the ZK Sync network are authorized with a signature using private keys. Public keys and addresses can be derived from the private key. Public address in the ZK Sync network is required to receive funds. For convenience, it is possible to use Ethereum private key to derive a ZK Sync private key.

All operations inside ZK Sync are arranged in blocks. After network operator creates block it gets published to Ethereum with a Commit transaction. When a block is committed, its state is not final. After a couple of minutes, ZK proof for the correctness of this block is produced. This proof is published to Ethereum using Verify transaction and after that state is considered final. Multiple blocks can be committed but not verified yet.

There are two types of operations:

  1. Priority operations
  2. Transactions

Priority operations are initiated from the Ethereum network using transactions. For example, the user creates a deposit transaction to move funds from Ethereum to ZK Sync. Priority operation can be identified with a numerical id or hash of the ethereum transaction that created it. Priority operations can't be ignored by the network.

Transactions are signed by some accounts in the ZK Sync network and should be delivered to the network operator node.

Transactions are identified by the hash of its serialized representation.

Tutorial

Here we show how to

  1. Connect to the ZK Sync network.
  2. Create a private key in the ZK Sync.
  3. Move funds from Ethereum to the ZK Sync.
  4. Make fast transfers.
  5. Move funds from the ZK Sync to Ethereum.

Adding dependencies

yarn add zksync
yarn add ethers # For interactions with ETH network

Add imports.

import * as zksync from "zksync";
import {ethers} from "ethers";

Alternatively.

const zksync = require("zksync");
const ethers = require("ethers");

Connecting to the Sync network

To interact with Sync network users have to know the endpoint of the operator node.

const syncProvider = await zksync.getDefaultProvider("testnet");

// When using WebSocket provider connection should be closed manually when needed using.
await syncProvider.disconnect();

The alternative provider is an HTTP provider.

const syncProvider = await zksync.SyncProvider.newHttpProvider("https://testnet.matter-labs.io/jsrpc");

Most operations require some read-only access to the Ethereum network. We use ethers library to interact with Ethereum.

Addresses of the Sync network contracts should be known in advance, for convenience now we can get these addresses from Sync network operator using syncProvider.

const ethersProvider = new ethers.getDefaultProvider('rinkeby');
const ethProxy = new zksync.ETHProxy(ethersProvider, syncProvider.contractAddress);

Creating Wallet

To use ZK Sync network we provide Wallet object. It can be used to sign transactions with keys stored in Signer and send transaction to the ZK Sync network using connection provided by Provider.

For convenience user can derive Sync network account from Ethereum account. Wallet secret key will be derived from signature of specific message.

// Create ethereum wallet using ethers.js
const ethWallet = ethers.Wallet.fromMnemonic( MNEMONIC ).connect(ethersProvider);
// Derive wallet from ethereum wallet.
const syncWallet = await zksync.Wallet.fromEthSigner(ethWallet, syncProvider, ethProxy);

Moving funds from ethereum to the Sync network

We are going do deposit some funds from our ethereum wallet into sync account. For that we should create specific ethereum transaction. We can create this transaction using depositFromETH function.

Here we are moving "ETH" token. To transfer supported ERC20 token we should use ERC20 address instead of "ETH".

const deposit = await zksync.depositFromETH({
    depositFrom: ethWallet,
    depositTo: syncWallet,
    token: "ETH",
    amount: ethers.utils.parseEther("1.0"),
    maxFeeInETHCurrency: ethers.utils.parseEther("0.1")
});

After transaction is submitted to the Ethereum we can track its progress using returned object.

// If we want to wait until deposit is processed by the SyncNetwork.
const depositReceipt = await deposit.awaitReceipt();

// If we want to wait until deposit is processed and finalized using ZKP.
const depositReceipt = await deposit.awaitVerifyReceipt();

Get balance in the ZK Sync network

To get balance of the ZK Sync account you can use getBalance method. Committed state is last state of the account that may or may not be finalized by ZK proof. Verified is referred to finalized by ZK proof state of the account.

const committedETHBalance = await syncWallet.getBalance("ETH");
const verifiedETHBalance = await syncWallet.getBalance("ETH", "verified");

To get all tokens of this account you can use getAccountState.

const state = await syncWallet.getAccountState();

const committedBalances = state.committed.balances;
const committedETHBalance = committedBalances["ETH"];

const verifiedBalances = state.verified.balances;
const committedETHBalance = verifiedBalances["ETH"];

Get balance in the Ethereum network

For convenience, there is a method with a similar signature that can be used to query balance in the Ethereum network.

const onchainETHBalance = await zksync.getEthereumBalance(ethWallet, "ETH");

Moving funds inside ZK Sync network

Let's create a second wallet and transfer funds to it.

const ethWallet2 = ethers.Wallet.fromMnemonic( MNEMONIC2 ).connect(ethersProvider);
const syncWallet2 = await zksync.SyncWallet.fromEthSigner(ethWallet2, syncProvider, ethProxy);

To transfer funds from one Sync account to another we can use the syncTransfer method. We are going to transfer 0.999 ETH to another account and pay 0.001 ETH as a fee to the operator.

const transfer= await syncWallet.syncTransfer({
    to: syncWallet2.address(),
    token: "ETH",
    amount: ethers.utils.parseEther("0.999"),
    fee: ethers.utils.parseEther("0.001")
});

To track progress of this transaction we can use returned transaction.

const transferReceipt = await transfer.awaitReceipt();

Moving funds out of the Sync network

To withdraw funds from Sync account to ethereum account we can use the withdrawTo method.

We are going to withdraw 0.998 ETH from the second sync account to the second ethereum wallet and pay 0.001 ETH as a fee.

const withdraw= await syncWallet2.withdrawTo({
    ethAddress: ethWallet2.address,
    token: "ETH",
    amount: ethers.utils.parseEther("0.998"),
    fee: ethers.utils.parseEther("0.001"),
});

Funds will be withdrawn to the target wallet after ZKP for sync block with this operation is produced and verified. We can wait until ZKP verification is completed using a returned transaction.

await withdraw.awaitVerifyReceipt();

Providers

JSON-RPC protocol is used to communicate with Sync network nodes. Provider is used to abstract details of the communication and provides useful API for interaction with Sync network.

We support HTTP and WebSocket transport protocol for JSON-RPC communications. WebSocket transport is preferred since it supports subscriptions. HTTPTransport and WSTransport classes are used to implement details of communication, but usually, you don't need to deal with these objects directly.

Sync provider

Get default provider for network

import * as zksync from "zksync";


const syncWSProvider = await zksync.getDefaultProvider("testnet")

// ..

// Later to close connection.
await syncWSProvider.disconnect();

Used to connect to the common endpoint for the given network over WebSocket transport.

Supported networks are: "testnet", "localhost".

Create WebSocket provider

Creating provider over WebSocket transport. This call will create WS connection that should be closed.

import * as zksync from "zksync";


const syncWSProvider = await zksync.Provider.newWebsocketProvider(
    "wss://testnet.matter-labs.io/jsrpc-ws"
);

// ..

// Later to close connection.
await syncWSProvider.disconnect();

Create HTTP provider

Creating provider over HTTP transport.

import * as zksync from "zksync";

const syncHTTPProvider = await zksync.Provider.newHttpProvider(
    "https://api-testnet.matter-labs.io:3030"
);

Submit transaction

Signature

async submitTx(tx: any): Promise<string>;

Inputs and outputs

Name Description
tx Signed Sync transaction (see types, for detailed description)
returns 0x-prefixed hex-encoded hash of the transaction

Example

import * as zksync from "zksync";

const syncWSProvider = await zksync.getDefaultProvider("testnet")
const signedTransferTx = {
    type: "Transfer",
    from: "sync:..address1",
    to: "sync:..address2",
    token: 0, // id of the ETH token
    amount: "1000000000000000000", // 1 Ether in Wei
    fee: "10000000000000000", // 0.01 Ether in Wei
    nonce: 0,
    signature: {
        pubKey: "dead..", // hex encoded packed public key of signer (32 bytes)
        signature: "beef.." // hex encoded signature of the tx (64 bytes)
    }
};


const transactionHash = await syncWSProvider.submitTx(signedTransferTx);
// 0x..hash (32 bytes)

Get contract addresses

Signature

async getContractAddress(): Promise<ContractAddress>;

Inputs and outputs

Name Description
returns Addresses of the Sync network smart contracts (see types, for detailed description)

Example

import * as zksync from "zksync";

const syncWSProvider = await zksync.SyncProvider.getDefaultProvider("testnet")

const contractAddresses = await syncWSProvider.getContractAddress();

Returns

{
    "mainContract": "0xab..cd",
    "govContract": "0xef..12"
}

Get tokens

Signature

async getTokens(): Promise<Tokens>;

Inputs and outputs

Name Description
returns All supported tokens (see types, for detailed description)

Example

import * as zksync from "zksync";

const syncWSProvider = await zksync.SyncProvider.getDefaultProvider("testnet")

const contractAddresses = await syncWSProvider.getTokens();

Returns

{
  "0xbeeb9f55d523918f9cd2979a454610f673c2885e": {
    "address": "0xbeeb9f55d523918f9cd2979a454610f673c2885e",
    "id": 1,
    "symbol": null
  },
  "ETH": {
    "address": "0000000000000000000000000000000000000000",
    "id": 0,
    "symbol": "ETH"
  }
}

Get account state by address

Signature

async getState(address: Address): Promise<AccountState>;

Inputs and outputs

Name Description
address sync:-prefixed hex-encoded address of the Sync account.
returns Detailed state of the Sync account, including balances, nonce. (see types, for detailed description)

Returns

{
    "address": "sync:2d5bf7a3ab29f0ff424d738a83f9b0588bc9241e",
    "id": 1, // optional
    "committed": {
        "balances": {
            "ETH": "1000000000000000000", // 1 Ether in Wei 
        },
        "nonce": 1,
    },
    "verified": {
        "balances": {
            "ETH": "1000000000000000000", // 1 Ether in Wei 
            // ERC20 token
            "0xFab46E002BbF0b4509813474841E0716E6730136": "1000000000000000000" 
        },
        "nonce": 0,
    }
}

Get transaction receipt

Signature

async getTxReceipt(txHash: string): Promise<TransactionReceipt>;

Inputs and outputs

Name Description
txHash 0x-prefixed hex-encoded hash of the Sync transaction.
returns Receipt of this transaction (see types, for detailed description)

Returns

// Not executed yet
{
    "executed": false
}

// Success
{
    "executed": true,
    "success": true,
    "block": {
      "blockNumber": 658,
      "committed": true,
      "verified": true
    }
}

// Failure
{
    "executed": true,
    "success": true,
    "failReason": "Nonce mismatch",
    "block": {
      "blockNumber": 658,
      "committed": true,
      "verified": true
    }
}

Wait for transaction receipt

Similar to Get transaction receipt but this method will return when a given transaction is committed or verified in the Sync network.

Signature

async notifyTransaction(
    hash: string, 
    action: "COMMIT" | "VERIFY"
): Promise<TransactionReceipt> ;

Inputs and outputs

Name Description
txHash 0x-prefixed hex-encoded hash of the Sync transaction.
action "COMMIT" or "VERIFY"
returns Receipt of this transaction (see types, for detailed description)

Example

import * as zksync from "zksync";

const syncWSProvider = await zksync.getDefaultProvider("testnet")

const receipt = await syncWSProvider.notifyTransaction(
    "0x1111111111111111111111111111111111111111111111111111111111111111",
    "COMMIT"
);

Get priority operation receipt

Signature

async getPriorityOpStatus(
    serialId: number
): Promise<PriorityOperationReceipt>;

Inputs and outputs

Name Description
serialId Numerical id of the priority operation, can be found in logs of the ethereum transaction that created this operation (e.g. deposit)
returns Receipt of this priority operation (see types, for detailed description)

Returns

{
    "executed": true,
    "block": {
      "blockNumber": 658,
      "committed": true,
      "verified": true
    }
}

Wait for priority operation receipt

Similar to Get priority operation receipt but this method will return when given priority operation is committed or verified in the Sync network.

Signature

async notifyPriorityOp(
    serialId: number, 
    action: "COMMIT" | "VERIFY"
): Promise<PriorityOperationReceipt>;

Inputs and outputs

Name Description
serialId Numerical id of the priority operation, can be found in logs of the ethereum transaction that created this operation (e.g. deposit)
action "COMMIT" or "VERIFY"
returns Receipt of this priority operation (see types, for detailed description)

Example

import * as zksync from "zksync";

const syncWSProvider = await zksync.getDefaultProvider("testnet")

const receipt = await syncWSProvider.notifyPriorityOp(
    178, // priority op id
    "COMMIT"
);

ETH Proxy

ETHProxy class is used to simplify some communication with Ethereum network.

Create ETH Proxy

Signature

constructor(
    private ethersProvider: ethers.providers.Provider,
    private contractAddress: ContractAddress
);

Inputs and outputs

Name Description
ethersProvider ethers.js provider connected to ethereum node
contractAddress Addresses of the Sync network contracts

Example

import * as zksync from "zksync";
import {ethers} from "ethers";


const ethersProvider = new ethers.getDefaultProvider('rinkeby');
const syncWSProvider = await zksync.SyncProvider.getDefaultProvider("testnet")

const ethProxy = new zksync.ETHProxy(
    ethersProvider, 
    syncProvider.contractAddress
);

Resolve token id

To sign Sync transaction users have to know the unique numerical id of the given token. It can be retrieved from the ZK Sync network governance contract.

Signature

async resolveTokenId(token: Token): Promise<number>;

Inputs and outputs

Name Description
token Ethereum token identifier ("ETH" or ERC20 contract address)
returns Numerical identifier of the given token inside Sync network.

Example

import * as zksync from "zksync";
import {ethers} from "ethers";

const ethersProvider = new ethers.getDefaultProvider("rinkeby");
const syncProvider = await zksync.getDefaultProvider("testnet");
const ethProxy = new zksync.ETHProxy(
    ethersProvider, 
    syncProvider.contractAddress
);

const ethId = await ethProxy.resolveTokenId("ETH"); // ETH token id is 0

 // ERC20 token if it is supported, >= 1
const erc20Id = await ethProxy.resolveTokenId("0xFab46E002BbF0b4509813474841E0716E6730136");

Estimate deposit fee

Estimates fee required for submitting deposit transactions. Fee for deposit always is always paid in ETH token.

Signature

async estimateDepositFeeInETHToken(token: Token, gasPrice?: utils.BigNumber): Promise<utils.BigNumber>;

Inputs and outputs

Name Description
token Ethereum token identifier ("ETH" or ERC20 contract address)
gasPrice Gas price that will be used for transaction.
returns Fee that has to be paid for deposit

Estimate emergency withdraw fee

Estimates fee required for submitting emergency withdraw transaction. Fee for emergency withdraw is always paid in ETH token.

Signature

async estimateEmergencyWithdrawFeeInETHToken(gasPrice?: utils.BigNumber): Promise<utils.BigNumber>;

Inputs and outputs

Name Description
gasPrice Gas price that will be used for transaction.
returns Fee that has to be paid for emergency withdraw

Accounts

Wallet

Creating wallet from Signer

Signature

constructor(signer: Signer);

Inputs and outputs

Name Description
signer Sync signer that will be used for transaction signing.
provider Sync provider that is used for submitting a transaction to the Sync network.
ethProxy Ethereum proxy that is used for read-only access to the ethereum network.

Example

import * as zksync from "zksync";
import {ethers} from "ethers";

const ethersProvider = new ethers.getDefaultProvider('rinkeby');
const ethProxy = new zksync.ETHProxy(
    ethersProvider, 
    syncProvider.contractAddress
);
const syncProvider = await zksync.getDefaultProvider('testnet');
const signer = zksync.Signer.fromSeed(
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
);

const syncWallet = new zksync.Wallet(signer)
    .connect(syncProvider, ethProxy);

Creating wallet from ETH signer

Signature

static async fromEthSigner(
    ethWallet: ethers.Signer,
    provider?: Provider,
    ethProxy?: ETHProxy
): Promise<Wallet>;

Inputs and outputs

Name Description
ethWallet ethers.Signer that is used to created random seed for zskync.Signer
provider Sync provider that is used for submitting a transaction to the Sync network.
ethProxy Ethereum proxy that is used for read-only access to the ethereum network.
returns zksync.Wallet derived from ethereum wallet (ethers.Signer)

Example

import * as zksync from "zksync";
import {ethers} from "ethers";

const ethersProvider = new ethers.getDefaultProvider('rinkeby');
const ethProxy = new zksync.ETHProxy(
    ethersProvider, 
    syncProvider.contractAddress
);
const syncProvider = await zksync.getDefaultProvider('testnet');

const ethWallet = ethers.Wallet.createRandom().connect(ethersProvider);
const syncWallet = await zksync.Wallet.fromEthSigner(ethWallet)
    .connect(syncProvider, ethProxy);

Get account state

Same as Get account state from provider but gets state of this account.

Signature

async getAccountState(): Promise<AccountState>;

Inputs and outputs

Name Description
returns State of the given account.

Get token balance on ZK Sync

Signature

async getBalance(
    token: Token,
    type: "committed" | "verified" = "committed"
): Promise<ethers.utils.BigNumber>;

Inputs and outputs

Name Description
token token of interest, "ETH" or address of the supported ERC20 token
type "committed" or "verified"
returns Balance of this token

Example

const wallet = ..;// setup wallet

// Get committed Ethereum balance.
const ethCommittedBalance = await getBalance("ETH");

// Get verified ERC20 token balance.
const erc20VerifiedBalance = await getBalance("0xFab46E002BbF0b4509813474841E0716E6730136", "verified"); 

Get token balance on Ethereum

Method similar to syncWallet.getBalance, used to query balance in the Ethereum network.

Signature

export async function getEthereumBalance(
    ethSigner: ethers.Signer,
    token: Token
): Promise<ethers.utils.BigNumber>;

Inputs and outputs

Name Description
ethSigner ethers.Signer, should be connected to the ethereum node.
token token of interest, "ETH" or address of the supported ERC20 token
returns Balance of this token

Example

import * as zksync from "zksync";
import {ethers} from "ethers";

// Setup ethers signer/wallet and connect to ethers provider
const ethersSigner = ..; 

const ethOnChainBalance = await zksync.getEthereumBalance(ethersSigner, "ETH");

Deposit token to Sync

Moves funds from the ethereum account(represented as Signer from ethers.js) to the Sync account. Fees are paid by ethereum account in ETH currency. The fee should be >= base fee, calculated on the contract based on the current gas price.

Formula for base fee calculation:

Token Formula
ETH token 2 * 179000 * GAS_PRICE
ERC20 token 2 * 214000 * GAS_PRICE

See utils for estimating fee.

After the transaction is committed funds are already usable by the recipient so there is no need to wait for verification before proceeding unless additional confirmation is required for your application. To wait for transaction commit use awaitReceipt(see utils).

Signature

async depositFromETH(deposit: {
          depositFrom: ethers.Signer,
          depositTo: Wallet,
          token: Token,
          amount: ethers.utils.BigNumberish,
          maxFeeInETHToken?: ethers.utils.BigNumberish
}): Promise<ETHOperation>;

Inputs and outputs

Name Description
deposit.depositFrom ethereum account of the sender
deposit.depositTo Sync account of the receiver
deposit.token token to be transferred ("ETH" or address of the ERC20 token)
deposit.amount amount of token to be transferred
deposit.maxFeeInETHToken amount of ETH to be paid by depositFrom wallet as a fee for this transaction.
If undefined, 115% of the base fee will be assumed with current GAS_PRICE in the formula.
returns Handle for this transaction.

Example

import * as zksync from "zksync";
import {ethers} from "ethers";

const ethersSigner = ..;  // Setup ethers wallet/signer.
const syncWallet = ..; // Setup zksync wallet.

const depositPriorityOperation = await zksync.depositFromETH({
    depositFrom: ethersSigner,
    depositTo: syncWallet,
    token: "ETH",
    amount: ethers.utils.formatEther("1.0"),
    maxFeeInETHToken: ethers.utils.formatEther("0.1")
});


// Wait till priority operation is committed.
const priorityOpReceipt = await depositPriorityOperation.awaitReceipt();

Transfer in the ZK Sync

Moves funds between accounts inside the ZK Sync network.

After the transaction is committed funds are already usable by the recipient so there is no need to wait for verification before proceeding unless additional confirmation is required for your application. To wait for transaction commit use awaitReceipt(see utils).

Signature

async syncTransfer(transfer: {
    to: Address,
    token: Token,
    amount: ethers.utils.BigNumberish,
    fee: ethers.utils.BigNumberish,
    nonce?: Nonce
}): Promise<Transaction>;

Inputs and outputs

Name Description
transfer.to Sync address of the recipient of funds
transfer.token token to be transferred ("ETH" or address of the ERC20 token)
transfer.amount amount of token to be transferred. To see if amount is packable use pack amount util
transfer.fee amount of token to be paid as a fee for this transaction. To see if amount is packable use pack fee util
transfer.nonce Nonce that is going to be used for this transaction. ("committed" is used for the last known nonce for this account)
returns Handle of the submitted transaction

Example

import {ethers} from "ethers";

const wallet = ..;// setup zksync wallet

const transferTransaction = await wallet.syncTransfer({
    to: "sync:2d5bf7a3ab29f0ff424d738a83f9b0588bc9241e",
    token: "0xFab46E002BbF0b4509813474841E0716E6730136",
    amount: ethers.utils.parseEther("1.0"), 
    fee: ethers.utils.parseEther("0.001") 
});

// Wait wait till transaction is committed
const transactionReceipt = await transferTransaction.awaitReceipt();

Withdraw token from Sync

Moves funds from the Sync account to ethereum address.

The transaction has to be verified until funds are available on the ethereum wallet balance so it is useful to use awaitVerifyReceipt(see utils) before checking ethereum balance.

Signature

async withdrawTo(withdraw: {
    ethAddress: string,
    token: Token,
    amount: ethers.utils.BigNumberish,
    fee: ethers.utils.BigNumberish,
    nonce?: Nonce
}): Promise<Transaction>;

Inputs and outputs

Name Description
withdraw.ethAddress ethereum address of the recipient
withdraw.token token to be transferred ("ETH" or address of the ERC20 token)
withdraw.amount amount of token to be transferred
withdraw.fee amount of token to be paid as a fee for this transaction. To see if amount is packable use pack fee util
withdraw.nonce Nonce that is going to be used for this transaction. ("committed" is used for the last known nonce for this account)
returns Handle of the submitted transaction

Example

import {ethers} from "ethers";

const wallet = ..;// setup zksync wallet

const withdrawTransaction = await wallet.withdrawTo({
    ethAddress: "0x9de880ac69f3ed1e4d6870fcdabf07cbbed6f85c",
    token: "0xFab46E002BbF0b4509813474841E0716E6730136",
    amount: ethers.utils.parseEther("1.0"), 
    fee: ethers.utils.parseEther("0.001") 
});

// Wait wait till transaction is verified
const transactionReceipt = await withdrawTransaction.awaitVerifyReceipt();

Emergency withdraw from Sync

If ordinary withdraw from Sync account is ignored by network operators user could create an emergency withdraw request using special ethereum transaction, this withdraw request can't be ignored.

Moves the full amount of the given token from the Sync account to the ethereum account(represented as Signer from ethers.js).

Fees are paid by ethereum account in ETH currency. The fee should be >= base fee, calculated on the contract based on the current gas price. The formula for base fee calculation: 2 * 170000 * GAS_PRICE

See utils for estimating fee.

The transaction has to be verified until funds are available on the ethereum wallet balance so it is useful to use awaitVerifyReceipt(see utils) before checking ethereum balance.

Signature

export async function emergencyWithdraw(withdraw: {
    withdrawTo: ethers.Signer,
    withdrawFrom: Wallet,
    token: Token,
    maxFeeInETHToken?: ethers.utils.BigNumberish,
    accountId?: number,
    nonce?: Nonce
}): Promise<ETHOperation>;

Inputs and outputs

Name Description
withdraw.withdrawTo ethereum account of the receiver, also it is used to post withdraw request to ethereum
withdraw.withdrawFrom Sync account of the sender
withdraw.token token to be transferred ("ETH" or address of the ERC20 token)
withdraw.amount amount of token to be transferred
withdraw.maxFeeInETHToken amount of ETH to be paid by withdrawTo wallet as a fee for this transaction.
If undefined, 115% of the base fee will be assumed with current GAS_PRICE in the formula.
withdraw.accountId Numerical id of the given account. If null it is going to be resolved from the ZK Sync provider.
withdraw.nonce Transaction nonce. "committed" by default
returns Handle for this transaction.

Example

import * as zksync from "zksync";
import {ethers} from "ethers";

const ethersSigner = ..;  // Setup ethers wallet/signer.
const syncWallet = ..; // Setup zksync wallet.

const emergencyWithdrawPriorityOp= await zksync.emergencyWithdraw({
    withdrawTo: ethersSigner,
    withdrawFrom: syncWallet,
    token: "ETH",
    maxFeeInETHToken: ethers.utils.parseEther("0.3")
});


// Wait till priority operation is verified.
const priorityOpReceipt = await emergencyWithdrawPriorityOp.awaitVerifyReceipt();

Close wallet transaction

Removes account from the ZK Sync network.

Signature

async close(close: {
    nonce: "committed" | number = "committed"
}): Promise<Transaction>;

Inputs and outputs

Name Description
close.nonce Nonce that is going to be used for this transaction. ("committed" is used for the last known nonce for this account)
returns Handle of the submitted transaction

Example

const wallet = ..;// setup zksync wallet

const closeTransaction = await wallet.close();

// Wait wait till transaction is committed
const transactionReceipt = await closeTransaction.awaitReceipt();

Signer

Create from private key

Signature

static fromPrivateKey(pk: BN): Signer;

Inputs and outputs

Name Description
pk private key
returns Signer derived from private key

Create from seed

Signature

static fromSeed(seed: Buffer): Signer;

Inputs and outputs

Name Description
seed Random bytes array (should be >= 32 bytes long)
returns Signer derived from this seed

Get address

Signature

address(): Address;

Inputs and outputs

Name Description
returns Address of the Sync account derrived from corresponding public key

Sign sync transfer

Signs transfer transaction, the result can be submitted to the Sync network. The sender for this transaction is assumed to be this SyncSigner address.

Signature

signSyncTransfer(transfer: {
    to: Address;
    tokenId: number;
    amount: ethers.utils.BigNumberish;
    fee: ethers.utils.BigNumberish;
    nonce: number;
}): SyncTransfer;

Inputs and outputs

Name Description
transfer.to Address of the recipient
transfer.tokenId Numerical token id
transfer.amount Amount to transfer, payed in token
transfer.fee Fee to pay for transfer, payed in token
transfer.nonce Transaction nonce
returns Signed Sync transfer transaction

Sign Sync Withdraw

Signs withdraw transaction, the result can be submitted to the Sync network. The sender for this transaction is assumed to be this SyncSigner address.

Signature

signSyncWithdraw(withdraw: {
    ethAddress: string;
    tokenId: number;
    amount: ethers.utils.BigNumberish;
    fee: ethers.utils.BigNumberish;
    nonce: number;
}): SyncWithdraw;

Inputs and outputs

Name Description
withdraw.ethAddress Ethereum address of the recipient
withdraw.tokenId Numerical token id
withdraw.amount Amount to withdraw, paid in token
withdraw.fee Fee to pay for withdrawing, paid in token
withdraw.nonce Transaction nonce
returns Signed Sync withdraw transaction

Sign Sync account close

Signs account close transaction, the result can be submitted to the Sync network. Account to be closed is assumed to be this Signer address.

Signature

signSyncCloseAccount(close: { nonce: number }): CloseAccount;

Inputs and outputs

Name Description
close.nonce Transaction nonce
returns Signed Sync account close transaction

Sign Sync emergency withdraw

Signs emergency withdraw transaction, the returned signature can be used to submit withdraw request to the ethereum network. Account for withdraw is assumed to be this Signer address.

Signature

syncEmergencyWithdrawSignature(emergencyWithdraw: {
    ethAddress: string;
    tokenId: number;
    nonce: number;
}): Buffer;

Inputs and outputs

Name Description
emergencyWithdraw.accountId Numerical account id of the sender in the ZK Sync network.
emergencyWithdraw.ethAddress Ethereum address of the recipient
emergencyWithdraw.tokenId Numerical token id in the ZK Sync network.
emergencyWithdraw.nonce Transaction nonce
returns Signature for emergency withdraw transaction (64 byte, packed)

Utils

Amount packing

Closest packable amount

Transfers amount should be packable to 5-byte long floating-point representation. This function is used to check if this amount can be used as a transfer amount.

Signature

export function closestPackableTransactionAmount(
    amount: ethers.utils.BigNumberish
): ethers.utils.BigNumber;

Closest packable fee

All fees paid in transfers and withdraws should be packable to 2-byte long floating-point representation. This function is used to check if this amount can be used as a fee.

Signature

export function closestPackableTransactionFee(
    fee: ethers.utils.BigNumberish
): ethers.utils.BigNumber;

Awaiting for operation completion

It is often useful to be able to wait until the transaction is committed or verified. It is possible to do that using objects returned from methods that submit transactions.

It is possible to wait until the operation is either 1. Committed (with awaitReceipt) when the state is updated in the ZK Sync network 2. Verified (with awaitVerifyReceipt) when the state is finalized on the Ethereum

Commit comes first, but there is no need to wait for commit if you are interested in the verify since await for verifying implies await for commit;

Awaiting for transaction.

import * as zksync from "zksync";
const wallet = ..; // create ZK Sync Wallet

// see transfer example for details
const transfer = wallet.syncTransfer({..}); 

// this function will return when deposit is committed to the ZK Sync chain
const receiptAfterCommit = await transfer.awaitReceipt();

// this function will return when deposit is verified with ZK proof.
const receiptAfterVerify = await transfer.awaitVerifyReceipt();

Awaiting for priority operation

import * as zksync from "zksync";

// see deposit example for details
const deposit = zksync.depositFromETH({..}); 

// this function will return when deposit is committed to the ZK Sync chain
const receiptAfterCommit = await deposit.awaitReceipt();

// this function will return when deposit is verified with ZK proof.
const receiptAfterVerify = await deposit.awaitVerifyReceipt();

Types

import { utils } from "ethers";

export type Address = string;

// ETH or ERC20 address
export type Token = "ETH" | string;

export type Nonce = number | "committed";

export interface AccountState {
    address: Address;
    id?: number;
    committed: {
        balances: {
            [token: string]: utils.BigNumberish;
        };
        nonce: number;
    };
    verified: {
        balances: {
            [token: string]: utils.BigNumberish;
        };
        nonce: number;
    };
}

export interface Signature {
    pubKey: string;
    signature: string;
}

export interface Transfer {
    type: "Transfer";
    from: Address;
    to: Address;
    token: number;
    amount: utils.BigNumberish;
    fee: utils.BigNumberish;
    nonce: number;
    signature: Signature;
}

export interface Withdraw {
    type: "Withdraw";
    account: Address;
    ethAddress: string;
    token: number;
    amount: utils.BigNumberish;
    fee: utils.BigNumberish;
    nonce: number;
    signature: Signature;
}

export interface CloseAccount {
    type: "Close";
    account: Address;
    nonce: number;
    signature: Signature;
}

export interface BlockInfo {
    blockNumber: number;
    committed: boolean;
    verified: boolean;
}

export interface TransactionReceipt {
    executed: boolean;
    success?: boolean;
    failReason?: string;
    block?: BlockInfo;
}

export interface PriorityOperationReceipt {
    executed: boolean;
    block?: BlockInfo;
}

export interface ContractAddress {
    mainContract: string;
    govContract: string;
}

export interface Tokens {
    [token: string]: {
        address: string,
        id: number,
        symbol?: string,
    }
}