Providers


Providers

A Web3 Provider object provides application-layer access to underlying blockchain networks.

The zksync-web3open in new window library supports provider methods from the ethers.jsopen in new window library and supplies additional functionality.

Two providers are available:

Tips

Provider

Info

constructor

Returns a zkSync Era Provider object.

Inputs

ParameterTypeDescription
url?string or ConnectionInfoopen in new windowNetwork RPC URL (optional)
network?ethers.providers.NetworkishNetwork name (optional)
constructor(url?: ConnectionInfo | string, network?: ethers.providers.Networkish) {
    super(url, network);
    this.pollingInterval = 500;

    const blockTag = this.formatter.blockTag.bind(this.formatter);
    this.formatter.blockTag = (tag: any) => {
        if (tag == 'committed' || tag == 'finalized') {
            return tag;
        }
        return blockTag(tag);
    };
    this.contractAddresses = {};
    this.formatter.transaction = parseTransaction;
}

Example

import { Provider } from "zksync-web3";
const provider = new Provider("https://testnet.era.zksync.dev");

estimateFee

Returns an estimated Fee for requested transaction.

Inputs

ParameterTypeDescription
transactionTransactionRequestopen in new windowTransaction request.
async estimateFee(transaction: TransactionRequest): Promise<Fee> {
    return await this.send("zks_estimateFee", [transaction]);
}

estimateGas

Returns an estimate of the amount of gas required to submit a transaction to the network.

Ethers implementation.open in new window

estimateGasL1

Returns an estimate of the amount of gas required to submit a transaction from L1 to L2 as a BigNumber object.

Calls the zks_estimateL1ToL2 JSON-RPC method.

estimateGasTransfer

Returns the gas estimation for a transfer transaction.

Calls internal method getTransferTxopen in new window to get the transfer transaction and sends it to the estimateGas method.

Inputs

ParameterTypeDescription
tokenAddress stringToken address.
amountBigNumberishAmount of token.
from?Address stringFrom address (optional).
to?Address stringTo address (optional).
overrides?ethers.CallOverridesEthers call overrides object (optional).
async estimateGasTransfer(transaction: {
    to: Address;
    amount: BigNumberish;
    from?: Address;
    token?: Address;
    overrides?: ethers.CallOverrides;
}): Promise<BigNumber> {
    const transferTx = await this.getTransferTx(transaction);
    return await this.estimateGas(transferTx);
}

estimateGasWithdraw

Returns the gas estimation for a withdrawal transaction.

Calls internal method getWithdrawTxopen in new window to get the withdrawal transaction and sends it to the estimateGas method.

Inputs

ParameterTypeDescription
tokenAddress stringToken address.
amountBigNumberishAmount of token.
from?Address stringFrom address (optional).
to?Address stringTo address (optional).
bridgeAddress?Address stringBridge address (optional).
overrides?ethers.CallOverridesEthers call overrides object (optional).
async estimateGasWithdraw(transaction: {
    token: Address;
    amount: BigNumberish;
    from?: Address;
    to?: Address;
    bridgeAddress?: Address;
    overrides?: ethers.CallOverrides;
}): Promise<BigNumber> {
    const withdrawTx = await this.getWithdrawTx(transaction);
    return await this.estimateGas(withdrawTx);
}

estimateL1ToL2Execute

Returns gas estimation for an L1 to L2 execute operation.

Inputs

ParameterTypeDescription
contractAddressAddress stringAddress of contract.
calldataBytesLikeThe transaction call data.
caller?Address stringCaller address (optional).
l2Value?BigNumberishCurrent L2 gas value (optional).
factoryDeps?BytesLike[]Byte array containing contract bytecode.
gasPerPubdataByte?BigNumberishConstant representing current amount of gas per byte (optional).
overrides?ethers.PayableOverridesEthers payable overrides object (optional).
async estimateL1ToL2Execute(transaction: {
    contractAddress: Address;
    calldata: BytesLike;
    caller?: Address;
    l2Value?: BigNumberish;
    factoryDeps?: ethers.BytesLike[];
    gasPerPubdataByte?: BigNumberish;
    overrides?: ethers.PayableOverrides;
}): Promise<BigNumber> {
    transaction.gasPerPubdataByte ??= REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT;

    // If the `from` address is not provided, we use a random address, because
    // due to storage slot aggregation, the gas estimation will depend on the address
    // and so estimation for the zero address may be smaller than for the sender.
    transaction.caller ??= ethers.Wallet.createRandom().address;

    const customData = {
        gasPerPubdataByte: transaction.gasPerPubdataByte
    };
    if (transaction.factoryDeps) {
        Object.assign(customData, { factoryDeps: transaction.factoryDeps });
    }

    const fee = await this.estimateGasL1({
        from: transaction.caller,
        data: transaction.calldata,
        to: transaction.contractAddress,
        value: transaction.l2Value,
        customData
    });

    return fee;
}

