Giter Site home page Giter Site logo

zksync2-go's Introduction

๐Ÿš€ zksync2-go Golang SDK ๐Ÿš€

License License: Apache 2.0 Contributor Covenant Contributions Welcome X (formerly Twitter) Follow

ZKsync Era Logo

In order to provide easy access to all the features of ZKsync Era, the zksync2-go Golang SDK was created, which is made in a way that has an interface very similar to those of geth. In fact, geth is a dependency of our library and most of the objects exported by zksync2-go ( e.g. Wallet, Client etc.) inherit from the corresponding geth objects and override only the fields that need to be changed.

While most of the existing SDKs should work out of the box, deploying smart contracts or using unique ZKsync Era features, like account abstraction, requires providing additional fields to those that Ethereum transactions have by default.

The library is made in such a way that after replacing geth with zksync2-go most client apps will work out of box.

๐Ÿ”— For a detailed walkthrough, refer to the official documentation.

๐Ÿ“Œ Overview

To begin, it is useful to have a basic understanding of the types of objects available and what they are responsible for, at a high level:

  • Client provides connection to the ZKsync Era blockchain, which allows querying the blockchain state, such as account, block or transaction details, querying event logs or evaluating read-only code using call. Additionally, the client facilitates writing to the blockchain by sending transactions.
  • Wallet wraps all operations that interact with an account. An account generally has a private key, which can be used to sign a variety of types of payloads. It provides easy usage of the most common features.

๐Ÿ›  Prerequisites

๐Ÿ“ฅ Installation & Setup

go get github.com/zksync-sdk/zksync2-go

๐Ÿ“ Examples

The complete examples with various use cases are available here.

Connect to the ZKsync Era network:

import (
    "github.com/ethereum/go-ethereum/ethclient"
    "github.com/zksync-sdk/zksync2-go/clients"
    "log"
    "os"
)

