Skip to content

Commit 7628716

Browse files
author
Ilan
committed
1 parent c368596 commit 7628716

File tree

7 files changed

+360
-14
lines changed

7 files changed

+360
-14
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package zksyncwrapper
2+
3+
import (
4+
"context"
5+
"crypto/rand"
6+
"fmt"
7+
8+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
9+
"github.com/ethereum/go-ethereum/common"
10+
"github.com/zksync-sdk/zksync2-go/accounts"
11+
"github.com/zksync-sdk/zksync2-go/clients"
12+
"github.com/zksync-sdk/zksync2-go/types"
13+
)
14+
15+
// this file is used as a template. see wrap_zk_bytecode.go before editing
16+
func DeployPlaceholderContractNameZk(deployOpts *accounts.TransactOpts, client *clients.Client, wallet *accounts.Wallet, backend bind.ContractBackend, args ...interface{}) (common.Address, *types.Receipt, *PlaceholderContractName, error) {
17+
var calldata []byte
18+
if len(args) > 0 {
19+
abi, err := PlaceholderContractNameMetaData.GetAbi()
20+
if err != nil {
21+
return common.Address{}, nil, nil, err
22+
}
23+
calldata, err = abi.Pack("", args...)
24+
if err != nil {
25+
return common.Address{}, nil, nil, err
26+
}
27+
}
28+
29+
salt := make([]byte, 32)
30+
n, err := rand.Read(salt)
31+
if err != nil {
32+
return common.Address{}, nil, nil, err
33+
}
34+
if n != len(salt) {
35+
return common.Address{}, nil, nil, fmt.Errorf("failed to read random bytes: expected %d, got %d", len(salt), n)
36+
}
37+
38+
txHash, err := wallet.Deploy(deployOpts, accounts.Create2Transaction{
39+
Bytecode: ZkBytecode,
40+
Calldata: calldata,
41+
Salt: salt,
42+
})
43+
if err != nil {
44+
return common.Address{}, nil, nil, err
45+
}
46+
47+
receipt, err := client.WaitMined(context.Background(), txHash)
48+
if err != nil {
49+
return common.Address{}, nil, nil, err
50+
}
51+
52+
address := receipt.ContractAddress
53+
contract, err := NewPlaceholderContractName(address, backend)
54+
if err != nil {
55+
return common.Address{}, nil, nil, err
56+
}
57+
58+
return address, receipt, contract, nil
59+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package zksyncwrapper
2+
3+
import (
4+
"github.com/ethereum/go-ethereum/accounts/abi"
5+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
6+
"github.com/ethereum/go-ethereum/common"
7+
)
8+
9+
// this are mocks for the placeholders used in the template
10+
type PlaceholderContractName struct{}
11+
12+
type IPlaceholderContractNameMetaData struct {
13+
GetAbi func() (*abi.ABI, error)
14+
}
15+
16+
var PlaceholderContractNameMetaData = IPlaceholderContractNameMetaData{
17+
GetAbi: func() (*abi.ABI, error) {
18+
return nil, nil
19+
},
20+
}
21+
22+
var ZkBytecode = []byte{}
23+
24+
func NewPlaceholderContractName(address common.Address, backend bind.ContractBackend) (*PlaceholderContractName, error) {
25+
return nil, nil
26+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package zksyncwrapper
2+
3+
import (
4+
"bytes"
5+
_ "embed"
6+
"encoding/json"
7+
"fmt"
8+
"go/ast"
9+
"go/format"
10+
"go/token"
11+
"os"
12+
"strings"
13+
)
14+
15+
//go:embed template.go
16+
var zksyncDeployTemplate string
17+
18+
func WrapZksyncDeploy(zksyncBytecodePath, className, pkgName, outPath string) {
19+
fmt.Printf("Generating zk bytecode binding for %s\n", pkgName)
20+
21+
fileNode := &ast.File{
22+
Name: ast.NewIdent(pkgName),
23+
Decls: []ast.Decl{
24+
declareImports(),
25+
declareDeployFunction(className),
26+
declareBytecodeVar(zksyncBytecodePath)}}
27+
28+
writeFile(fileNode, outPath)
29+
}
30+
31+
const comment = `// Code generated - DO NOT EDIT.
32+
// This file is a generated binding and any manual changes will be lost.
33+
`
34+
35+
var importValues = []string{
36+
`"context"`,
37+
`"crypto/rand"`,
38+
`"fmt"`,
39+
`"github.com/ethereum/go-ethereum/accounts/abi/bind"`,
40+
`"github.com/ethereum/go-ethereum/common"`,
41+
`"github.com/zksync-sdk/zksync2-go/accounts"`,
42+
`"github.com/zksync-sdk/zksync2-go/clients"`,
43+
`"github.com/zksync-sdk/zksync2-go/types"`,
44+
}
45+
46+
func declareImports() ast.Decl {
47+
48+
specs := make([]ast.Spec, len(importValues))
49+
for i, value := range importValues {
50+
specs[i] = &ast.ImportSpec{
51+
Path: &ast.BasicLit{
52+
Kind: token.STRING,
53+
Value: value}}
54+
}
55+
56+
return &ast.GenDecl{
57+
Tok: token.IMPORT,
58+
Specs: specs}
59+
}
60+
61+
func declareDeployFunction(contractName string) ast.Decl {
62+
template := zksyncDeployTemplate
63+
64+
// this is not ideal. use ast to read the function
65+
// remove imports, function name, first indent and closing bracket
66+
var (
67+
count = 0
68+
index = 0
69+
)
70+
for count < len(importValues)+8 { // lines to skip
71+
if template[index] == '\n' {
72+
count++
73+
}
74+
index++
75+
}
76+
template = template[index+1 : len(template)-3]
77+
78+
template = strings.Replace(template, "PlaceholderContractName", contractName, 2)
79+
80+
return &ast.FuncDecl{
81+
Name: ast.NewIdent("Deploy" + contractName + "Zk"),
82+
Type: &ast.FuncType{
83+
Params: &ast.FieldList{
84+
List: []*ast.Field{{
85+
Names: []*ast.Ident{ast.NewIdent("deployOpts")},
86+
Type: &ast.Ident{Name: "*accounts.TransactOpts"}}, {
87+
Names: []*ast.Ident{ast.NewIdent("client")},
88+
Type: &ast.Ident{Name: "*clients.Client"}}, {
89+
Names: []*ast.Ident{ast.NewIdent("wallet")},
90+
Type: &ast.Ident{Name: "*accounts.Wallet"}}, {
91+
Names: []*ast.Ident{ast.NewIdent("backend")},
92+
Type: &ast.Ident{Name: "bind.ContractBackend"}}, {
93+
Names: []*ast.Ident{ast.NewIdent("args")},
94+
Type: &ast.Ellipsis{Elt: &ast.Ident{Name: "interface{}"}}}}},
95+
Results: &ast.FieldList{
96+
List: []*ast.Field{
97+
{Type: &ast.Ident{Name: "common.Address"}},
98+
{Type: &ast.Ident{Name: "*types.Receipt"}},
99+
{Type: &ast.StarExpr{X: &ast.Ident{Name: contractName}}},
100+
{Type: &ast.Ident{Name: "error"}}}}},
101+
Body: &ast.BlockStmt{
102+
List: []ast.Stmt{
103+
&ast.ExprStmt{
104+
X: &ast.BasicLit{
105+
Kind: token.STRING,
106+
Value: template}}}}}
107+
}
108+
109+
func declareBytecodeVar(srcFile string) ast.Decl {
110+
jsonData, err := os.ReadFile(srcFile)
111+
if err != nil {
112+
panic(err)
113+
}
114+
115+
var bytecodeData struct {
116+
Bytecode struct {
117+
Object string `json:"object"`
118+
} `json:"bytecode"`
119+
}
120+
if err := json.Unmarshal(jsonData, &bytecodeData); err != nil {
121+
panic(err)
122+
}
123+
124+
return &ast.GenDecl{
125+
Tok: token.VAR,
126+
Specs: []ast.Spec{
127+
&ast.ValueSpec{
128+
Names: []*ast.Ident{ast.NewIdent("ZkBytecode")},
129+
Values: []ast.Expr{
130+
&ast.CallExpr{
131+
Fun: &ast.SelectorExpr{
132+
X: ast.NewIdent("common"),
133+
Sel: ast.NewIdent("Hex2Bytes")},
134+
Args: []ast.Expr{
135+
&ast.BasicLit{
136+
Kind: token.STRING,
137+
Value: fmt.Sprintf(`"%s"`, bytecodeData.Bytecode.Object)}}}}}}}
138+
}
139+
140+
func writeFile(fileNode *ast.File, dstFile string) {
141+
var buf bytes.Buffer
142+
fset := token.NewFileSet()
143+
if err := format.Node(&buf, fset, fileNode); err != nil {
144+
panic(err)
145+
}
146+
147+
bs := buf.Bytes()
148+
bs = append([]byte(comment), bs...)
149+
150+
if err := os.WriteFile(dstFile, bs, 0600); err != nil {
151+
panic(err)
152+
}
153+
}

gethwrappers/generation/zksync/wrap.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77

88
"github.com/smartcontractkit/chainlink-evm/gethwrappers"
9+
zksyncwrapper "github.com/smartcontractkit/chainlink-evm/gethwrappers/generation/generate/zksync"
910
)
1011

1112
const template = `// Code generated by gethwrappers/zksync. DO NOT EDIT.
@@ -27,17 +28,9 @@ func main() {
2728
if err != nil {
2829
gethwrappers.Exit("could not get working directory", err)
2930
}
30-
outDir := filepath.Join(cwd, "..", project, "generated", packageName)
31-
if mkdErr := os.MkdirAll(outDir, 0700); err != nil {
32-
gethwrappers.Exit("failed to create wrapper dir", mkdErr)
33-
}
34-
outPath := filepath.Join(outDir, packageName+"_zksync.go")
3531

36-
// sample generation
37-
data := []byte(fmt.Sprintf(template, packageName, contractName))
32+
zksyncBytecodePath := filepath.Join(cwd, "..", "..", "contracts", "zkout", contractName+".sol", contractName+".json")
33+
outPath := filepath.Join(cwd, "..", project, "generated", packageName, packageName+"_zksync.go")
3834

39-
err = os.WriteFile(outPath, data, 0600)
40-
if err != nil {
41-
gethwrappers.Exit("failed to write file", err)
42-
}
35+
zksyncwrapper.WrapZksyncDeploy(zksyncBytecodePath, contractName, packageName, outPath)
4336
}

gethwrappers/shared/generated/link_token/link_token_zksync.go

Lines changed: 58 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/smartcontractkit/chainlink-integrations/evm v0.0.0-20250402183906-b7e976bc0c24
1111
github.com/stretchr/testify v1.10.0
1212
github.com/tidwall/gjson v1.18.0
13+
github.com/zksync-sdk/zksync2-go v1.0.0
1314
go.uber.org/multierr v1.11.0
1415
golang.org/x/text v0.23.0
1516
golang.org/x/tools v0.30.0
@@ -33,6 +34,10 @@ require (
3334
github.com/apache/arrow-go/v18 v18.0.0 // indirect
3435
github.com/beorn7/perks v1.0.1 // indirect
3536
github.com/bits-and-blooms/bitset v1.17.0 // indirect
37+
github.com/btcsuite/btcd v0.24.0 // indirect
38+
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
39+
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
40+
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
3641
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
3742
github.com/cespare/xxhash/v2 v2.3.0 // indirect
3843
github.com/cockroachdb/errors v1.11.3 // indirect
@@ -119,12 +124,14 @@ require (
119124
github.com/shopspring/decimal v1.4.0 // indirect
120125
github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250325121830-cfa9bf24c4f5 // indirect
121126
github.com/smartcontractkit/libocr v0.0.0-20250328171017-609ec10a5510 // indirect
127+
github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 // indirect
122128
github.com/supranational/blst v0.3.14 // indirect
123129
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
124130
github.com/tidwall/match v1.1.1 // indirect
125131
github.com/tidwall/pretty v1.2.1 // indirect
126132
github.com/tklauser/go-sysconf v0.3.13 // indirect
127133
github.com/tklauser/numcpus v0.7.0 // indirect
134+
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
128135
github.com/ugorji/go/codec v1.2.12 // indirect
129136
github.com/urfave/cli/v2 v2.27.5 // indirect
130137
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect

0 commit comments

Comments
 (0)