Go

Accounts

Overview

The accounts package provides abstractions that wrap operations that interact with an account. An account typically contains a private key, allowing it to sign various types of payloads. There are the following interfaces that provide account operations for different purposes:

  • Signer provides support for signing EIP-712 transactions as well as other types of transactions supported by types.Signer.
  • AdapterL1 is associated with an account and provides common operations on the L1 network for the associated account.
  • AdapterL2 is associated with an account and provides common operations on the L2 network for the associated account.
  • Deployer is associated with an account and provides deployment of smart contracts and smart accounts on the L2 network for the associated account.
  • Adapter consists of AdapterL1, AdapterL2, and Deployer interfaces.

There are the following objects that provide account operations:

  • BaseSigner implements the Signer interface.
  • WalletL1 implements the AdapterL1 interface.
  • WalletL2 implements the AdapterL2 interface.
  • BaseDeployer implements the Deployer interface.
  • Wallet implements the Adapter interface.
  • SmartAccount which provides better support for account abstraction. There are following factory methods:
    • NewECDSASmartAccount: uses a single ECDSA key for signing payload.
    • NewMultisigECDSASmartAccount: uses multiple ECDSA keys for signing payloads.

In most cases, Wallet should be used because it provides all the necessary operations. Other objects and interfaces are separated to make the SDK more flexible and extensible.

BaseSigner

Init

Creates a new instance of BaseSigner based on the provided mnemonic phrase.

func NewBaseSignerFromMnemonic(mnemonic string, chainId int64) (*BaseSigner, error)

Creates a new instance of BaseSigner based on the provided mnemonic phrase and account ID.

func NewBaseSignerFromMnemonicAndAccountId(mnemonic string, accountId uint32, chainId int64) (*BaseSigner, error)

Creates a new instance of BaseSigner based on the provided raw private key.

func NewBaseSignerFromRawPrivateKey(rawPk []byte, chainId int64) (*BaseSigner, error)

Creates an instance of Signer with a randomly generated private key.

func NewRandomBaseSigner(chainId int64) (*BaseSigner, error)

Address

Returns the address associated with the signer.

Address() common.Address

Domain

Returns the EIP-712 domain used for signing.

Domain() *eip712.Domain

PrivateKey

Returns the private key associated with the signer.

PrivateKey() *ecdsa.PrivateKey

Signs the given hash using the signer's private key and returns the signature. The hash should be the 32-byte hash of the data to be signed.

SignHash

SignHash(msg []byte) ([]byte, error)

SignTypeData

Signs the given EIP-712 typed data using the signer's private key and returns the signature. The domain parameter is the EIP-712 domain separator, and the data parameter is the EIP-712 typed data.

SignTypedData(d *eip712.Domain, data eip712.TypedData) ([]byte, error)

WalletL1

Init

Creates an instance of WalletL1 associated with the account provided by the raw private key.

func NewWalletL1(rawPrivateKey []byte, clientL1 *ethclient.Client, clientL2 *clients.Client) (*WalletL1, error

Creates an instance of WalletL1 associated with the account provided by the signer.

NewWalletL1FromSigner(signer *Signer, clientL1 *ethclient.Client, clientL2 *clients.Client) (*WalletL1, error)

Example

PrivateKey     := os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider := "https://sepolia.era.zksync.dev"
EthereumProvider := "https://rpc.ankr.com/eth_sepolia"

client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

ethClient, err := ethclient.Dial(EthereumProvider)
if err != nil {
    log.Panic(err)
}
defer ethClient.Close()

wallet, err := accounts.NewWalletL1(common.Hex2Bytes(PrivateKey), &client, ethClient)
if err != nil {
    log.Panic(err)
}

MainContract

Returns the ZKsync L1 smart contract.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
MainContract(ctx context.Context) (*zksync.IZkSync, error)

Example

mainContract, err := wallet.MainContract(context.Background())
if err != nil {
    log.Panic(err)
}

BridgehubContract

Returns the Bridgehub L1 smart contract.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
BridgehubContract(_ context.Context) (*bridgehub.IBridgehub, error)

Example

bridgehub, err := wallet.BridgehubContract(context.Background())
if err != nil {
    log.Panic(err)
}

L1BridgeContracts

Returns L1 bridge contracts.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
L1BridgeContracts(ctx context.Context) (*zkTypes.L1BridgeContracts, error)

Example

contracts, err := wallet.L1BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}

BaseToken

Returns the address of the base token on L1.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
BaseToken(opts *CallOpts) (common.Address, error)

Example

baseToken, err := wallet.BaseToken(nil)
if err != nil {
    log.Panic(err)
}
fmt.Println("Base token: ", baseToken)

IsEthBasedChain

Returns whether the chain is ETH-based.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
IsEthBasedChain(ctx context.Context) (bool, error)

Example

isEthBased, err := wallet.IsEthBasedChain(context.Background())
if err != nil {
    log.Panic(err)
}
fmt.Println("Is ETH-based chain: ", isEthBased)

BalanceL1

Returns the balance of the specified token on L1 that can be either ETH or any ERC20 token.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
tokencommon.AddressToken address.
BalanceL1(opts *CallOpts, token common.Address) (*big.Int, error)

Example

balance, err := wallet.BalanceL1(nil, utils.EthAddress)
if err != nil {
    log.Panic(err)
}
fmt.Println("Balance: ", balance)

AllowanceL1

Returns the amount of approved tokens for a specific L1 bridge.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
tokencommon.AddressToken address.
bridgeAddresscommon.AddressBridge address.
AllowanceL1(opts *CallOpts, token common.Address, bridgeAddress common.Address) (*big.Int, error)

Example

// The Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")

contracts, err := client.BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}
bridgeAllowance, err := wallet.AllowanceL1(nil, TokenAddress, contracts.L1Erc20DefaultBridge)
if err != nil {
    log.Panic(err)
}
fmt.Println("Bridge allowance: ", bridgeAllowance)

L2TokenAddress

Returns the corresponding address on the L2 network for the token on the L1 network.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tokencommon.AddressL1 token address.
L2TokenAddress(ctx context.Context, token common.Address) (common.Address, error)

Example

l1DAI := common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B")
l2DAI, err := wallet.L2TokenAddress(context.Background(), l1DAI)
if err != nil {
    log.Panic(err)
}
fmt.Println("L2 DAI address: ", l2DAI)

ApproveERC20