getAllAccountBalances

Returns all balances for confirmed tokens given by an account address.

Calls the zks_getAllAccountBalances JSON-RPC method.

getBalance

Returns the user's balance as a BigNumber object for an (optional) block tag and (optional) token.

When block and token are not supplied, committed and ETH are the default values.

Inputs

NameDescription
addressUser's address.
blockTag?Block tag for getting the balance on. Latest committed block is default.
tokenAddress?The address of the token. ETH is default.
override async getBalance(address: Address, blockTag?: BlockTag, tokenAddress?: Address) {
    const tag = this.formatter.blockTag(blockTag);
    if (tokenAddress == null || isETH(tokenAddress)) {
        // requesting ETH balance
        return await super.getBalance(address, tag);
    } else {
        try {
            let token = IERC20MetadataFactory.connect(tokenAddress, this);
            return await token.balanceOf(address, { blockTag: tag });
        } catch {
            return BigNumber.from(0);
        }
    }
}

Example

import { Provider } from "zksync-web3";

const provider = new Provider("https://testnet.era.zksync.dev");

//Find the USDC ADDRESS in https://zksync2-testnet.zkscan.io/address/0x0faF6df7054946141266420b43783387A78d82A9/transactions
const USDC_L2_ADDRESS = "<USDC_L2_ADDRESS>";
// Get the USDC balance from your account using your address. Get your address from https://zksync2-testnet.zkscan.io/txs
console.log(await provider.getBalance("<YOUR_ADDRESS>", "latest", USDC_L2_ADDRESS));

// Getting ETH balance
console.log(await provider.getBalance("<YOUR_ADDRESS>"));

getBlock

Returns block from the network, or false if there is no block.

Ethers implementation.open in new window

getBlockDetails

Returns additional zkSync-specific information about the L2 block.

Calls the zks_getBlockDetails JSON-RPC method.

getBlockWithTransactions

Returns an array of TransactionResponse objects.

Ethers implementation.open in new window

getConfirmedTokens

Returns [address, symbol, name, and decimal] information of all tokens within a range of ids given by parameters from and limit.

Calls the zks_getConfirmedTokens JSON-RPC method.

Tip

  • Confirmed in the function name means any token bridged to zkSync Era via the official bridge.

The tokens are returned in alphabetical order by their symbol. This means the token id is its position in an alphabetically sorted array of tokens.

Inputs

NameDescription
startThe token id from which to start returning the information about the tokens. Zero by default.
limitThe number of tokens to be returned from the API. 255 by default.
async getConfirmedTokens(start: number = 0, limit: number = 255): Promise<Token[]> {
    const tokens: Token[] = await this.send('zks_getConfirmedTokens', [start, limit]);
    return tokens.map((token) => ({ address: token.l2Address, ...token }));
}

Example

import { Provider } from "zksync-web3";
const provider = new Provider("https://testnet.era.zksync.dev");

console.log(await provider.getConfirmedTokens());

getContractAccountInfo

Returns the version of the supported account abstraction and nonce ordering from a given contract address.

Inputs

NameDescription
addressContract address
async getContractAccountInfo(address: Address): Promise<ContractAccountInfo> {
    const deployerContract = new Contract(CONTRACT_DEPLOYER_ADDRESS, CONTRACT_DEPLOYER, this);
    const data = await deployerContract.getAccountInfo(address);

    return {
        supportedAAVersion: data.supportedAAVersion,
        nonceOrdering: data.nonceOrdering
    };
}

getDefaultBridgeAddresses

Returns the addresses of the default zkSync Era bridge contracts on both L1 and L2.

