Abi calls to interact with smart contracts using go

In the previous article, we explained how go uses function selectors to call smart contracts. Next, let's learn how to use abi to call smart contracts.

Courses in this series:

Section 1: Function selector call for interacting with smart contracts using go

Section 2: Abi call using go to interact with smart contracts

Section 3: Use go to interact with smart contracts and use abigen to generate contract go files for calling

1. First, let's install go-ethereum

go get -u github.com/ethereum/go-ethereum


2. Create a new main.go file and add dependencies

import (
    "context"
    "crypto/ecdsa"
    "fmt"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/ethclient"
    "math/big"
    "os"
)


3. Define constants

const (
    privateKey      = "你的钱包私钥"
    contractAddress = "调用合约地址"
    toAddress       = "接收转账地址" //这里我使用transfer方法作为案例,所以需要一个接收转账地址
)


4. Define the calling function

func transfer(client *ethclient.Client, privateKey, toAddress, contract string) (string, error) {}


4.1. First deduce the public key from the private key, and then deduce the wallet address from the public key

  //从私钥推导出 公钥
    privateKeyECDSA, err := crypto.HexToECDSA(privateKey)
    if err != nil {
        fmt.Println("crypto.HexToECDSA error ,", err)
        return "", err
    }
    publicKey := privateKeyECDSA.Public()
    publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
    if !ok {
        fmt.Println("publicKeyECDSA error ,", err)
        return "", err
    }
    //从公钥推导出钱包地址
    fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
    fmt.Println("钱包地址:", fromAddress.Hex())

4.2. Construct request parameters

This is different from the way of using function selectors, which is also the focus of this article

4.2.1. Prepare the abi file abi.json of the contract

( If you will not get the contract abi file, you can follow the official account: Wai Bai San Preacher ( web3_preacher ) and leave me a message )

[
  {
    "inputs": [],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  .....
]

4.2.2, read abi file

//读取abi文件
	abiData, err := os.ReadFile("./part2/abi.json")
	if err != nil {
		fmt.Println("os.ReadFile error ,", err)
		return "", err
	}

4.2.3. Convert abi data into contract abi objects

contractAbi, err := abi.JSON(bytes.NewReader(abiData))
	if err != nil {
		fmt.Println("abi.JSON error ,", err)
		return "", err
	}

4.2.4. The contract abi object packs the methods and parameters to be called

amount, _ := new(big.Int).SetString("100000000000000000000", 10)
	data, err := contractAbi.Pack("transfer", common.HexToAddress(toAddress), amount)
	if err != nil {
		fmt.Println("contractAbi.Pack error ,", err)
		return "", err
	}

In fact, this operation is the same as the code we mentioned in the first chapter (see below). If you are interested, you can read the source code of the contractAbi.Pack method by yourself.

var data []byte
	methodName := crypto.Keccak256([]byte("transfer(address,uint256)"))[:4]
	paddedToAddress := common.LeftPadBytes(common.HexToAddress(toAddress).Bytes(), 32)
	amount, _ := new(big.Int).SetString("100000000000000000000", 10)
	paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
	data = append(data, methodName...)
	data = append(data, paddedToAddress...)
	data = append(data, paddedAmount...)

4.3. Construct transaction objects

    //获取nonce
	nonce, err := client.NonceAt(context.Background(), fromAddress, nil)
	if err != nil {
		return "", err
	}
	//获取小费
	gasTipCap, _ := client.SuggestGasTipCap(context.Background())
	//transfer 默认是 使用 21000 gas
	gas := uint64(100000)
	//最大gas fee
	gasFeeCap := big.NewInt(38694000460)
 
	contractAddress := common.HexToAddress(contract)
	//创建交易
	tx := types.NewTx(&types.DynamicFeeTx{
		Nonce:     nonce,
		GasTipCap: gasTipCap,
		GasFeeCap: gasFeeCap,
		Gas:       gas,
		To:        &contractAddress,
		Value:     big.NewInt(0),
		Data:      data,
	})

4.4. Transaction signature/send transaction

    // 获取当前区块链的ChainID
	chainID, err := client.ChainID(context.Background())
	if err != nil {
		fmt.Println("获取ChainID失败:", err)
		return "", err
	}
 
	fmt.Println("当前区块链的ChainID:", chainID)
	//创建签名者
	signer := types.NewLondonSigner(chainID)
	//对交易进行签名
	signTx, err := types.SignTx(tx, signer, privateKeyECDSA)
	if err != nil {
		return "", err
	}
	//发送交易
	err = client.SendTransaction(context.Background(), signTx)
	if err != nil {
		return "", err
	}

4.5, call the function in the main function

func main() {
	client, err := ethclient.Dial("https://goerli.infura.io/v3/3214cac49d354e48ad196cdfcefae1f8")
	if err != nil {
		fmt.Println("ethclient.Dial error : ", err)
		os.Exit(0)
	}
	tx, err := transfer(client, privateKey, toAddress, contractAddress)
	if err != nil {
		fmt.Println("transfer error : ", err)
		os.Exit(0)
	}

	fmt.Println("使用go调用智能合约第二讲:transfer tx : ", tx)

}

 5. Execute the main method

 Our code has been successfully executed, let's go to the blockchain explorer to have a look

 

It can be seen that the blockchain has confirmed our transaction

In this tutorial, we learned how to use go to call contract abi to interact with smart contracts. If you have any questions during the learning process, you can leave me a message on the official account. I will reply you as soon as I see it. In addition The official account will also share cutting-edge information about blockchain and web3 from time to time. Interested friends can stay tuned

 Please pay attention to the official account: Web3_preacher ( web3_preacher ) , reply "go contract call" to receive the complete code

 

 

Guess you like

Origin blog.csdn.net/rao356/article/details/131979356