Approves the specified amount of tokens for the specified L1 bridge.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tokencommon.AddressL1 token address.
amount*big.IntApproval amount.
ApproveERC20(auth *TransactOpts, token common.Address, amount *big.Int, bridgeAddress common.Address) (*types.Transaction, error)

Example

// The Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")

contracts, err := client.BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}
tx, err := wallet.ApproveERC20(nil, TokenAddress, contracts.L1Erc20DefaultBridge)
if err != nil {
    log.Panic(err)
}
fmt.Println("Tx: ", tx.Hash())

BaseCost

Returns base cost for L2 transaction.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
gasLimit*big.IntThe gasLimit for the the L2 contract call.
gasPerPubdataByte*big.IntThe L2 gas price for each published L1 calldata byte.
gasPrice*big.Int (optional)The L1 gas price of the L1 transaction that will send the request for an execute call.
BaseCost(opts *CallOpts, gasLimit, gasPerPubdataByte, gasPrice *big.Int) (*big.Int, error)

Example

gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
    log.Panic(err)
}

baseCost, err := wallet.BaseCost(nil, big.NewInt(9000), utils.RequiredL1ToL2GasPerPubdataLimit, gasPrice)
if err != nil {
    log.Panic(err)
}
fmt.Println("Base cost: ", baseCost)

DepositAllowanceParams

Returns the parameters for the approval token transaction based on the deposit token and amount. Some deposit transactions require multiple approvals. Existing allowance for the bridge is not checked; allowance is calculated solely based on the specified amount.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
msgDepositCallMsgDeposit call parameters.
DepositAllowanceParams(opts *CallOpts, msg DepositCallMsg) ([]struct {
    Token     common.Address
    Allowance *big.Int
}, error)

Example

Get allowance parameters for depositing token on ETH-based chain.

msg := accounts.DepositCallMsg{
        Token:  common.HexToAddress("<L1 token address>"),
        To:     Receiver,
        Amount: big.NewInt(5),
}

allowanceParams, err := wallet.DepositAllowanceParams(nil, msg)
if err != nil {
    log.Panic(err)
}
bridgeContracts, err := client.BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}
approveTx, err := wallet.ApproveERC20(nil, allowanceParams[0].Token, allowanceParams[0].Allowance, bridgeContracts.L1SharedBridge)
if err != nil {
    log.Panic(err)
}
_, err = bind.WaitMined(context.Background(), ethClient, approveTx)
if err != nil {
    log.Panic(err)
}

Get allowance parameters for depositing ETH on non-ETH-based chain.

msg := accounts.DepositCallMsg{
        Token:  utils.LegacyEthAddress,
        To:     Receiver,
        Amount: big.NewInt(7_000_000_000),
}

allowanceParams, err := wallet.DepositAllowanceParams(nil, msg)
if err != nil {
    log.Panic(err)
}
bridgeContracts, err := client.BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}
approveTx, err := wallet.ApproveERC20(nil, allowanceParams[0].Token, allowanceParams[0].Allowance, bridgeContracts.L1SharedBridge)
if err != nil {
    log.Panic(err)
}
_, err = bind.WaitMined(context.Background(), ethClient, approveTx)
if err != nil {
    log.Panic(err)
}

Get allowance parameters for depositing base token on non-ETH-based chain.

token, err := wallet.BaseToken(nil)
if err != nil {
    log.Panic(err)
}

msg := accounts.DepositCallMsg{
    Token:  token,
    To:     Receiver,
    Amount: big.NewInt(7_000_000_000),
}

allowanceParams, err := wallet.DepositAllowanceParams(nil, msg)
if err != nil {
    log.Panic(err)
}
bridgeContracts, err := client.BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}
approveTx, err := wallet.ApproveERC20(nil, allowanceParams[0].Token, allowanceParams[0].Allowance, bridgeContracts.L1SharedBridge)
if err != nil {
    log.Panic(err)
}
_, err = bind.WaitMined(context.Background(), ethClient, approveTx)
if err != nil {
    log.Panic(err)
}

Get allowance parameters for depositing non-base token on non-ETH-based chain.

msg := accounts.DepositCallMsg{
        Token:  common.HexToAddress("<L1 token address>"),
        To:     Receiver,
        Amount: big.NewInt(5),
}

allowanceParams, err := wallet.DepositAllowanceParams(nil, msg)
if err != nil {
    log.Panic(err)
}
bridgeContracts, err := client.BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}
approveTx, err := wallet.ApproveERC20(nil, allowanceParams[0].Token, allowanceParams[0].Allowance, bridgeContracts.L1SharedBridge)
if err != nil {
    log.Panic(err)
}
_, err = bind.WaitMined(context.Background(), ethClient, approveTx)
if err != nil {
    log.Panic(err)
}
approveTx, err = wallet.ApproveERC20(nil, allowanceParams[1].Token, allowanceParams[1].Allowance, bridgeContracts.L1SharedBridge)
if err != nil {
    log.Panic(err)
}
_, err = bind.WaitMined(context.Background(), ethClient, approveTx)
if err != nil {
    log.Panic(err)
}
ZkSyncEraProvider := "https://testnet.era.zksync.dev"

client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
    log.Panic(err)
}

baseCost, err := wallet.BaseCost(nil, big.NewInt(9000), utils.RequiredL1ToL2GasPerPubdataLimit, gasPrice)
if err != nil {
    log.Panic(err)
}
fmt.Println("Base cost: ", baseCost)

Deposit

Transfers the specified token from the associated account on the L1 network to the target account on the L2 network. The token can be either ETH or any ERC20 token. For ERC20 tokens, enough approved tokens must be associated with the specified L1 bridge (default one or the one defined in BridgeAddress). In this case, depending on is the chain ETH-based or not ApproveERC20 or ApproveBaseERC20 can be enabled to perform token approval. to perform token approval. If there are already enough approved tokens for the L1 bridge, token approval will be skipped. To check the amount of approved tokens for a specific bridge, use the AllowanceL1 method.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txDepositTransactionDeposit transaction parameters.
Deposit(auth *TransactOpts, tx DepositTransaction) (*types.Transaction, error)

Example

Deposit ETH on ETH-based chain.

tx, err := wallet.Deposit(nil, accounts.DepositTransaction{
        To:              wallet.Address(),
        Token:           utils.LegacyEthAddress,
        Amount:          amount,
        RefundRecipient: wallet.Address(),
})
if err != nil {
    log.Panic(err)
}