async getDefaultBridgeAddresses() {
    if (!this.contractAddresses.erc20BridgeL1) {
        let addresses = await this.send('zks_getBridgeContracts', []);
        this.contractAddresses.erc20BridgeL1 = addresses.l1Erc20DefaultBridge;
        this.contractAddresses.erc20BridgeL2 = addresses.l2Erc20DefaultBridge;
    }
    return {
        erc20L1: this.contractAddresses.erc20BridgeL1,
        erc20L2: this.contractAddresses.erc20BridgeL2
    };
}

getDefaultProvider

Static method which returns a Provider object from the RPC URL or localhost.

static getDefaultProvider() {
    return new Provider(process.env.ZKSYNC_WEB3_API_URL || 'http://localhost:3050');
}

getFilterChanges

Returns an array of logs by calling Ethereum method eth_getFilterChanges.open in new window

getFormatter

Static utility method that returns a Formatter object for processing readable block data.

static override getFormatter(): Formatter {
    if (defaultFormatter == null) {
        defaultFormatter = new Formatter();
        const number = defaultFormatter.number.bind(defaultFormatter);
        const boolean = defaultFormatter.boolean.bind(defaultFormatter);
        const hash = defaultFormatter.hash.bind(defaultFormatter);
        const address = defaultFormatter.address.bind(defaultFormatter);

        defaultFormatter.formats.receiptLog.l1BatchNumber = Formatter.allowNull(number);

        (defaultFormatter.formats as any).l2Tol1Log = {
            blockNumber: number,
            blockHash: hash,
            l1BatchNumber: Formatter.allowNull(number),
            transactionIndex: number,
            shardId: number,
            isService: boolean,
            sender: address,
            key: hash,
            value: hash,
            transactionHash: hash,
            logIndex: number
        };

        defaultFormatter.formats.receipt.l1BatchNumber = Formatter.allowNull(number);
        defaultFormatter.formats.receipt.l1BatchTxIndex = Formatter.allowNull(number);
        defaultFormatter.formats.receipt.l2ToL1Logs = Formatter.arrayOf((value) =>
            Formatter.check((defaultFormatter.formats as any).l2Tol1Log, value)
        );

        defaultFormatter.formats.block.l1BatchNumber = Formatter.allowNull(number);
        defaultFormatter.formats.block.l1BatchTimestamp = Formatter.allowNull(number);
        defaultFormatter.formats.blockWithTransactions.l1BatchNumber = Formatter.allowNull(number);
        defaultFormatter.formats.blockWithTransactions.l1BatchTimestamp = Formatter.allowNull(number);
        defaultFormatter.formats.transaction.l1BatchNumber = Formatter.allowNull(number);
        defaultFormatter.formats.transaction.l1BatchTxIndex = Formatter.allowNull(number);

        defaultFormatter.formats.filterLog.l1BatchNumber = Formatter.allowNull(number);
    }
    return defaultFormatter;
}

getGasPrice

Returns an estimate (best guess) of the gas price to use in a transaction.

Ethers implementation.open in new window

getL1BatchBlockRange

Returns the range of blocks contained within a batch given by batch number.

Calls the zks_getL1BatchBlockRange JSON-RPC method.

async getL1BatchBlockRange(l1BatchNumber: number): Promise<[number, number] | null> {
    const range = await this.send('zks_getL1BatchBlockRange', [l1BatchNumber]);
    if (range == null) {
        return null;
    }
    return [parseInt(range[0], 16), parseInt(range[1], 16)];
}

getL1BatchDetails

Returns data pertaining to a given batch.

Calls the zks_getL1BatchDetails JSON-RPC method.

getL1BatchNumber

Returns the latest L1 batch number.

Calls the zks_getL1BatchNumber JSON-RPC method.

getL2TransactionFromPriorityOp

Returns a transaction object from a given Ethers TransactionResponseopen in new window object.

Inputs

NameDescription
l1TxResponseEthers TransactionResponse object.
async getL2TransactionFromPriorityOp(
    l1TxResponse: ethers.providers.TransactionResponse
): Promise<TransactionResponse> {
    const receipt = await l1TxResponse.wait();
    const l2Hash = getL2HashFromPriorityOp(receipt, await this.getMainContractAddress());

    let status = null;
    do {
        status = await this.getTransactionStatus(l2Hash);
        await sleep(this.pollingInterval);
    } while (status == TransactionStatus.NotFound);

    return await this.getTransaction(l2Hash);
}

getLogProof

Returns the proof for a transaction's L2 to L1 log sent via the L1Messenger system contract.