var (
    ZkSyncProvider   = "https://sepolia.era.zksync.dev" // zkSync Era testnet  
    EthereumProvider = "https://rpc.ankr.com/eth_sepolia" // Sepolia testnet
)
// Connect to ZKsync network
client, err := clients.Dial(ZkSyncProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

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

Get the latest block number

blockNumber, err := client.BlockNumber(context.Background())
if err != nil {
    log.Panic(err)
}
fmt.Println("Block number: ", blockNumber)

Get the latest block

block, err := client.BlockByNumber(context.Background(), nil)
if err != nil {
    log.Panic(err)
}
fmt.Printf("%+v\n", block)

Create a wallet

privateKey := os.Getenv("PRIVATE_KEY")
w, err := accounts.NewWallet(common.Hex2Bytes(privateKey), &client, ethClient)
if err != nil {
    log.Panic(err)
}

Check account balances

balance, err := w.Balance(context.Background(), utils.EthAddress, nil) // balance on ZKsync Era network
if err != nil {
    log.Panic(err)
}
fmt.Println("Balance: ", balance)

balanceL1, err := w.BalanceL1(nil, utils.EthAddress) // balance on goerli network
if err != nil {
    log.Panic(err)
}
fmt.Println("Balance L1: ", balanceL1)

Transfer funds

Transfer funds among accounts on L2 network.

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

tx, err := w.Transfer(accounts.TransferTransaction{
    To:     receiver.Address(),
    Amount: big.NewInt(7_000_000_000_000_000_000),
    Token:  utils.EthAddress,
})
if err != nil {
    log.Panic(err)
}
fmt.Println("Transaction: ", tx.Hash())

Deposit funds

Transfer funds from L1 to L2 network.

tx, err := w.Deposit(accounts.DepositTransaction{
    Token:  utils.EthAddress, 
    Amount: big.NewInt(2_000_000_000_000_000_000),
    To:     w.Address(),
})
if err != nil {
    log.Panic(err)
}
fmt.Println("L1 transaction: ", tx.Hash())

Withdraw funds

Transfer funds from L2 to L1 network.

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

๐Ÿค– Running tests

In order to run test you need to run local-setup on your machine. For running tests, use:

make run-tests

๐Ÿค Contributing

We welcome contributions from the community! If you're interested in contributing to the zksync2-go Golang SDK, please take a look at our CONTRIBUTING.md for guidelines and details on the process.

Thank you for making zksync2-go Golang SDK better! ๐Ÿ™Œ

zksync2-go's People

Contributors

danijeltxfusion avatar eteissonniere avatar maximfischuk avatar semantic-release-bot avatar tiennampham23 avatar vickmellon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

zksync2-go's Issues

`/tests` Missing

๐Ÿ› Bug Report for zksync2-js JavaScript SDK

๐Ÿ“ Description

Repository is missing tests to assert functionality. This issue is meant to track this missing implementation which is currently blocked by a bug in https://github.com/matter-labs/local-setup that errors when the functions zks_getMainContract and zks_estimateGasL1toL2 are called.

BlockByNumber gives various errors

When using BlockByNumber function, it either gives server returned empty transaction list but block header indicates transactions or invalid transaction v, r, s values. Code Snippet:

	client, err := zksync2.NewDefaultProvider("https://mainnet.era.zksync.io")
	if err != nil {
		return 0, 0, err
	}

	latestBlock, err := client.BlockNumber(context.TODO())
	if err != nil {
		return 0, 0, err
	}

	startBlock, err := client.BlockByNumber(context.TODO(), big.NewInt(int64(latestBlock)))
	if err != nil {
		return 0, 0, err
	}

Incorrect sender address was returned

There is transaction on ZkSync Era https://explorer.zksync.io/tx/0x197058ca77d906d883f75c1a720b414142092b27862f344044411b7268c7169e

Library returns incorrect sender address for this transaction -0x120982a08B06f31583c10F0383a2C3aa46f06606

Actual sender address is 0xBB4ddF60b4013B10E7D1709DED7f4B8A81398073

Code for reproduce

ctx := context.Background()
zp, err := zksync2.NewDefaultProvider("https://mainnet.era.zksync.io")
if err != nil {
	panic(err)
}

txHash := "0x197058ca77d906d883f75c1a720b414142092b27862f344044411b7268c7169e"
tx, _, err := zp.GetClient().TransactionByHash(ctx, common.HexToHash(txHash))
if err != nil {
	panic(err)
}

signer := types.LatestSignerForChainID(new(big.Int).SetUint64(324))
sender, err := signer.Sender(tx)
if err != nil {
	panic(err)
}

fmt.Printf("%s \n", sender)

How to get actual sender address?

Create depost transaction prompt error: โ€œno contract code at given addressโ€

// zkSyncProvider, err := zksync2.NewDefaultProvider("https://zksync2-mainnet.zksync.io")
// zkSyncProvider, err := zksync2.NewDefaultProvider("https://testnet.era.zksync.dev")
zkSyncProvider, err := zksync2.NewDefaultProvider("https://zksync2-testnet.zksync.dev")
checkError(err)

bcs, err := zkSyncProvider.ZksGetBridgeContracts()
checkError(err)

//BUT GET bcs.L1EthDefaultBridge is nil
fmt.Printf("bcs=%+v\n", bcs)
//bcs out = &{L1Erc20DefaultBridge:0x927DdFcc55164a59E0F33918D13a2D559bC10ce7
// L1EthDefaultBridge:0x0000000000000000000000000000000000000000
// L2Erc20DefaultBridge:0x00ff932A6d70E2B8f1Eb4919e1e09C1923E7e57b
// L2EthDefaultBridge:0x0000000000000000000000000000000000000000}
fmt.Printf("l1Eth=%v\n", bcs.L1EthDefaultBridge) //out 0x0000000000000000000000000000000000000000
fmt.Printf("l2Eth=%v\n", bcs.L2EthDefaultBridge) //out 0x0000000000000000000000000000000000000000

....

// gasOpts := &zksync2.GasOptions{
// 	GasPrice: gasprice,
// }
tx, err := ethereumProvider.Deposit(zksync2.CreateETH(), big.NewInt(1000000000000000), self, nil)
checkError(err)
//depost err = no contract code at given address
fmt.Println("Tx hash", tx.Hash())

go dependency version too old

this repo depend on github.com/miguelmota/go-ethereum-hdwallet, which uses github.com/btcsuite/btcutil/hdkeychain, and btcsuite has already move btcutil to github.com/btcsuite/btcd/btcutil which is under btcd repo, so if i use zksync-go and other repo depend on btcsuite/btcd/btcutil๏ผŒconfilct will happen.

here is the go mod tidy error output message:
github.com/zksync-sdk/zksync2-go/accounts imports
github.com/miguelmota/go-ethereum-hdwallet imports
github.com/btcsuite/btcutil/hdkeychain imports
github.com/btcsuite/btcd/btcec: module github.com/btcsuite/btcd@latest found (v0.24.0), but does not contain package github.com/btcsuite/btcd/btcec

you can fork this repo and update its go mod dependency or use this instead:https://github.com/stephenlacy/go-ethereum-hdwallet

unknown field ExcessDataGas in struct literal

go.mod

module l2

go 1.21.3

require (
	github.com/ethereum/go-ethereum v1.13.8
	github.com/zksync-sdk/zksync2-go v0.3.2
)

Code from example

package main

import (
	"github.com/zksync-sdk/zksync2-go/clients"
)

func main() {
	ZkSyncEraProvider := "https://testnet.era.zksync.dev"
	ZkSyncEraWSProvider := "ws://testnet.era.zksync.dev:3051"

	// Connect to zkSync network
	client, err := clients.Dial(ZkSyncEraProvider)
	if err != nil {
		panic(err)
	}
	defer client.Close()

	// Connect to zkSync network using Web Socket
	wsClient, err := clients.Dial(ZkSyncEraWSProvider)
	if err != nil {
		panic(err)
	}
	defer wsClient.Close()

}

Command go run main.go

Error

# github.com/zksync-sdk/zksync2-go/clients
../../../../go/pkg/mod/github.com/zksync-sdk/[email protected]/clients/base_client.go:743:4: unknown field ExcessDataGas in struct literal of type "github.com/ethereum/go-ethereum/core/types".Header

Cannot decode EIP712 transaction encoded by zksync-ethers JS library

๐Ÿ› Bug Report for zksync2-go Go SDK

๐Ÿ“ Description

We are trying to create an EIP712 transaction in one application (in TypeScript) and send it to another (in Go) for signing. The transaction is successfully created and transmitted but cannot be unmarshalled into a types.Transaction712 struct.

Question:
What is the prescribed way for decoding a zksync-ethers types.Transaction into a zksync2-go types.Transaction712?

Issue:
We cannot do the above transformation because the Go library is using a Meta field, while the TS library is using a customData field.

Our approach to solving this:
We tried to use geth's rlp.Decode but we are losing some data fields.

	b, err := hex.DecodeString(strings.TrimPrefix(rlpTx, "0x"))
	if err != nil {
		log.Fatal(err)
	}
	var txn types.Transaction712
	err = rlp.DecodeBytes(b[1:], &txn)
	if err != nil {
		log.Println("error:", err) // We get and error here, even though we're also getting a useful value.
	}
	fmt.Printf("txn: %+v\n", txn)

๐Ÿ”„ Reproduction Steps

  1. Step 1
  2. Step 2
  3. ...

๐Ÿค” Expected Behavior

Describe what you expected to happen.

๐Ÿ˜ฏ Current Behavior

Describe what actually happened.

๐Ÿ–ฅ๏ธ Environment

  • Go version: 1.22.0
  • Node version: 18.20.2
  • Other relevant environment details:

๐Ÿ“‹ Additional Context

Add any other context about the problem here. If applicable, add screenshots to help explain.

๐Ÿ“Ž Log Output

Paste any relevant log output here.

walletL1 BalanceL1 bug

func (a *WalletL1) BalanceL1(opts *CallOpts, token common.Address) (*big.Int, error) { callOpts := ensureCallOpts(opts).ToCallOpts(a.auth.From) if token == utils.EthAddress { return a.clientL1.BalanceAt(opts.Context, a.auth.From, opts.BlockNumber) } else { erc20Contract, err := erc20.NewIERC20(token, a.clientL1) if err != nil { return nil, fmt.Errorf("failed to load IERC20: %w", err) } return erc20Contract.BalanceOf(callOpts, a.auth.From) } }
when I call this function have nil address error
maybe return a.clientL1.BalanceAt(opts.Context, a.auth.From, opts.BlockNumber)
fix to
return a.clientL1.BalanceAt(callOpts.Context, a.auth.From, callOpts.BlockNumber)
?

Provided example is not working any more

       pkBytes, err := hex.DecodeString("REDACTED")
	if err != nil {
		panic(err)
	}

	// or from raw PrivateKey bytes
	ethereumSigner, err := zksync2.NewEthSignerFromRawPrivateKey(pkBytes, 280)
	if err != nil {
		panic(err)
	}
	fmt.Println(ethereumSigner.GetAddress().String())

	// also, init ZkSync Provider, specify ZkSync2 RPC URL (e.g. testnet)
	zkSyncProvider, err := zksync2.NewDefaultProvider("https://zksync2-testnet.zksync.dev")
	if err != nil {
		panic(err)
	}

	// then init Wallet, passing just created Ethereum Signer and ZkSync Provider
	wallet, err := zksync2.NewWallet(ethereumSigner, zkSyncProvider)
	if err != nil {
		panic(err)
	}

	b, err := wallet.GetBalance()
	if err != nil {
		panic(err)
	}

	fmt.Println(b)

	hash, err := wallet.Transfer(
		common.HexToAddress("4C466C61cf8cEEa6c7365f6F6490fcF765deC6cD"),
		big.NewInt(1),
		nil,
		nil,
	)
	if err != nil {
		panic(err)
	}
	fmt.Println("Tx hash", hash)

Prints out:

0xAfD2d8d18B2B7D1C1f35869Df4ab66BAeFc9A912
22000000000000000
panic: failed to call eth_sendRawTransaction: Failed to submit transaction: failed to validate the transaction. reason: Validation revert: Account validation error: Account validation returned invalid magic value. Most often this means that the signature is incorrect

As far as I remember it worked before an updated ~ near end of January / beginning of February...

.GetBlockByNumber() return error

.GetBlockByNumber() return error "transaction type not supported",the block height is 5145518.
The following is response from rpc node.

{ "jsonrpc": "2.0", "result": { "baseFeePerGas": "0x362db6eb", "difficulty": "0x0", "extraData": "0x", "gasLimit": "0xffffffff", "gasUsed": "0x2115690", "hash": "0x579c463556ac2cbbb3619121c8a35df23bbed885162f13bbb20b88471612aaed", "l1BatchNumber": "0x11f9e", "l1BatchTimestamp": "0x64536c0a", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "miner": "0x0000000000000000000000000000000000000000", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "nonce": "0x0000000000000000", "number": "0x4e83ae", "parentHash": "0xcb0ec3280d99b017fb760539413b5347e7d9c239b85dba1314381e2f63d87860", "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "sealFields": [], "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "size": "0x0", "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x64536f43", "totalDifficulty": "0x0", "transactions": [ { "blockHash": "0x579c463556ac2cbbb3619121c8a35df23bbed885162f13bbb20b88471612aaed", "blockNumber": "0x4e83ae", "chainId": "0x118", "from": "0x524757053f1530a6ed5825130dadbed2466b2dd4", "gas": "0x7d3a08", "gasPrice": "0x362db6eb", "hash": "0xc85288ec7de61407c1b333e46c430eaae7e46c96a37370eed672bdce31d86b77", "input": "0x", "l1BatchNumber": "0x11f9e", "l1BatchTxIndex": "0x248", "maxFeePerGas": "0x5386bc7a", "maxPriorityFeePerGas": "0x5386bc7a", "nonce": "0x277a", "r": "0x6cebcf239acbcda534c9d43cde81a9bd88c45ce32f16091d83bb16def0ba787e", "s": "0x294b34ea7fc606c3ec4307abfb8005769dd88050864a7288105f73a040f4a4fc", "to": "0x61d2fc53e4a1d57def662bfd4110eb16fa99ddb6", "transactionIndex": "0x0", "type": "0x71", "v": "0x1", "value": "0xb1a2bc2ec50000" }, { "blockHash": "0x579c463556ac2cbbb3619121c8a35df23bbed885162f13bbb20b88471612aaed", "blockNumber": "0x4e83ae", "chainId": "0x118", "from": "0x3acf326aaabfba39a40311ca2c757f856003370e", "gas": "0xbaed588", "gasPrice": "0x362db6eb", "hash": "0xb9d7d038ce757e5f6a8bc69f486d19bcfa7f8eb92537dd31edc8d848690a163e", "input": "0x793647d80000000000000000000000004ed75454062a2fd60929f386a371ada8a65f103a0000000000000000000000000000000000000000000000056bc75e2d6310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003acf326aaabfba39a40311ca2c757f856003370e00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000000000000000039b01000000000100e1783b82a18dfe6c2ef35f38edc836c4b495df2c919bbe7f562e915a527e668278847883e844c37b4342c1ea88bd555c45f219d84e7adc0986c29e1bfe2a4a1a0164536f3b00000000001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6000000000130896e0150325748000300010001020005009d41b0bf6e145a9f1296879040f2822fb5896addc7fbd4c1d94806e98f144f6d3a672fbb7d9ec665cfbe8c2ffa643ba321a047b7a72d7b6d7c3d8fb120fc40954b00000000000187040000000000000026fffffff6000000000001874700000000000000300100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000000001870400000000000000260000000064536f3a230abfe0ec3b460bd55fc4fb36356716329915145497202b8eb8bf1af6a0a3b9fe650f0367d4a7ef9815a593ea15d36593f0643aaaf0149bb04be67ab851decd0000000083fc1c840000000000127facfffffff8000000008421f8de000000000015cd450100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000000083fbec3b000000000013ed2d0000000064536f3ad1ff89ed8e67dfc99d6c6bd3e2cf47db21900c98f5a239fe21e59480a8da0e6b64ae1fc7ceacf2cd59bee541382ff3770d847e63c40eb6cf2413e7de5e93078a000000001fe35401000000000003eb68fffffff8000000001fddd57800000000000490b80100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000001fe35401000000000003d7df0000000064536f3a4fe17ca403512d0003bfb1993de595e2dc3a01977935b0ec7718e98ba5ad0a9541f3625971ca2ed2263e78573fe5ce23e13d2558ed3f2e47ab0f84fb9e7ae7220000000005f5c3b30000000000006705fffffff80000000005f5bf170000000000005cb10100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000000005f5c3b300000000000067050000000064536f3aa4b430a1ce2c68685e0c0e54a60340854fe15ce154e2f0b39927968e447cf93b1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c15880000000005f6737c0000000000005a8efffffff80000000005f66c4700000000000063910100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000000005f6737c0000000000005a8e0000000064536f3a0000000000000000000000000000000000000000000000000000000000000000000000039b0100000000010088743119e5e080659d190afaced910e28e239c7e56606c1c4ed8e568a4cd28ae088f48216814a7445311df69d9dbe06df78fef2ca2f4352297a58f120e15005e0164536f3b00000000001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6000000000130896d0150325748000300010001020005009d28fe05d2708c6571182a7c9d1ff457a221b465edf5ea9af1373f9562d16b8d15f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b000002a53311ca7300000000264232b8fffffff8000002a562f850200000000030f17ff40100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000002a53cf3f076000000002fd1c1530000000064536f3a8b38db700e8b34640e681ec9a73e89608bda29415547a224f96585192b4b9dc794bce4aee88fdfa5b58d81090bd6b3784717fa6df85419d9f04433bb3d615d5c0000000005ab751f0000000000009b9dfffffff80000000005aa8f31000000000000a9ae0100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000000005ab730b00000000000099890000000064536f3a3b69a3cf075646c5fd8148b705b8107e61a1a253d5d8a84355dcb628b3f1d12031775e1d6897129e8a84eeba975778fb50015b88039e9bc140bbd839694ac0ae000000000078d0200000000000001a9ffffffff8000000000079020d00000000000011890100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000000078d2a500000000000018190000000064536f3a48667de4448a204153aa90b89afd68f054c0e59596c4dac7af45be8ae5a9e9cd05a934cb3bbadef93b525978ab5bd3d5ce3b8fc6717b9ea182a688c5d8ee8e02000000000f28aedc000000000001a2e9fffffff8000000000f34a41300000000000180bb0100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000000f28aedc000000000001a2e90000000064536f3a56d0721e607dc033ff02bee21b9918e13bcceb97e279a2d1fa2888f0056add3db5622d32f36dc820af288aab779133ef1205d3123bbe256603849b820de48b87000000001faf0f75000000000002225bfffffff8000000001fcc2792000000000002ac530100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000001faf0f7500000000000218510000000064536f3a0000000000000000000000000000000000000000000000000000000000000000000000039b0100000000010016e68b4af79f5b635231a7e7bded02871e5fda81bc52ed2ca5fd59d3e15e30731a61bd81d587864198023745d8640cdd734c93f53b612f7fb1cd54175409f0ed0064536f3b00000000001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b600000000013089730150325748000300010001020005009d431cc2fd0ef4af4bc7c85fffae2f63d51b26d162179682d149ae619b1221c00bfc309467defa4b198c6b5bd59c08db4b9dfb27ddbcc32f31560f217b4ff8fc2b0000002c30d4f5b90000000007578487fffffff80000002c2335deb0000000000812ff730100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000002c30d4f5b900000000075784870000000064536f3af42aaf884c7b1454894170be0aaf1db39b4b78d3a56a27fd49bd8b39ef2c33d7651071f8c7ab2321b6bdd3bc79b94a50841a92a6e065f9e3b8b9926a8fb5a5d10000002d711d127800000000149d35d2fffffff80000002d676f1f000000000015dd34560100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000002d711d127800000000149d35d20000000064536f3a1801eb03803af0244523ee2a86c3f27b126abe8904db4b45a82adb5fe21708b4ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a60000002c4b91d159000000000331bda7fffffff80000002c4084345800000000031cb79e0100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000002c4b20c5c00000000002f34eca0000000064536f3a7ddf0d82af531f0af109d5e9ce9ec27ba9f00e9ee8ab71c912afffa16d715836b7abd25a76ddaffdf847224f03198ccb92723f90b2429cf33f0eecb96e352a860000002c46c7559900000000200f8d88fffffff80000002c37fcf630000000001cc8232a0100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000002c46c7559900000000200f8d880000000064536f3ad5a5c2f30e06bd6f38e01c2c4c8cdd7ca7c1c12d47a7336e459fc6db4171bae660fd61b2d90eba47f281505a88869b66133d9dc58f203b019f5aa47f1b39343e0000002d2366ea1a0000000022b037f9fffffff80000002d21b4c3980000000022aefd900100000001000000020000000064536f3b000000006447fcf2000000006447fcf00000002d2366ea1a0000000022b037f9000000006447fcf20000000000000000000000000000000000000000000000000000000000000000000000039b010000000001005621125b5cc47e65542b3354daffc823d8c571700f493977c2812e675f7552c422222583d5d701122853068cf7bb3b5fd012270074a398be3fe287a2f058a27c0164536f3b00000000001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6000000000130896a0150325748000300010001020005009db8104aadc85157eadd671370cfdbe85ee370ef0e2ac0422b302890526096df1883be4ed61dd8a3518d198098ce37240c494710a7b9d85e35d9fceac21df08994000000002a22b2a20000000000065d02fffffff8000000002a37550800000000000599da0100000001000000020000000064536f3b0000000064536f3a0000000064536f37000000002a2226e6000000000005d1460000000064536f3aff9b2f0b40487a69177a2760eb06dfc4a086792be9966e7fd18264f9be1e97e0997e0bf451cb36b4aea096e6b5c254d700922211dd933d9d17c467f0d6f34321000000020d6cf8e0000000000055a5eafffffff8000000020e288b3c00000000003ae3f60100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000020d6d36ff00000000004e0ecd0000000064536f3acc87847c1a87d5603101d7949777baa2beee2321b9f99d71e987fab0f52df666d2c2c1f2bba8e0964f9589e060c2ee97f5e19057267ac3284caef3bd50bd2cb50000000005f040bf000000000000b8bffffffff80000000005efd7e7000000000000b97f0100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000000005f040bf000000000000b51b0000000064536f3a35e66aaf5b9c68a610208f45e9a03c7f9cb5f6ca0156532ded7e2fc276ce837b27e867f0f4f61076456d1a73b14c7edc1cf5cef4f4d6193a33424288f11bd0f4000000000b240543000000000001fb5afffffff8000000000b24c314000000000001e76d0100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000000b23ee5b00000000000208ca0000000064536f3a082d489fc47462af441f2c0b60883287deb54a29ff3c5ca3f3fcdf8aa2784bcc71334dcd37620ce3c33e3bafef04cc80dec083042e49b734315b36d1aad7991f000000000cb70f89000000000001bb2efffffff8000000000cb736c60000000000017cd80100000001000000020000000064536f3b0000000064536f3a0000000064536f37000000000cb70f89000000000001bb2e0000000064536f3a0000000000000000000000000000000000000000000000000000000000000000000000039b0100000000010029b4ec9f14bd054a1cc5310b83676514e0c09a1bd81c2f82bea730de397a32e0630180d74996b06cb450483399d3c6b8a4cad49a9ceda09dcd9ff0137cb470c50164536f3b00000000001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b600000000013089690150325748000300010001020005009d7b0b1a58a54e5aa24e28f2311acf9edcb4689f22bac65d131249870040176185d6b3bc030a8bbb7dd9de46fb564c34bb7f860dead8985eb16a49cdc62f8ab3a500000001a94775c0000000000056b3ccfffffff800000001a8e54bac00000000005669460100000001000000020000000064536f3b0000000064536f3a0000000064536f3700000001a9477b9c000000000060fc8a0000000064536f3a1dc9fc22544655b453008cc68559639a8f74d584d94f84ac945b36c957afd9db73dc009953c83c944690037ea477df627657f45c14f16ad3a61089c5a3f9f4f200000000025643600000000000005106fffffff8000000000257900300000000000053cd0100000001000000020000000064536f3b0000000064536f3a0000000064536f3700000000025646f90000000000004b670000000064536f3a17222352da167878654cb84119be343ef62b079f85528d4b079da396c497812ecb1743d0e3e3eace7e84b8230dc082829813e3ab04e91b503c08e9a441c0ea8b0000000016e84ddd000000000002b343fffffff80000000016ef6a1200000000000308620100000001000000020000000064536f3b0000000064536f3b0000000064536f3a0000000016e84ddd000000000002b3430000000064536f3aeaa4bdf732d22d3487eb6e023fea350a31a24c0c7ccbedb3fbd48c8e390307b844a93dddd8effa54ea51076c4e851b6cbbfd938e82eb90197de38fe8876bb66e000000003b06072d00000000000477eefffffff8000000003b294d7600000000000594230100000001000000020000000064536f3b0000000064536f3b0000000064536f3a000000003b065f15000000000004cfd50000000064536f3a2fcc153fe438323a56df1aba9b3fbf91e96f428f4511434ed8e7360757ecdc5737f40d2898159e8f2e52b93cb78f47cc3829a31e525ab975c49cc5c5d91763780000000008050c9d0000000000012711fffffff80000000008028e22000000000000e9910100000001000000020000000064536f3b0000000064536f3a0000000064536f370000000008050c9d00000000000127110000000064536f3a0000000000", "l1BatchNumber": "0x11f9e", "l1BatchTxIndex": "0x249", "maxFeePerGas": "0x5386bc7a", "maxPriorityFeePerGas": "0x5386bc7a", "nonce": "0xd2", "r": "0x87f73a94ad24e24c8891e0ade306d7745bc41a70ac239cacdcd64d5cdf8480cb", "s": "0x12db2daebe564cd1a7942d65b9810b8240dca48dcb22b49ea356ca2af04fb812", "to": "0xd78b4ad524c136bc822cba23ab6785ecbc55d180", "transactionIndex": "0x1", "type": "0x0", "v": "0x0", "value": "0x5" } ], "transactionsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "uncles": [] }, "id": 1 }

error happened when call contract

Hello:
I want to use this SDK to call a swap contract, there are always happen error.Could you please help me to check what is the problem is? Thanks in advance.

My code is as following:

func Swap(user *zksync2.Wallet) error {

swapabi, err := abi.JSON(strings.NewReader(SWAP_ABI_TEST))
if err != nil {
	return err
}
token0 := common.HexToAddress("0x0000000000000000000000000000000000000000")
token1 := common.HexToAddress("0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4")

	path := []common.Address{token0, token1}
	//function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
	calldata, err := swapabi.Pack("swapExactETHForTokens", big.NewInt(0), path, user, big.NewInt(time.Now().Unix()+300))
	if err != nil {
		return err
	}
	fmt.Println(calldata)

	hash, err := Execute(user, common.HexToAddress("0x2da10A1e27bF85cEdD8FFb1AbBe97e53391C0295"), calldata, nil, big.NewInt(1e14))
	if err != nil {
		fmt.Println(err)
		return err
	}
	fmt.Println("swap Tx hash", hash)

return nil

}

func Execute(user *zksync2.Wallet, contract common.Address, calldata []byte, nonce *big.Int, ethval *big.Int) (string, error) {

var err error
if nonce == nil {
	nonce, err = user.GetNonce()
	if err != nil {
		return "", fmt.Errorf("failed to get nonce: %w", err)
	}
}
tx := zksync2.CreateFunctionCallTransaction(
	user.GetAddress(),
	contract,
	big.NewInt(0),
	big.NewInt(0),
	ethval,
	calldata,
	nil, nil,
)

hash, err := user.EstimateAndSend(tx, nonce)

return hash.Hex(), err

}

the error will be returned after call user.EstimateAndSend(tx, nonce)
the error is:
failed to EstimateGas: failed to query eth_estimateGas: Failed to submit transaction: cannot estimate gas


and I add funtion mimic EstimateAndSend in wallet to remove EstimateGas as following

func (w *Wallet) TxSend(tx *Transaction, nonce *big.Int, gasLimit *big.Int) (common.Hash, error) {

chainId := w.es.GetDomain().ChainId
gasPrice, err := w.zp.GetGasPrice()
if err != nil {
	return common.Hash{}, fmt.Errorf("failed to GetGasPrice: %w", err)
}
prepared := NewTransaction712(
	chainId,
	nonce,
	gasLimit,
	tx.To,
	tx.Value.ToInt(),
	tx.Data,
	big.NewInt(100000000), // TODO: Estimate correct one
	gasPrice,
	tx.From,
	tx.Eip712Meta,
)
signature, err := w.es.SignTypedData(w.es.GetDomain(), prepared)
rawTx, err := prepared.RLPValues(signature)
return w.zp.SendRawTransaction(rawTx)

}

replace hash, err := user.EstimateAndSend(tx, nonce) with hash, err = user.TxSend(tx, nonce, big.NewInt(200000)) in my code
the error is:
failed to call eth_sendRawTransaction: Failed to submit transaction: failed to validate the transaction. reason: Validation revert: Account validation error: Error function_selector = 0x, data = 0x

-----------------------------------------------abi------------------------------------------------------------------
var SWAP_ABI_TEST = [{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"depositProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"removeLiquidityETHWithPermit2","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens2","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"removeLiquidityWithPermit2","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueERC20","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueETH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"onBehalf","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"stakeProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]

full context support

Hi guys! Is it possible to make context support for all funcs where it is needed? May I make a pull request for that addon?

failed to EstimateGas: failed to query eth_estimateGas: Failed to submit transaction: cannot estimate gas: The code hash is not known

I try to do sth like

package main

import (
	"encoding/hex"
	"fmt"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/rpc"
	"github.com/zksync-sdk/zksync2-go"
	"log"
)

func main() {
	bytecode := []byte("some bytecode")
	dValue, err := hex.DecodeString("private key")
	if err != nil {
		log.Fatal(err)
	}

	es, err := zksync2.NewEthSignerFromRawPrivateKey(dValue, zksync2.ZkSyncChainIdMainnet)
	if err != nil {
		log.Fatal(err)
	}

	zp, err := zksync2.NewDefaultProvider("https://testnet.era.zksync.dev")
	if err != nil {
		log.Fatal(err)
	}

	w, err := zksync2.NewWallet(es, zp)
	if err != nil {
		log.Fatal(err)
	}

	ethRpc, err := rpc.Dial("https://eth-goerli.public.blastapi.io")
	if err != nil {
		log.Fatal(err)
	}

	ep, err := w.CreateEthereumProvider(ethRpc)
	if err != nil {
		log.Fatal(err)
	}

	_ = ep

	log.Println(len(bytecode) % 32)
	hash, err := w.Deploy(bytecode, nil, nil, nil, nil)
	if err != nil {
		panic(err)
	}
	fmt.Println("Tx hash", hash)

	addr, err := zksync2.ComputeL2Create2Address(
		common.HexToAddress("<deployer_L2_address>"),
		bytecode,
		nil,
		nil,
	)
	if err != nil {
		panic(err)
	}
	fmt.Println("Deployed address", addr.String())
}

And get error "failed to EstimateGas: failed to query eth_estimateGas: Failed to submit transaction: cannot estimate gas: The code hash is not known"

Whats wrong?

Thanks in advise!

Encoding paymaster params for a general paymaster does not work

๐Ÿ› Bug Report for zksync2-go Go SDK

๐Ÿ“ Description

GetGeneralPaymasterInput will fail due to the underlying behavior of the github.com/ethereum/go-ethereum/accounts/abi library which expects an input as bytes instead of types.GeneralPaymasterInput.

๐Ÿ”„ Reproduction Steps

GetGeneralPaymasterInput(types.GeneralPaymasterInput{}) should return an error.

๐Ÿค” Expected Behavior

It shouldn't return an error :)

๐Ÿ˜ฏ Current Behavior

It returns an error :)

Fix

The underlying ABI library expects the arguments to come in as []byte{}, since it uses reflect to check the type of the parameters passed. We were able to hack this around by passing []byte{} manually:

func hack_createPaymasterParams(paymasterAddress common.Address) (*types.PaymasterParams, error) {
	paymasterFlowAbi, err := abi.JSON(strings.NewReader(paymasterflow.IPaymasterFlowMetaData.ABI))
	if err != nil {
		return &types.PaymasterParams{}, fmt.Errorf("failed to load paymasterFlowAbi: %w", err)
	}

	input, err := paymasterFlowAbi.Pack("general", []byte{})
	if err != nil {
		return &types.PaymasterParams{}, fmt.Errorf("failed to pack general paymaster input: %w", err)
	}

	return &types.PaymasterParams{
		Paymaster:      paymasterAddress,
		PaymasterInput: input,
	}, nil
}

Of course this fix should be adapted to supporting the current code.

L2Wallet SendTransaction is not thread safe

I found that when multiple goroutines concurrently call SendTransaction to send transactions, it's possible to get the same txhash for different transactions. This can lead to some transactions not being confirmed, and calling WaitMined after sending the transaction can't retrieve the transaction information, resulting in a deadlock. The code to reproduce this issue is as follows:
`func main() {
PrivateKey := ""
ZkSyncEraProvider := "
"

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

wallet, err := accounts.NewWalletL2(common.Hex2Bytes(PrivateKey), &client)
if err != nil {
	return
}

SatsAddress := common.HexToAddress("***")
ZBTCAddress := common.HexToAddress("***")
l2address := common.HexToAddress("***")

contractABI, err := abi.JSON(strings.NewReader(erc20ABI))
if err != nil {
	log.Fatal(err)
}

var wg sync.WaitGroup
wg.Add(3) 

go func() {
	defer wg.Done()
	amount := ToWei("1", 18)
	mintData, err := contractABI.Pack("mint", l2address, amount)
	if err != nil {
		return
	}
	hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{
		To:   &SatsAddress,
		Data: mintData,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	_, err = client.WaitMined(context.Background(), hash)
	if err != nil {
		log.Panic(err)
	}
}()

go func() {
	defer wg.Done()
	amount := ToWei("0.001", 18)
	mintData, err := contractABI.Pack("mint", l2address, amount)
	if err != nil {
		return
	}
	hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{
		To:   &ZBTCAddress,
		Data: mintData,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	_, err = client.WaitMined(context.Background(), hash)
	if err != nil {
		log.Panic(err)
	}
}()

go func() {
	defer wg.Done()
	amount := ToWei("0.001", 18)
	mintData, err := contractABI.Pack("mint", l2address, amount)
	if err != nil {
		return
	}
	hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{
		To:   &ZBTCAddress,
		Data: mintData,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	_, err = client.WaitMined(context.Background(), hash)
	if err != nil {
		log.Panic(err)
	}
}()
wg.Wait()

}`

However, after adding a lock to SendTransaction, a new problem arose.
Since the Nonce calculation in PopulateTransaction is based on an RPC call rather than local caching, concurrent calls to SendTransaction can lead to the Nonce not being updated in time.
This can result in transactions with the same Nonce field being generated. When the previous transaction is submitted and successfully processed, the subsequent transaction will be rejected due to an invalid Nonce field.

go func() { defer wg.Done() amount := ToWei("1", 18) mintData, err := contractABI.Pack("mint", l2address, amount) if err != nil { return } lock.Lock() hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{ To: &SatsAddress, Data: mintData, }) if err != nil { fmt.Println(err) return } lock.Unlock() _, err = client.WaitMined(context.Background(), hash) if err != nil { log.Panic(err) } }()

In the end, I had to include WaitMined in the locked scope as well, forcing the originally concurrent transactions to be executed and confirmed in a completely serial manner.

go func() { defer wg.Done() amount := ToWei("1", 18) mintData, err := contractABI.Pack("mint", l2address, amount) if err != nil { return } lock.Lock() hash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{ To: &SatsAddress, Data: mintData, }) if err != nil { fmt.Println(err) return } _, err = client.WaitMined(context.Background(), hash) if err != nil { log.Panic(err) } lock.Unlock() }()

My question is, when using zksync-gosdk, is it only possible to execute transactions serially, and not to send transactions concurrently?
If concurrent transactions are possible, how can it be done? If not, please add a note in the comments of SendTransaction indicating that it is not thread-safe for concurrent use.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.