您现在的位置是:首页 >技术杂谈 >go语言操作以太坊智能合约网站首页技术杂谈

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

四矢 2024-09-12 12:01:04
简介go语言操作以太坊智能合约

操作中要注意版本问题 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)
}

结果展示:
在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。