轉載請注明:https://www.cnblogs.com/tkblack/p/13559254.html
說實話對以太坊還不太熟,這幾個月研究並基於以太坊搭建聯盟鏈平台,主要是圍繞CA認證、國密兼容和共識算法展開,最近需要整一個go的sdk,於是翻了各種資料如何部署和調用智能合約。
以hello合約作為示例:
// SPDX-License-Identifier: SimPL-2.0 pragma solidity >=0.4.0 <=0.7.0; contract HelloWorld { function Hello() pure public returns(string){ return "hello world!"; } }
說實話,單單安裝solc我都費了一番功夫,老是報版本錯誤,我裝的是0.6.12版本,這里要說一點就是:pure 要寫在public前面,不然會報錯。。。(剛接觸solidity,還不知道為什么,如果你知道可以評論指出,先行感謝)
接下來就是編譯:
solc --bin hello.sol -o hello.abi solc --abi hello.sol -o hello.bin abigen --bin=hello.bin --abi=hello.abi --pkg=contract --out=hello.go
這樣就得到了可用的hello.go文件,后續需要導入並使用。
接着是部署和調用:
package ethclient import( "github.com/ethereum/go-ethereum/ethclient/contract" //hello.go放在該文件夾下 "github.com/ethereum/go-ethereum/accounts/abi/bind" //其他包懶得寫,主要是兩個 ) func TestDeployContract(t *testing.T) { ethclient, err := Dial("http://localhost:8545") if err != nil { t.Error(err) } keyJson, err := ioutil.ReadFile("../build/bin/data/keystore/UTC--2020-08-17T03-35-30.955610100Z--520613668132f205d5ee27246098c72bbb793896") if err != nil { t.Error(err) } key, err := keystore.DecryptKey(keyJson, "") if err != nil { t.Error(err) } publicKey := key.PrivateKey.Public() publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) if !ok { t.Error("error casting public key to ECDSA") } fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) nonce, err := ethclient.PendingNonceAt(context.Background(), fromAddress) if err != nil { t.Error(err) } gasPrice, err := ethclient.SuggestGasPrice(context.Background()) if err != nil { t.Error(err) } auth := bind.NewKeyedTransactor(key.PrivateKey) auth.Nonce = big.NewInt(int64(nonce)) auth.Value = big.NewInt(0) // in wei auth.GasLimit = uint64(300000) // in units auth.GasPrice = gasPrice address, tx, _, err := contract.DeployHello(auth, ethclient) // 部署合約 if err != nil { t.Error(err) } fmt.Println(address.Hex()) // 0x80bec2b5FbFC19Bc06c3423b6b1De65156528929 fmt.Println(tx.Hash().Hex()) // 0x414d211952688a35c9a08619823e40ef6c2dd6b288c89375c269bb7946e1aa9b // 調用合約,建議部署和調用不要寫在同一個函數中,我這里為了簡便所以合到了一起 nonce1, err := ethclient.PendingNonceAt(context.Background(), fromAddress) if err != nil { t.Error(err) } auth.Nonce = big.NewInt(int64(nonce1)) hello, err := contract.NewHello(address, ethclient) helloRaw := contract.HelloRaw{hello} helloTx, err := helloRaw.Transact(auth, "Hello") // 這是hello.go中已經封裝好的方法,也可以自己組裝交易然后Send if err != nil { t.Error(err) } fmt.Printf("txid : %v\n", helloTx.Hash().String()) }
細節就不描述了,主要是就兩個函數,DeployHello和Transact;其實,在Dial的時候是需要傳入一個證書(畢竟是聯盟鏈),但是,這里被我省掉了。