l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx)
if err != nil {
    log.Panic(err)
}

l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt)
if err != nil {
    log.Panic(err)
}

l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash)
if err != nil {
    log.Panic(err)
}

Deposit token on ETH-based chain.

tx, err := wallet.Deposit(nil, accounts.DepositTransaction{
        To:              wallet.Address(),
        Token:           L1Dai,
        Amount:          amount,
        ApproveERC20:    true,
        RefundRecipient: wallet.Address(),
})
if err != nil {
    log.Panic(err)
}

l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx)
if err != nil {
    log.Panic(err)
}

l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt)
if err != nil {
    log.Panic(err)
}

l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash)
if err != nil {
    log.Panic(err)
}

Deposit ETH on non-ETH-based chain.

tx, err := wallet.Deposit(nil, accounts.DepositTransaction{
        To:               wallet.Address(),
        Token:            utils.LegacyEthAddress,
        Amount:           amount,
        ApproveBaseERC20: true,
        RefundRecipient:  wallet.Address(),
})
if err != nil {
    log.Panic(err)
}

l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx)
if err != nil {
    log.Panic(err)
}

l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt)
if err != nil {
    log.Panic(err)
}

l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash)
if err != nil {
    log.Panic(err)
}

Deposit base token on non-ETH-based chain.

baseToken, err := wallet.BaseToken(nil)
if err != nil {
    log.Panic(err)
}

tx, err := wallet.Deposit(nil, accounts.DepositTransaction{
        To:               wallet.Address(),
        Token:            baseToken,
        Amount:           amount,
        ApproveBaseERC20: true,
        RefundRecipient:  wallet.Address(),
})
if err != nil {
    log.Panic(err)
}

l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx)
if err != nil {
    log.Panic(err)
}

l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt)
if err != nil {
    log.Panic(err)
}

l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash)
if err != nil {
    log.Panic(err)
}

Deposit non-base token on non-ETH-based chain.

tx, err := wallet.Deposit(nil, accounts.DepositTransaction{
  To:               wallet.Address(),
  Token:            L1Dai,
  Amount:           amount,
  ApproveERC20:     true,
  ApproveBaseERC20: true,
  RefundRecipient:  wallet.Address(),
})
if err != nil {
    log.Panic(err)
}

l1Receipt, err := bind.WaitMined(context.Background(), ethClient, tx)
if err != nil {
    log.Panic(err)
}

l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt)
if err != nil {
    log.Panic(err)
}

l2Receipt, err := client.WaitMined(context.Background(), l2Tx.Hash)
if err != nil {
    log.Panic(err)
}

EstimateGasDeposit

Estimates the amount of gas required for a deposit transaction on L1 network. Gas of approving ERC20 token is not included in the estimation.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
msgDepositCallMsgDeposit call parameters.
EstimateGasDeposit(ctx context.Context, msg DepositCallMsg) (uint64, error)

Example

