Abigen
Compile a solidity contract into golang to deploy and call contracts progrmatically.

How to Build

Download the solidity compiler from solc-bin.
Copy the appropriate compiler into your current path. ~/bin/ is a common path in most linux distributions.
1
# cp linux-amd64/solc-linux-amd64-v0.8.9+commit.e5eed63a ~/bin
Copied!
Ensure solc can run.
1
# solc --version
2
solc, the solidity compiler commandline interface
3
Version: 0.8.9+commit.e5eed63a.Linux.g++
Copied!
Build abigen.
1
# cd ~/go/src/github.com/ava-labs/avalanche
2
# go build -o abigen cmd/abigen/main.go
3
# cp abigen ~/bin
Copied!
Compile a contract.
1
# abigen --sol counter.sol --pkg main --out counter.go
Copied!
This will produce contract.go suitable to interact with contract.

Example Code

Setup the connection to avalanhcego, then deploy, call, and fetch values from the contract.
Abigen offers more features for complicated contracts, the following is provided as an example to get started using the basic contract
1
package main
2
3
import (
4
"context"
5
"log"
6
"math/big"
7
"strings"
8
"time"
9
10
"github.com/ava-labs/avalanchego/utils/constants"
11
"github.com/ava-labs/avalanchego/utils/formatting"
12
"github.com/ava-labs/coreth/accounts/abi/bind"
13
"github.com/ava-labs/coreth/core/types"
14
"github.com/ava-labs/coreth/ethclient"
15
"github.com/ava-labs/coreth/params"
16
"github.com/ava-labs/coreth/rpc"
17
"github.com/decred/dcrd/dcrec/secp256k1/v3"
18
"github.com/ethereum/go-ethereum/common"
19
"github.com/ethereum/go-ethereum/crypto"
20
)
21
22
func main() {
23
// setup client
24
rc, err := rpc.Dial("http://localhost:9650/ext/bc/C/rpc")
25
if err != nil {
26
log.Fatal(err)
27
}
28
ec := ethclient.NewClient(rc)
29
30
ctx := context.Background()
31
32
// fetch networkid
33
networkId, err := ec.ChainID(ctx)
34
if err != nil {
35
log.Fatal(err)
36
}
37
38
// parse key
39
privateKeyString := "PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"
40
privateKeyBytes, err := formatting.Decode(formatting.CB58, strings.TrimPrefix(privateKeyString, constants.SecretKeyPrefix))
41
if err != nil {
42
log.Fatal(err)
43
}
44
privateKey := secp256k1.PrivKeyFromBytes(privateKeyBytes)
45
privateKeyECDSA := privateKey.ToECDSA()
46
47
// derive 'c' address
48
cAddress := crypto.PubkeyToAddress(privateKeyECDSA.PublicKey)
49
50
// setup siner and transaction options.
51
signer := types.LatestSignerForChainID(networkId)
52
to := &bind.TransactOpts{
53
Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) {
54
return types.SignTx(transaction, signer, privateKeyECDSA)
55
},
56
From: cAddress,
57
Context: ctx,
58
GasLimit: params.ApricotPhase1GasLimit,
59
}
60
61
// deploy the contract
62
storageAddress, storageTransaction, storageContract, err := DeployStorage(to, ec)
63
if err != nil {
64
log.Fatal(err)
65
}
66
67
// wait for the transaction to be accepted
68
for {
69
r, err := ec.TransactionReceipt(ctx, storageTransaction.Hash())
70
if err != nil {
71
if err.Error() != "not found" {
72
log.Fatal(err)
73
}
74
time.Sleep(1 * time.Second)
75
continue
76
}
77
if r.Status != 0 {
78
break
79
}
80
time.Sleep(1 * time.Second)
81
}
82
83
log.Println("storageAddress", storageAddress)
84
log.Println("storageTransaction", storageTransaction)
85
86
// Call store on the contract
87
storeTransaction, err := storageContract.Store(to, big.NewInt(1), common.BytesToAddress([]byte("addr1")))
88
if err != nil {
89
log.Fatal(err)
90
}
91
92
// wait for the transaction
93
for {
94
r, err := ec.TransactionReceipt(ctx, storeTransaction.Hash())
95
if err != nil {
96
if err.Error() != "not found" {
97
log.Fatal(err)
98
}
99
time.Sleep(1 * time.Second)
100
continue
101
}
102
if r.Status != 0 {
103
break
104
}
105
time.Sleep(1 * time.Second)
106
}
107
108
log.Println("storeTransaction", storeTransaction)
109
110
// setup call options for storage
111
co := &bind.CallOpts{
112
Accepted: true,
113
Context: ctx,
114
From: storageAddress,
115
}
116
117
// retrieve the value of the contract
118
storageValue, err := storageContract.Retrieve(co)
119
if err != nil {
120
log.Fatal(err)
121
}
122
123
log.Println("storageValue", storageValue)
124
}
Copied!
Last modified 19d ago
Copy link