Calls the zks_getL2ToL1LogProof JSON-RPC method.

getLogs

Returns an array of all logs that match a filter with a given id by calling Ethereum method eth_getLogs.open in new window

getMainContractAddress

Returns the main zkSync Era smart contract address.

Calls the zks_getMainContract JSON-RPC method.

async getMainContractAddress(): Promise<Address> {
    if (!this.contractAddresses.mainContract) {
        this.contractAddresses.mainContract = await this.send('zks_getMainContract', []);
    }
    return this.contractAddresses.mainContract;
}

getMessageProof

Returns the proof for a message sent via the L1Messenger system contract.

Calls the zks_getL2ToL1MsgProof JSON-RPC method.

async getMessageProof(
    blockNumber: ethers.BigNumberish,
    sender: Address,
    messageHash: BytesLike,
    logIndex?: number
): Promise<MessageProof | null> {
    return await this.send('zks_getL2ToL1MsgProof', [
        BigNumber.from(blockNumber).toNumber(),
        sender,
        ethers.utils.hexlify(messageHash),
        logIndex
    ]);
}

getPriorityOpResponse

Returns an Ethers TransactionResponseopen in new window as a PriorityOpResponse object.

Inputs

NameDescription
l1TxResponseEthers TransactionResponse object.
async getPriorityOpResponse(l1TxResponse: ethers.providers.TransactionResponse): Promise<PriorityOpResponse> {
    const l2Response = { ...l1TxResponse } as PriorityOpResponse;

    l2Response.waitL1Commit = l2Response.wait;
    l2Response.wait = async () => {
        const l2Tx = await this.getL2TransactionFromPriorityOp(l1TxResponse);
        return await l2Tx.wait();
    };
    l2Response.waitFinalize = async () => {
        const l2Tx = await this.getL2TransactionFromPriorityOp(l1TxResponse);
        return await l2Tx.waitFinalize();
    };

    return l2Response;
}

getTestnetPaymasterAddress

Returns the testnet paymaster address if available, or null.

async getTestnetPaymasterAddress(): Promise<Address | null> {
    // Unlike contract's addresses, the testnet paymaster is not cached, since it can be trivially changed
    // on the fly by the server and should not be relied to be constant
    return await this.send('zks_getTestnetPaymaster', []);
}

Example

import { Provider } from "zksync-web3";

const provider = new Provider("https://testnet.era.zksync.dev");

console.log(await provider.getTestnetPaymasterAddress());

getTransaction

Returns a specified L2 transaction response object by overriding the Ethers implementationopen in new window.

Inputs

NameDescription
hashstring
override async getTransaction(hash: string | Promise<string>): Promise<TransactionResponse> {
    hash = await hash;
    const tx = await super.getTransaction(hash);
    return tx ? this._wrapTransaction(tx, hash) : null;
}

Example

import { Provider } from "zksync-web3";
const provider = new Provider("https://testnet.era.zksync.dev");

const TX_HASH = "<YOUR_TX_HASH_ADDRESS>";
const txHandle = await provider.getTransaction(TX_HASH);

// Wait until the transaction is processed by the server.
await txHandle.wait();
// Wait until the transaction is finalized.
await txHandle.waitFinalize();

getTransactionDetails

Returns data from a specific transaction given by the transaction hash.

Calls the getTransactionDetails JSON-RPC method.

getTransactionReceipt

Returns the transaction receipt from a given hash number.

Ethers implementation.open in new window

getTransactionStatus

Returns the status of a specified transaction.

Inputs

NameDescription
txHashstring
async getTransactionStatus(txHash: string) {
    const tx = await this.getTransaction(txHash);
    if (tx == null) {
        return TransactionStatus.NotFound;
    }
    if (tx.blockNumber == null) {
        return TransactionStatus.Processing;
    }
    const verifiedBlock = await this.getBlock('finalized');
    if (tx.blockNumber <= verifiedBlock.number) {
        return TransactionStatus.Finalized;
    }
    return TransactionStatus.Committed;
}

Example

import { Provider } from "zksync-web3";
const provider = new Provider("https://testnet.era.zksync.dev");

const TX_HASH = "YOUR_TX_HASH_ADDRESS";
console.log(await provider.getTransactionStatus(TX_HASH));

l1ChainId

Returns the chain id of the underlying L1.

Calls the zks_L1ChainId JSON-RPC method.