depositGas, err := wallet.EstimateGasDeposit(context.Background(), accounts.DepositCallMsg{
    To:    wallet.Address(),
    Token: utils.EthAddress,
    Amount: big.NewInt(7_000_000_000),
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Deposit gas: ", depositGas)

FullRequiredDepositFee

Retrieves the full needed ETH fee for the deposit on both L1 and L2 networks.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
msgDepositCallMsgDeposit call parameters.
FullRequiredDepositFee(ctx context.Context, msg DepositCallMsg) (*FullDepositFee, error)

Example

fee, err := wallet.FullRequiredDepositFee(context.Background(), accounts.DepositCallMsg{
    To:    wallet.Address(),
    Token: utils.EthAddress,
    Amount: big.NewInt(7_000_000_000),
})
if err != nil {
    log.Panic(err)
}
fmt.Printf("Fee: %+v\n", fee)

FinalizeWithdraw

Proves the inclusion of the L2 -> L1 withdrawal message.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
withdrawalHashcommon.HashHash of the L2 transaction where the withdrawal was initiated.
indexintIn case there were multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize.
FinalizeWithdraw(auth *TransactOpts, withdrawalHash common.Hash, index int) (*types.Transaction, error)

Example

withdrawalHash := common.HexToHash("<tx hash>")
finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawalHash, 0)
if err != nil {
    log.Panic(err)
}
fmt.Println("Finalize withdraw transaction: ", finalizeWithdrawTx.Hash())

IsWithdrawFinalized

Checks if the withdrawal finalized on L1 network.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
withdrawalHashcommon.HashHash of the L2 transaction where the withdrawal was initiated.
indexintIn case there where multiple withdrawals in one transaction, you may pass an index of the withdrawal you want to finalize.
IsWithdrawFinalized(opts *CallOpts, withdrawalHash common.Hash, index int) (bool, error)

Example

withdrawalHash := common.HexToHash("<tx hash>")
isFinalized, err := wallet.IsWithdrawFinalized(nil, withdrawalHash, 0)
if err != nil {
    log.Panic(err)
}
fmt.Println("Is withdrawal finalized: ", isFinalized)

ClaimFailedDeposit

Withdraws funds from the initiated deposit, which failed when finalizing on L2. If the deposit L2 transaction has failed, it sends an L1 transaction calling ClaimFailedDeposit method of the L1 bridge, which results in returning L1 tokens back to the depositor, otherwise throws the error.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
depositHashcommon.HashThe L2 transaction hash of the failed deposit.
ClaimFailedDeposit(auth *TransactOpts, depositHash common.Hash) (*types.Transaction, error)

Example

failedDepositL2Hash := common.HexToHash("<deposit L2 hash>")
cfdTx, err := wallet.ClaimFailedDeposit(nil, failedDepositL2Hash)
if err != nil {
        log.Panic(err)
}
fmt.Println("ClaimFailedDeposit hash: ", cfdTx.Hash)

RequestExecute

Request execution of L2 transaction from L1.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txRequestExecuteTransactionRequest execute transaction parameters.
RequestExecute(auth *TransactOpts, tx RequestExecuteTransaction) (*types.Transaction, error)

Example

contractAddress := common.HexToAddress("<Contract address>")
requestExecuteTx, err := wallet.RequestExecute(nil, accounts.RequestExecuteTransaction{
    ContractAddress:   contractAddress,
    L2Value:           big.NewInt(7_000_000_000),
    L2GasLimit:        big.NewInt(90_000),
    GasPerPubdataByte: utils.RequiredL1ToL2GasPerPubdataLimit,
    RefundRecipient:   to,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Request execute tx: ", requestExecuteTx.Hash())

EstimateGasRequestExecute

Estimates the amount of gas required for a request execute transaction.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
msgRequestExecuteCallMsgRequest execute call parameters.
EstimateGasRequestExecute(ctx context.Context, msg RequestExecuteCallMsg) (uint64, error)

Example

contractAddress := common.HexToAddress("<Contract address>")
gas, err := wallet.EstimateGasRequestExecute(context.Background(), accounts.RequestExecuteCallMsg{
    ContractAddress:   contractAddress,
    L2Value:           big.NewInt(7_000_000_000),
    L2GasLimit:        big.NewInt(90_000),
    GasPerPubdataByte: utils.RequiredL1ToL2GasPerPubdataLimit,
    RefundRecipient:   to,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Gas: ", gas)

RequestExecuteAllowanceParams

Returns the parameters for the approval token transaction based on the request execute transaction. Existing allowance for the bridge is not checked; allowance is calculated solely based on the specified transaction.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
msgRequestExecuteCallMsgRequest execute call parameters.
RequestExecuteAllowanceParams(opts *CallOpts, msg RequestExecuteCallMsg) (AllowanceParams, error)

Example

msg := accounts.RequestExecuteCallMsg{
  ContractAddress: wallet.Address(),
  L2Value:         big.NewInt(7_000_000_000),
  Value:           big.NewInt(0),
}
allowanceParams, err := wallet.RequestExecuteAllowanceParams(nil, msg)
if err != nil {
    log.Panic(err)
}

bridgeContracts, err := client.BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}

approveTx, err := wallet.ApproveERC20(nil, allowanceParams.Token, allowanceParams.Allowance, bridgeContracts.L1SharedBridge)
if err != nil {
    log.Panic(err)
}

_, err = bind.WaitMined(context.Background(), ethClient, approveTx)
if err != nil {
    log.Panic(err)
}

EstimateCustomBridgeDepositL2Gas

Used by EstimateDefaultBridgeDepositL2Gas to estimate L2 gas required for token bridging via a custom ERC20 bridge.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
l1BridgeAddresscommon.AddressL1 bridge address.
l2BridgeAddresscommon.AddressL2 bridge address.
tokencommon.AddressToken address.
amount*big.IntDeposit amount.
tocommon.AddressRecipient address.
bridgeData[]byteBridge data.
fromcommon.Address (optional)Sender address.
gasPerPubdataByte*big.Int (optional)Current gas per byte of pubdata.
EstimateCustomBridgeDepositL2Gas(ctx context.Context, l1BridgeAddress, l2BridgeAddress, token common.Address,
    amount *big.Int, to common.Address, bridgeData []byte, from common.Address, gasPerPubdataByte *big.Int) (uint64, error)

Example

L1BridgeAddress := common.HexToAddress("<Bridge address>")
Token := common.HexToAddress("<Token address>")
From := common.HexToAddress("<Sender address>")
To := common.HexToAddress("<Receipt address>")


bridge, err := l1bridge.NewIL1Bridge(L1BridgeAddress, ethClient)
if err != nil {
    log.Panic(err)
}
l2BridgeAddress, err := bridge.L2Bridge(nil)
if err != nil {
    log.Panic(err)
}
customBridgeData, err := utils.Erc20DefaultBridgeData(Token, ethClient)
if err != nil {
    log.Panic(err)
}

gas, err := wallet1.EstimateCustomBridgeDepositL2Gas(context.Background(), L1BridgeAddress, l2BridgeAddress, Token,
    big.NewInt(7), To, customBridgeData, From, utils.RequiredL1ToL2GasPerPubdataLimit)
if err != nil {
    log.Panic(err)
}
fmt.Println("L2 gas: ", gas)

EstimateDefaultBridgeDepositL2Gas

Returns an estimation of L2 gas required for token bridging via the default ERC20 bridge.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tokencommon.AddressToken address.
amount*big.IntDeposit amount.
tocommon.AddressRecipient address.
fromcommon.Address (optional)Sender address.
gasPerPubdataByte*big.Int (optional)Current gas per byte of pubdata.
EstimateDefaultBridgeDepositL2Gas(ctx context.Context, token common.Address, amount *big.Int,
    to, from common.Address, gasPerPubdataByte *big.Int) (uint64, error)

Example

Token := common.HexToAddress("<Token address>")
From := common.HexToAddress("<Sender address>")
To := common.HexToAddress("<Receipt address>")
gas, err := wallet1.EstimateDefaultBridgeDepositL2Gas(
    context.Background(), Token, big.NewInt(7), To, From, utils.RequiredL1ToL2GasPerPubdataLimit,
)
if err != nil {
    log.Panic(err)
}
fmt.Println("L2 gas: ", gas)

WalletL2

Init

Creates an instance of WalletL2 associated with the account provided by the raw private key.

func NewWalletL2(rawPrivateKey []byte, client *clients.Client) (*WalletL2, error)

Creates an instance of WalletL2. The client can be optional; if it is not provided, only SignTransaction, Address, Signer can be performed, as the rest of the functionalities require communication to the network.

func NewWalletL2FromSigner(signer *Signer, client *clients.Client) (*WalletL2, error)

Example

PrivateKey     := os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider := "https://testnet.era.zksync.dev"

client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client)
if err != nil {
    log.Panic(err)
}

Address

Returns the address of the associated account.

Address() common.Address

Example

fmt.Println("Address: ", wallet.Address())

Signer

Returns the signer of the associated account.

Signer() Signer

Example

fmt.Printf("Signer %+v\n", wallet.Signer())

Balance

Returns the balance of the specified token that can be either ETH or any ERC20 token. The block number can be nil, in which case the balance is taken from the latest known block.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tokencommon.AddressL2 token address.
at*big.IntBlock number.
Balance(ctx context.Context, token common.Address, at *big.Int) (*big.Int, error)

Example

balance, err := wallet.Balance(context.Background(), utils.EthAddress, nil)
if err != nil {
    log.Panic(err)
}
fmt.Println("Balance: ", balance)

AllBalances

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

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
AllBalances(ctx context.Context) (map[common.Address]*big.Int, error)

Example

balances, err := wallet.AllBalances(context.Background())
if err != nil {
    log.Panic(err)
}
fmt.Printf("Balances: %+v\n", balances)

L2BridgeContracts

Returns L2 bridge contracts.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
L2BridgeContracts(ctx context.Context) (*zkTypes.L2BridgeContracts, error)

Example

contracts, err := wallet.L2BridgeContracts(context.Background())
if err != nil {
    log.Panic(err)
}

DeploymentNonce

Returns the deployment nonce of the account.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
func (a *WalletL2) DeploymentNonce(opts *CallOpts) (*big.Int, error)

Example

deploymentNonce, err := wallet.DeploymentNonce(nil)
if err != nil {
    log.Panic(err)
}

IsBaseToken

Returns whether the token is the base token.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tokencommon.AddressToken address.
IsBaseToken(ctx context.Context, token common.Address) (bool, error)

Example

isBaseToken, err := wallet.IsBaseToken(
  context.Background(),
  common.HexToAddress("0x5C221E77624690fff6dd741493D735a17716c26B")
)
if err != nil {
    log.Panic(err)
}
fmt.Println("Is base token: ", isBaseToken)

Withdraw

Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 network to the target account on L1 network.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txWithdrawalTransactionWithdrawal transaction parameters.
Withdraw(auth *TransactOpts, tx WithdrawalTransaction) (*types.Transaction, error)

Example

tx, err := wallet.Withdraw(nil, accounts.WithdrawalTransaction{
    To:     wallet.Address(),
    Amount: big.NewInt(1_000_000_000_000_000_000),
    Token:  utils.EthAddress,
})
if err != nil {
    panic(err)
}
fmt.Println("Withdraw transaction: ", tx.Hash())

EstimateGasWithdraw

Estimates the amount of gas required for a withdrawal transaction.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
msgWithdrawalCallMsgWithdrawal call parameters.
EstimateGasWithdraw(ctx context.Context, msg WithdrawalCallMsg) (uint64, error)

Example

gas, err := wallet.EstimateGasWithdraw(context.Background(), accounts.WithdrawalCallMsg{
    To:   wallet.Address(),
    Amount: big.NewInt(7_000_000),
    Token:  utils.EthAddress,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Gas: ", gas)

Transfer

Moves the ETH or any ERC20 token from the associated account to the target account.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txTransferTransactionTransfer transaction parameters.
Transfer(auth *TransactOpts, tx TransferTransaction) (*types.Transaction, error)

Example

tx, err := wallet.Transfer(nil, accounts.TransferTransaction{
    To:     common.HexToAddress("<Receipt address>"),
    Amount: big.NewInt(7_000_000_000),
    Token:  utils.EthAddress,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Transaction: ", tx.Hash())

EstimateGasTransfer

Estimates the amount of gas required for a transfer transaction.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
msgTransferCallMsgTransfer call parameters.
EstimateGasTransfer(ctx context.Context, msg TransferCallMsg) (uint64, error)

Example

gas, err := wallet.EstimateGasTransfer(context.Background(), accounts.TransferCallMsg{
    To:   common.HexToAddress("<Receipt address>"),
    Amount: big.NewInt(7_000_000_000),
    Token:  utils.EthAddress,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Gas: ", gas)

CallContract

Executes a message call for EIP-712 transaction, which is directly executed in the VM of the node, but never mined into the blockchain.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
msgCallMsgContains parameters for contract call using EIP-712 transaction.
blockNumber*big.Int (optional)Selects the block height at which the call runs. It can be nil, in which case the code is taken from the latest known block. Note that state from very old blocks might not be available.
CallContract(ctx context.Context, msg CallMsg, blockNumber *big.Int) ([]byte, error)

Example

// The Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")

tokenAbi, err := erc20.IERC20MetaData.GetAbi()
if err != nil {
    log.Panic(err)
}
symbolCalldata, err := tokenAbi.Pack("symbol")
if err != nil {
    log.Panic(err)
}

result, err := wallet.CallContract(context.Background(), types.CallMsg{
    CallMsg: ethereum.CallMsg{
        To:   &TokenAddress,
        Data: symbolCalldata,
    },
}, nil)
if err != nil {
    log.Panic(err)
}
unpack, err := tokenAbi.Unpack("symbol", result)
if err != nil {
    log.Panic(err)
}
symbol := *abi.ConvertType(unpack[0], new(string)).(*string)
fmt.Println("Symbol: ", symbol)

PopulateTransaction

Designed for users who prefer a simplified approach by providing only the necessary data to create a valid EIP-712 transaction. The only required fields are Transaction.To and either Transaction.Data or Transaction.Value (or both, if the method is payable). Any other fields that are not set will be prepared by this method.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
txTransactionTransaction parameters.
PopulateTransaction(ctx context.Context, tx Transaction) (*zkTypes.Transaction712, error)

Example

// The Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")
// Paymaster for Crown token on testnet
PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46")
ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618")

abi, err := erc20.IERC20MetaData.GetAbi()
if err != nil {
    log.Panic(err)
}

// Encode transfer function from token contract
calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7))
if err != nil {
    log.Panic(err)
}

preparedTx, err := wallet.PopulateTransaction(context.Background(), &accounts.Transaction{
    To:   &TokenAddress,
    Data: calldata,
})
fmt.Printf("Prepared tx: %+v\n", preparedTx)

SignTransaction

Returns a signed transaction that is ready to be broadcast to the network. The input transaction must be a valid transaction with all fields having appropriate values. To obtain a valid transaction, you can use the PopulateTransaction method.

Inputs

ParameterTypeDescription
txzkTypes.Transaction712EIP-712 transaction parameters.
SignTransaction(tx *zkTypes.Transaction712) ([]byte, error)

Example

// The Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")
// Paymaster for Crown token on testnet
PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46")
ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618")

abi, err := erc20.IERC20MetaData.GetAbi()
if err != nil {
    log.Panic(err)
}

// Encode transfer function from token contract
calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7))
if err != nil {
    log.Panic(err)
}

preparedTx, err := wallet.PopulateTransaction(context.Background(), &accounts.Transaction{
    To:   &TokenAddress,
    Data: calldata,
})

signedTx, err := wallet.SignTransaction(preparedTx)
if err != nil {
    log.Panic(err)
}
fmt.Printf("Signed tx: %+v\n", signedTx)

SendTransaction

Injects a transaction into the pending pool for execution. Any unset transaction fields are prepared using the PopulateTransaction method.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
txTransactionTransaction parameters.
SendTransaction(ctx context.Context, tx *Transaction) (common.Hash, error)

Example

// The Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")
// Paymaster for Crown token on testnet
PaymasterAddress := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46")
ReceiptAddress := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618")

abi, err := erc20.IERC20MetaData.GetAbi()
if err != nil {
    log.Panic(err)
}

// Encode transfer function from token contract
calldata, err := abi.Pack("transfer", ReceiptAddress, big.NewInt(7))
if err != nil {
    log.Panic(err)
}

// Create paymaster parameters with encoded paymaster input
paymasterParams, err := utils.GetPaymasterParams(
    PaymasterAddress,
    &zkTypes.ApprovalBasedPaymasterInput{
        Token:            TokenAddress,
        MinimalAllowance: big.NewInt(1),
        InnerInput:       []byte{},
    })
if err != nil {
    log.Panic(err)
}

hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{
    To:   &TokenAddress,
    Data: calldata,
    Meta: &types.Eip712Meta{
        PaymasterParams: paymasterParams,
    },
})
if err != nil {
    log.Panic(err)
}

_, err = client.WaitMined(context.Background(), hash)
if err != nil {
    log.Panic(err)
}

fmt.Println("Tx: ", hash)

BaseDeployer

Init

Creates an instance of BaseDeployer based on provided AdapterL2.

func NewBaseDeployer(adapter *AdapterL2) *BaseDeployer

Deploy

Deploys smart contract using CREATE2 method.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txCreate2TransactionCREATE2 transaction parameters.
Deploy(auth *TransactOpts, tx Create2Transaction) (common.Hash, error)

Example

bytecode, err := os.ReadFile("Storage.zbin")
if err != nil {
    log.Panic(err)
}

//Deploy smart contract
hash, err := wallet.Deploy(nil, accounts.Create2Transaction{Bytecode: bytecode})
if err != nil {
    panic(err)
}
fmt.Println("Transaction: ", hash)

DeployWithCreate

Deploys smart contract using CREATE method.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txCreateTransactionCREATE transaction parameters.
DeployWithCreate(auth *TransactOpts, tx CreateTransaction) (common.Hash, error)

Example

bytecode, err := os.ReadFile("Storage.zbin")
if err != nil {
    log.Panic(err)
}

//Deploy smart contract
hash, err := wallet.DeployWithCreate(nil, accounts.CreateTransaction{Bytecode: bytecode})
if err != nil {
    panic(err)
}
fmt.Println("Transaction: ", hash)

DeployAccount

Deploys smart account using CREATE2 method.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txCreate2TransactionCREATE2 transaction parameters.
DeployAccount(auth *TransactOpts, tx Create2Transaction) (common.Hash, error)

Example

# Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")

_, paymasterAbi, bytecode, err := utils.ReadStandardJson("Paymaster.json")
if err != nil {
    log.Panic(err)
}

// Encode paymaster constructor
constructor, err := paymasterAbi.Pack("", common.HexToAddress(TokenAddress))
if err != nil {
    log.Panic(err)
}

// Deploy paymaster contract
hash, err := wallet.DeployAccount(nil, accounts.Create2Transaction{Bytecode: bytecode, Calldata: constructor})
if err != nil {
    log.Panic(err)
}
if err != nil {
    log.Panic(err)
}
fmt.Println("Transaction: ", hash)

DeployAccountWithCreate

Deploys smart account using CREATE method.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txCreateTransactionCREATE transaction parameters.
DeployAccountWithCreate(auth *TransactOpts, tx CreateTransaction) (common.Hash, error)

Example

# Crown token on testnet
TokenAddress := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F")

_, paymasterAbi, bytecode, err := utils.ReadStandardJson("Paymaster.json")
if err != nil {
    log.Panic(err)
}

constructor, err := paymasterAbi.Pack("", common.HexToAddress(TokenAddress))
if err != nil {
    log.Panic(err)
}

// Deploy paymaster contract
hash, err := wallet.DeployAccountWithCreate(nil, accounts.CreateTransaction{
    Bytecode: bytecode,
    Calldata: constructor,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Transaction: ", hash)

Wallet

It contains the same functions as WalletL1, WalletL2, and BaseDeployer since it implements the Adapter interface, and the usage of those methods is the same.

Init

Creates an instance of Wallet associated with the account provided by the rawPrivateKey. The clientL1 parameters is optional; if not provided, only methods from AdapterL2 and Deployer interfaces can be used, as the rest of the functionalities require communication with the L1 network. A Wallet can be configured to communicate with L1 networks by using and ConnectL1 method.

func NewWallet(rawPrivateKey []byte, clientL2 *clients.Client, clientL1 *ethclient.Client) (*Wallet, error)

Creates an instance of Wallet associated with the account provided by the signer. The clientL2 and clientL1 parameters are optional; if not provided, only SignTransaction, Address and Signer methods can be used, as the rest of the functionalities require communication with the network. A wallet that contains only a signer can be configured to communicate with L2 and L1 networks by using Connect and ConnectL1, respectively.

func NewWalletFromSigner(signer Signer, clientL2 *clients.Client, clientL1 *ethclient.Client) (*Wallet, error)

Creates a new instance of Wallet based on the provided mnemonic phrase. The clientL2 and clientL1 parameters are optional, and can be configured with Connect and ConnectL1, respectively.

func NewWalletFromMnemonic(mnemonic string, chainId int64, clientL2 *clients.Client, clientL1 *ethclient.Client) (*Wallet, error)

Creates a new instance of Wallet based on the provided private key of the account and chain ID. The clientL2 and clientL1 parameters are optional, and can be configured with Connect and ConnectL1, respectively.

func NewWalletFromRawPrivateKey(rawPk []byte, chainId int64, clientL2 *clients.Client, clientL1 *ethclient.Client) (*Wallet, error)

Creates an instance of Wallet with a randomly generated account. The clientL2 and clientL1 parameters are optional, and can be configured with Connect and ConnectL1, respectively.

func NewRandomWallet(chainId int64, clientL2 *clients.Client, clientL1 *ethclient.Client) (*Wallet, error)

Example

PrivateKey     := os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider := "https://sepolia.era.zksync.dev"
EthereumProvider := "https://rpc.ankr.com/eth_sepolia"

client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

ethClient, err := ethclient.Dial(EthereumProvider)
if err != nil {
    log.Panic(err)
}
defer ethClient.Close()

wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient)
if err != nil {
    log.Panic(err)
}

chainID, err := client.ChainID(context.Background())
if err != nil {
    log.Panic(err)
}
wallet, err = accounts.NewRandomWallet(chainID.Int64(),nil,nil)
if err != nil {
    log.Panic(err)
}

Connect

Returns a new instance of Wallet with the provided client for the L2 network.

Inputs

ParameterTypeDescription
client*clients.ClientL2 client.
Connect(client *clients.Client) (*Wallet, error)

Example

PrivateKey     := os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider := "https://testnet.era.zksync.dev"

client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

chainID, err := client.ChainID(context.Background())
if err != nil {
    log.Panic(err)
}

wallet, err := accounts.NewRandomWallet(chainID, nil, nil)
if err != nil {
    log.Panic(err)
}

// create new wallet with connection to L2
wallet, err = wallet.Connect(&client)
if err != nil {
    log.Panic(err)
}

ConnectL1

Returns a new instance of Wallet with the provided client for the L1 network.

Inputs

ParameterTypeDescription
client*ethclient.ClientL1 client.
ConnectL1(client *ethclient.Client) (*Wallet, error)

Example

chainID, err := client.ChainID(context.Background())
if err != nil {
    log.Panic(err)
}

wallet, err = accounts.NewRandomWallet(chainID, nil, nil)
if err != nil {
    log.Panic(err)
}

// create new wallet with connection to L1
wallet, err = wallet.Connect(&ethClient)
if err != nil {
    log.Panic(err)
}

Nonce

Returns the account nonce of the associated account. The block number can be nil, in which case the nonce is taken from the latest known block.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
blockNumber*big.Int (optional)Block number.
Nonce(ctx context.Context, blockNumber *big.Int) (uint64, error)

Example

nonce, err := wallet.Nonce(context.Background(), big.NewInt(9000))
if err != nil {
    log.Panic(err)
}
fmt.Println("Nonce: ", nonce)

PendingNonce

Returns the account nonce of the associated account in the pending state. This is the nonce that should be used for the next transaction.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
PendingNonce(ctx context.Context) (uint64, error)

Example

nonce, err := wallet.PendingNonce(context.Background())
if err != nil {
    log.Panic(err)
}
fmt.Println("Nonce: ", nonce)

SmartAccount

A SmartAccount is a signer which can be configured to sign various payloads using a provided secret. The secret can be in any form, allowing for flexibility when working with different account implementations. The SmartAccount is bound to a specific address and provides the ability to define custom method for populating transactions and custom signing method used for signing messages, typed data, and transactions.

Init

Creates a new SmartAccount instance. By default, it uses SignPayloadWithECDSA as a signer and PopulateTransactionECDSA as a builder and requires private key in hex format to be provided.

Inputs

ParameterTypeDescription
addresscommon.AddressAccount address.
secretinterface{}Secret used for signing.
signer*PayloadSignerFunction used for signing payload.
builder*TransactionBuilderFunction used for populating transaction.
client*clients.BaseClientThe client to connect to. Can be nil for offline usage.

func NewSmartAccount(
    address common.Address,
    secret interface{},
    signer *PayloadSigner,
    builder *TransactionBuilder,
    client *clients.BaseClient) *SmartAccount

Examples

privateKey     := os.Getenv("PRIVATE_KEY")
address := common.HexToAddress("<ACCOUNT ADDRESS>")
ZkSyncEraProvider := "https://sepolia.era.zksync.dev"

client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

account := accounts.NewSmartAccount(
    address,
    privateKey,
    &accounts.SignPayloadWithECDSA,
    &accounts.PopulateTransactionECDSA,
nil)

NewECDSASmartAccount

Creates a SmartAccount instance that uses single ECDSA key for signing payload.

ParameterTypeDescription
addresscommon.AddressAccount address.
privateKeystringThe ECDSA private key.
client*clients.BaseClientThe client to connect to. Can be nil for offline usage.

func NewECDSASmartAccount(address common.Address, privateKey string, client *clients.BaseClient) *SmartAccount

Example

privateKey := os.Getenv("PRIVATE_KEY")
address := common.HexToAddress("<ACCOUNT ADDRESS>")
ZkSyncEraProvider := "https://sepolia.era.zksync.dev"

client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

account := accounts.NewECDSASmartAccount(address, privateKey, client)

NewMultisigECDSASmartAccount

Creates a SmartAccount instance that uses multiple ECDSA keys for signing payloads. The signature is generated by concatenating signatures created by signing with each key individually.

ParameterTypeDescription
addresscommon.AddressAccount address.
privateKeys[]stringThe list of the ECDSA private keys.
client*clients.BaseClientThe client to connect to. Can be nil for offline usage.
NewMultisigECDSASmartAccount(address common.Address, privateKeys []string, client *clients.BaseClient) *SmartAccount

Example

privateKey1 := os.Getenv("PRIVATE_KEY1")
privateKey2 := os.Getenv("PRIVATE_KEY2")
address := common.HexToAddress("<ACCOUNT ADDRESS>")
ZkSyncEraProvider := "https://sepolia.era.zksync.dev"

client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

account := accounts.NewMultisigECDSASmartAccount(address, []string{privateKey1, privateKey2}, client)

Connect

Creates a new instance of SmartAccount connected to a client or detached from any provider if nil is provided.

Inputs

ParameterTypeDescription
client*clients.DialBaseThe client to connect the SmartAccount to. If nil, the SmartAccount will be detached from any provider.
Connect(client *clients.BaseClient) *SmartAccount

Example

privateKey     := os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider := "https://testnet.era.zksync.dev"

client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, nil)
account = account.Connect(client)

Address

Returns the address of the associated account.

Address() common.Address

Example

fmt.Println("Address: ", account.Address())

Balance

Returns the balance of the specified token that can be either ETH or any ERC20 token. The block number can be nil, in which case the balance is taken from the latest known block.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tokencommon.AddressL2 token address.
at*big.IntBlock number.
Balance(ctx context.Context, token common.Address, at *big.Int) (*big.Int, error)

Example

balance, err := account.Balance(context.Background(), utils.EthAddress, nil)
if err != nil {
    log.Panic(err)
}
fmt.Println("Balance: ", balance)

AllBalances

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

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
AllBalances(ctx context.Context) (map[common.Address]*big.Int, error)

Example

balances, err := account.AllBalances(context.Background())
if err != nil {
    log.Panic(err)
}
fmt.Printf("Balances: %+v\n", balances)

Nonce

Returns the account nonce of the associated account. The block number can be nil, in which case the nonce is taken from the latest known block.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
blockNumber*big.Int (optional)Block number.
Nonce(ctx context.Context, blockNumber *big.Int) (uint64, error)

Example

nonce, err := account.Nonce(context.Background(), big.NewInt(9000))
if err != nil {
    log.Panic(err)
}
fmt.Println("Nonce: ", nonce)

DeploymentNonce

Returns the deployment nonce of the account.

Inputs

ParameterTypeDescription
optsCallOpts (optional)Call options.
DeploymentNonce(opts *CallOpts) (*big.Int, error)

Example

deploymentNonce, err := account.DeploymentNonce(nil)
if err != nil {
    log.Panic(err)
}

PopulateTransaction

Populates the transaction tx using the provided TransactionBuilder function. If tx.From is not set, it sets the value from the Address() method which can be utilized in the TransactionBuilder function.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tx*zkTypes.Transaction712The transaction that needs to be populated.
PopulateTransaction(ctx context.Context, tx *zkTypes.Transaction712) error

Example

address := common.HexToAddress("<ACCOUNT ADDRESS>")
tx := &zkTypes.Transaction712{
  To:    &address,
  Value: big.NewInt(7_000_000_000),
}

err = account.PopulateTransaction(context.Background(), tx)
if err != nil {
    log.Panic(err)
}

SignTransaction

Returns a signed transaction that is ready to be broadcast to the network. The PopulateTransaction method is called first to ensure that all necessary properties for the transaction to be valid have been populated.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tx*zkTypes.Transaction712The transaction that needs to be signed.

SignTransaction(ctx context.Context, tx *zkTypes.Transaction712) ([]byte, error)

Example

address := common.HexToAddress("<ACCOUNT ADDRESS>")
signedTx, err := account.SignTransaction(context.Background(), &zkTypes.Transaction712{
    To:    &address,
    Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH
})
if err != nil {
  log.Panic(err)
}

SendTransaction

Injects a transaction into the pending pool for execution. The SignTransaction is called first to ensure transaction is properly signed.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tx*zkTypes.Transaction712The transaction that needs to be signed.
SendTransaction(ctx context.Context, tx *zkTypes.Transaction712) (common.Hash, error)

Example

address := common.HexToAddress("<ACCOUNT ADDRESS>")
txHash, err := account.SendTransaction(context.Background(), &zkTypes.Transaction712{
    To:    &address,
    Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH
})
if err != nil {
  log.Panic(err)
}

SignMessage

Signs a message using the provided PayloadSigner function.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
message[]byteThe message that needs to be signed.
SignMessage(ctx context.Context, message []byte) ([]byte, error)

Example

signature, err := account.SignMessage(context.Background(), []byte("Hello World!"))
if err != nil {
  log.Panic(err)
}

SignTypedData

signs a typed data using the provided PayloadSigner function.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
typedDataapitypes.TypedDataThe typed data that needs to be signed.
SignTypedData(ctx context.Context, typedData apitypes.TypedData) ([]byte, error)

Example

signature, err := account.SignTypedData(context.Background(), apitypes.TypedData{
  Domain: apitypes.TypedDataDomain{
    Name:    "Example",
    Version: "1",
    ChainId: math.NewHexOrDecimal256(270),
  },
  Types: apitypes.Types{
    "Person": []apitypes.Type{
      {Name: "name", Type: "string"},
      {Name: "age", Type: "uint8"},
    },
    "EIP712Domain": []apitypes.Type{
      {Name: "name", Type: "string"},
      {Name: "version", Type: "string"},
      {Name: "chainId", Type: "uint256"},
    },
  },
  PrimaryType: "Person",
  Message: apitypes.TypedDataMessage{
    "name": "John",
    "age":  hexutil.EncodeUint64(30),
  },
})
if err != nil {
  log.Panic(err)
}

Withdraw

Initiates the withdrawal process which withdraws ETH or any ERC20 token from the associated account on L2 network to the target account on L1 network.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txWithdrawalTransactionWithdrawal transaction parameters.
Withdraw(auth *TransactOpts, tx WithdrawalTransaction) (common.Hash, error)

Examples

Withdraw ETH.

txHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{
    To:     account.Address(),
    Amount: big.NewInt(1_000_000_000_000_000_000),
    Token:  utils.LegacyEthAddress,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Withdraw transaction: ", txHash)

Withdraw ETH using paymaster to facilitate fee payment with an ERC20 token.

token := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F"); // Crown token which can be minted for free
paymaster := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46"); // Paymaster for Crown token

paymasterParams, err := utils.GetPaymasterParams(
        paymaster,
        &zkTypes.ApprovalBasedPaymasterInput{
            Token:            token,
            MinimalAllowance: big.NewInt(1),
            InnerInput:       []byte{},
})
if err != nil {
    log.Panic(err)
}

txHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{
        To:              account.Address(),
        Amount:          big.NewInt(1_000_000_000_000_000_000),
        Token:           utils.LegacyEthAddress,
        PaymasterParams: paymasterParams,
    })

Transfer

Moves the ETH or any ERC20 token from the associated account to the target account.

Inputs

ParameterTypeDescription
auth*TransactOpts (optional)Transaction options.
txTransferTransactionTransfer transaction parameters.
Transfer(auth *TransactOpts, tx TransferTransaction) (common.Hash, error)

Examples

Transfer ETH.

txHash, err := account.Transfer(nil, accounts.TransferTransaction{
  To:     Address2,
  Amount: amount,
  Token:  utils.LegacyEthAddress,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Transaction: ", txHash)

Transfer ETH using paymaster to facilitate fee payment with an ERC20 token.

token := common.HexToAddress("0x927488F48ffbc32112F1fF721759649A89721F8F"); // Crown token which can be minted for free
paymaster := common.HexToAddress("0x13D0D8550769f59aa241a41897D4859c87f7Dd46"); // Paymaster for Crown token

paymasterParams, err := utils.GetPaymasterParams(
  paymaster,
  &zkTypes.ApprovalBasedPaymasterInput{
    Token:            token,
    MinimalAllowance: big.NewInt(1),
    InnerInput:       []byte{},
})
if err != nil {
  log.Panic(err)
}

txHash, err := account.Transfer(nil, accounts.TransferTransaction{
  To:     Address2,
  Amount: amount,
  Token:  utils.LegacyEthAddress,
  PaymasterParams: paymasterParams,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Transaction: ", txHash)

Made with ❤️ by the ZKsync Community