SmartAccount

Flexible signer for various payloads

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.

Address

Returns the address of the associated account.

Address() common.Address

Example

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

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)

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
optsCallOpts (optional)Call options.
tokencommon.AddressL2 token address.
Balance(opts *CallOpts, token common.Address) (*big.Int, error)

Example

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

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.Client) *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)

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)
}

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.ClientThe client to connect to. Can be nil for offline usage.

func NewSmartAccount(
  address common.Address,
  secret interface{},
  signer *PayloadSigner,
  builder *TransactionBuilder,
  client *clients.Client) *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)

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)

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.TransactionThe transaction that needs to be populated.
PopulateTransaction(ctx context.Context, tx *zkTypes.Transaction) error

Example

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

err = account.PopulateTransaction(context.Background(), tx)
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.TransactionThe transaction that needs to be signed.
SendTransaction(ctx context.Context, tx *zkTypes.Transaction) (common.Hash, error)

Example

address := common.HexToAddress("<ACCOUNT ADDRESS>")
txHash, err := account.SendTransaction(context.Background(), &zkTypes.Transaction{
  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)
}

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.TransactionThe transaction that needs to be signed.

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

Example

address := common.HexToAddress("<ACCOUNT ADDRESS>")
signedTx, err := account.SignTransaction(context.Background(), &zkTypes.Transaction{
  To:    &address,
  Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH
})
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)
}

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)

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,
})

Made with ❤️ by the ZKsync Community