l1TokenAddress

Returns the L1 token address equivalent for a L2 token address as they are not equal. ETH's address is set to zero address.

Note

Only works for tokens bridged on default zkSync Era bridges.

Inputs

NameDescription
tokenThe address of the token on L2.
async l1TokenAddress(token: Address) {
    if (token == ETH_ADDRESS) {
        return ETH_ADDRESS;
    } else {
        const erc20BridgeAddress = (await this.getDefaultBridgeAddresses()).erc20L2;
        const erc20Bridge = IL2BridgeFactory.connect(erc20BridgeAddress, this);
        return await erc20Bridge.l1TokenAddress(token);
    }
}

l2TokenAddress

Returns the L2 token address equivalent for a L1 token address as they are not equal. ETH's address is set to zero address.

Note

Only works for tokens bridged on default zkSync Era bridges.

Inputs

NameDescription
tokenThe address of the token on L1.
async l2TokenAddress(token: Address) {
    if (token == ETH_ADDRESS) {
        return ETH_ADDRESS;
    } else {
        const erc20BridgeAddress = (await this.getDefaultBridgeAddresses()).erc20L2;
        const erc20Bridge = IL2BridgeFactory.connect(erc20BridgeAddress, this);
        return await erc20Bridge.l2TokenAddress(token);
    }
}

newBlockFilter

Returns a new block filter by calling Ethereum method eth_newBlockFilter.open in new window

newFilter

Returns a new filter by calling Ethereum method eth_newFilteropen in new window and passing a filter object.

newPendingTransactionFilter

Returns a new pending transaction filter by calling Ethereum method eth_newPendingTransactionFilteropen in new window and passing a filter object.

sendTransaction

Override of Ethers implementation.open in new window

Web3Provider

Use this provider for Web3 browser wallet integrations for easy compatibility with Metamask, WalletConnect, and other popular browser wallets.

constructor

Returns a provider object by extending the constructor of the Provider class and accepting an ExternalProvider instead of a node URL.

Inputs and outputs

NameDescription
providerThe ethers.providers.ExternalProvideropen in new window class instance. For instance, Metamask is window.ethereum.
network?The description of the network.
constructor(provider: ExternalProvider, network?: ethers.providers.Networkish) {
    if (provider == null) {
        throw new Error('missing provider');
    }
    if (!provider.request) {
        throw new Error('provider must implement eip-1193');
    }

    let path = provider.host || provider.path || (provider.isMetaMask ? 'metamask' : 'eip-1193:');
    super(path, network);
    this.provider = provider;
}

Example

import { Web3Provider } from "zksync-web3";

const provider = new Web3Provider(window.ethereum);

estimateGas

Returns gas estimate by overriding the zkSync Era estimateGas method.

Inputs and outputs

NameDescription
transactionDeferrable object of TransactionRequest type.
override async estimateGas(transaction: ethers.utils.Deferrable<TransactionRequest>) {
    const gas: BigNumber = await super.estimateGas(transaction);
    const metamaskMinimum = BigNumber.from(21000);
    const isEIP712 = transaction.customData != null || transaction.type == EIP712_TX_TYPE;
    return gas.gt(metamaskMinimum) || isEIP712 ? gas : metamaskMinimum;
}

getSigner

Override of Ethers implementationopen in new window.

Example

import { Web3Provider } from "zksync-web3";

const provider = new Web3Provider(window.ethereum);
const signer = provider.getSigner();

send

Returns a provider request object by overriding the Ethers implementationopen in new window.

Inputs and outputs

NameDescription
methodRequest method name as string
params?Optional array of any type
override async send(method: string, params?: Array<any>): Promise<any> {
    params ??= [];
    // Metamask complains about eth_sign (and on some versions hangs)
    if (method == 'eth_sign' && (this.provider.isMetaMask || this.provider.isStatus)) {
        // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
        method = 'personal_sign';
        params = [params[1], params[0]];
    }
    return await this.provider.request({ method, params });
}

override getSigner(addressOrIndex?: number | string): Signer {
    return Signer.from(super.getSigner(addressOrIndex) as any);
}
Last update:
Contributors: Blessing Krofegha,Antonio,Stanislav Bezkorovainyi,niramisa,AnastasiiaVashchuk,Danijel Radakovic,Dustin Brickwood,Roman Brodetski,Roman Petriv,botdad,defigen,omahs