go语言操作以太坊智能合约

  • Post author:
  • Post category:其他



操作中要注意版本问题

geth版本、golang版本等

在remix环境中写好合约后,进行编译得到abi文件


简单举例


Hello.sol合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Hello {
    string Msg;

    function setMsg(string memory _msg) public{
        Msg=_msg;
    }

    function getMsg() view public returns(string memory){
        return Msg;
    }
}

编译后abi文件(Hello.abi)内容

[
	{
		"inputs": [],
		"name": "getMsg",
		"outputs": [
			{
				"internalType": "string",
				"name": "",
				"type": "string"
			}
		],
		"stateMutability": "view",
		"type": "function"
	},
	{
		"inputs": [
			{
				"internalType": "string",
				"name": "_msg",
				"type": "string"
			}
		],
		"name": "setMsg",
		"outputs": [],
		"stateMutability": "nonpayable",
		"type": "function"
	}
]

然后需要一个

abigen工具

可以将abi、bin等编译后的智能合约文件内容生成go代码

abigen可以在geth官网下载geth的时候下载Geth&Tools版本 里面带有abigen工具

在这里插入图片描述

采用以下命令将Hello.abi生成hello.go文件

其中

-out hello.go:指定输出为hello.go文件

-pkg main:指定该go文件属于哪个包

-type hello:指定合约的名称为hello

abigen -abi Hello.abi -pkg main -type hello -out hello.go


如果合约已经部署成功,采用上面的abigen生成的合约绑定就足够调用合约了,但是要部署合约还需要一些编译字节码形式的附加信息

可以通过remix合约直接得到合约编码后的字节码,也可以通过solc来编译

得到Hello.bin文件

然后 abigen 可以再次运行,这次传递 Hello.bin:

abigen --abi Hello.abi --pkg main --type Hello --out hello.go --bin Hello.bin



部署合约过程

1 连接到以太坊(创建客户端)

//1 创建客户端
	client, err := ethclient.Dial("http://localhost:8545")
	if err != nil {
		log.Panic("failed to Dail", err)
	}

2 创建一个用户部署合约的身份

//2 身份准备
//自己的账户文件的内容
var keyinfo = `{"address":"470455a4b2492d75f19ec7b29d25e19aee0c48b1","crypto":{"cipher":"aes-128-ctr","ciphertext":"08ef3a09df1d731bf71d8ce52a0fed4d4c9187f7a5ef845833bac9854700cd70","cipherparams":{"iv":"e8b8b6ed222f8906b31e391e6ef8b7d7"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"e0970e0f38759ee32152429f692df30c0b4efd1d8adef6a9cf2a58e4f67fdcc7"},"mac":"0bea42bc7c1284307f518f4939f2de3af2278ac83e329541bf9e258e107c2feb"},"id":"83cb1145-c55b-439f-a1f0-5416a3805beb","version":3}`
keyin := strings.NewReader(keyinfo)
chainID, err := client.ChainID(context.Background())
if err != nil {
	log.Panic(err)
}
auth, err := bind.NewTransactorWithChainID(keyin, "123456", chainID)
if err != nil {
	log.Panic(err)
}

3 部署合约

这里我不知道我用abigen生成的go合约代码中没有DeployHello方法

//3 部署合约
	//3 部署合约
	// 合约地址,部署交易,合约对象
	address, tx, HelloInstance, err := DeployHello(auth, client)
	if err != nil {
		log.Panic(err)
	}
	fmt.Println("address:", address.Hex())
	fmt.Println("tx:", tx.Hash())
	fmt.Println("contractInstance", HelloInstance)

部署后得到的结果

address: 0xEC1Bd1468F090cf41ddbf9463d7c27689a4002De
tx: 0x3c3a4d51efa0ea1d736a0ce6b415282dff22e41a2a9f3aa0147e2e8365cbcab3
contractInstance &{{0xc00007ec80} {0xc00007ec80} {0xc00007ec80}}

可以拿着这个交易hash在geth控制台查看交易数据

在这里插入图片描述



调用合约过程

1 连接到以太坊(创建客户端)

2 加载合约对象

3 创建一个用户部署合约的身份

4 调用合约

func main() {
	//1 创建客户端
	client, err := ethclient.Dial("http://localhost:8545")
	if err != nil {
		log.Panic("failed to Dail", err)
	}

	//2 身份准备
	var keyinfo = `{"address":"470455a4b2492d75f19ec7b29d25e19aee0c48b1","crypto":{"cipher":"aes-128-ctr","ciphertext":"08ef3a09df1d731bf71d8ce52a0fed4d4c9187f7a5ef845833bac9854700cd70","cipherparams":{"iv":"e8b8b6ed222f8906b31e391e6ef8b7d7"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"e0970e0f38759ee32152429f692df30c0b4efd1d8adef6a9cf2a58e4f67fdcc7"},"mac":"0bea42bc7c1284307f518f4939f2de3af2278ac83e329541bf9e258e107c2feb"},"id":"83cb1145-c55b-439f-a1f0-5416a3805beb","version":3}`
	keyin := strings.NewReader(keyinfo)
	chainID, err := client.ChainID(context.Background())
	if err != nil {
		log.Panic(err)
	}
	auth, err := bind.NewTransactorWithChainID(keyin, "123456", chainID)
	if err != nil {
		log.Panic(err)
	}
	//3 创建合约对象
	// 合约地址,部署交易,合约对象
	HelloInstance, err := NewHello(common.HexToAddress("0xEC1Bd1468F090cf41ddbf9463d7c27689a4002De"), client)
	if err != nil {
		log.Panic("failed to New ", err)
	}
	tx, err := HelloInstance.SetMsg(auth, "test")
	if err != nil {
		log.Panic("failed to set ", err)
	}
	fmt.Println("setmsg tx:", tx.Hash())
	time.Sleep(time.Second * 20)
	msg, err := HelloInstance.GetMsg(nil)
	if err != nil {
		log.Panic("failed to get ", err)
	}
	fmt.Println("getmsg:", msg)
}

结果展示:

在这里插入图片描述



版权声明:本文为qxjswl原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。