无法在网上找到上述问题的解决方案,因此将其发布在这里: 对于 golang,我们需要使用 go-ethereum 包来执行智能合约相关操作。它类似于我们在 javascript 中用于智能合约操作的 ethers.js。
import (
"encoding/hex"
"encoding/json"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"
)
// Connect to the Ethereum client
client, err := rpc.Dial("<rpc_node_url>")
if err != nil {
fmt.Println("unable to create client due to error: %s", err)
}
defer client.Close()
// Address of the smart contract
contractAddress := "<contract_address_here>"
// abi of the function to be executed
contractABI := []byte(`<function_abi_here>`)
// parsing ABI of the function to be executed
parsedABI := abi.ABI{}
err = json.Unmarshal(contractABI, &parsedABI)
if err != nil {
fmt.Println("error while unmarshaling abi: %s", err)
}
inputData, err := parsedABI.Pack("<function_name_here>", <args_comma_seperated_here>)
if err != nil {
fmt.Println("unable to pack input data due to error: %s", err)
}
var invokeResponse string
// Call a view function of the smart contract
err = client.Call(&invokeResponse, "eth_call", map[string]interface{}{
"to": contractAddress,
"data": hex.EncodeToString(inputData),
}, "latest")
if err != nil {
fmt.Println("unable to call contract due to error: %s", err)
}
// Decode the hex response into bytes
data, err := hexutil.Decode(invokeResponse)
if err != nil {
fmt.Println("unable to decode invoke hex response due to error: %s", err)
}
var resp responseStruct
err = parsedABI.UnpackIntoInterface(&resp, "<function_name_here>", data)
if err != nil {
fmt.Println("unable to unpack invoke response due to error: %s", err)
}
在网上找不到上述问题的解决方案,正在考虑直接使用一些包来解决
这只是一个非常快速的答案,但应该可以满足您的需求。这是一个对 erc20 合约调用“balanceOf”的函数:
func ERC20GetBalanceOf(ctx context.Context, client *ethclient.Client, erc20Abi *abi.ABI, tokenAddr *common.Address,
queryAddr *common.Address) (*big.Int, error) {
balanceData, err := erc20Abi.Pack("balanceOf", queryAddr)
if err != nil {
return nil, fmt.Errorf("error packing balanceOf data %w", err)
}
balanceMsg := ethereum.CallMsg{
To: tokenAddr,
Data: balanceData,
}
balanceResult, err := client.CallContract(ctx, balanceMsg, nil)
if err != nil {
return nil, fmt.Errorf("error calling balanceOf function: %w", err)
}
balance, err := erc20Abi.Unpack("balanceOf", balanceResult)
if err != nil {
return nil, fmt.Errorf("error unpacking balanceOf result: %w", err)
}
return balance[0].(*big.Int), nil
}
当然,如果您正确遵循
client.Call
中的幕后操作,您可以使用较低级别的调用,例如 client.CallContract(ctx, balanceMsg, nil)
。
但我相信我给您的是最常见的方法,无需生成 abi 绑定函数,如 goethereumbook
中所述