:2026-03-06 2:12 点击:2
随着区块链技术的飞速发展,以太坊作为最智能合约平台之一,其代币(如ERC-20标准代币)的转账操作成为开发者必备技能,本文将详细介绍如何使用Go语言结合以太坊官方库go-ethereum,实现以太坊代币的转账功能,涵盖环境准备、核心代码实现及注意事项。
在开始编写Go代码之前,我们需要确保以下环境已准备就绪:
GOPATH和GOROOT。安装Go-ethereum库:
go get github.com/ethereum/go-ethereum go get github.com/ethereum/go-ethereum/accounts/abi go get github.com/ethereum/go-ethereum/accounts/abi/bind go get github.com/ethereum/go-ethereum/common go get github.com/ethereum/go-ethereum/crypto go get github.com/ethereum/go-ethereum/ethclient
以太坊代币转账本质上是调用代币合约的transfer函数,以下是使用Go语言实现代币转账的详细步骤和代码示例。
我们需要创建一个与以太坊节点的连接。
package main
import (
"context"
"crypto/ecdsa"
"fmt"
"log"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
// 替换为你的以太坊节点RPC URL
rpcURL := "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"
client, err := ethclient.Dial(rpcURL)
if err != nil {
log.Fatalf("Failed to connect to the Ethereum network: %v", err)
}
defer client.Close()
fmt.Println("Successfully connected to the Ethereum network")
}
加载或生成转账者的以太坊账户,并获取其公钥地址。
// 加载私钥(实际项目中应从安全的地方读取,如密钥库、环境变量等)
privateKey, err := crypto.HexToECDSA("YOUR_PRIVATE_KEY_WITHOUT_0X")
if err != nil {
log.Fatalf("Failed to parse private key: %v", err)
}
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatalf("Error casting public key to ECDSA: %v", err)
}
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
fmt.Printf("From Address: %s\n", fromAddress.Hex())
定义目标代币的合约地址和ABI(Application Binary Interface),ERC-20代币的ABI是标准的,我们可以使用go-ethereum提供的部分ABI或手动编写。
// 替换为你想要转账的ERC-20代币合约地址
tokenAddress := common.HexToAddress("0_TOKEN_CONTRACT_ADDRESS")
// ERC-20标准的transfer函数签名
// function transfer(address to, uint256 amount) returns (bool)
// 这里我们使用一个简化的ABI,实际项目中建议使用完整的ERC-20 ABI
tokenAbi, err := abi.JSON([]string{`[
{
"constant": false,
"inputs": [
{
"name": "to",
"type": "address"
},
{
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
]`})
if err != nil {
log.Fatalf("Failed to parse token ABI: %v", err)
}
调用代币合约的transfer函数,构建交易参数。
// 接收者地址
toAddress := common.HexToAddress("0_RECEIVER_ADDRESS")
// 转账代币数量(注意:代币有精度,例如USDT有6位小数,1 USDT = 1000000)
// 假设我们要转账10个代币,代币精度为18(如ETH)
amount := big.NewInt(10)
amount.Mul(amount, new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) // 10 * 10^18
// 创建调用transfere函数的调用选项(包含nonce, gasPrice, gasLimit)
auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) // mainnet chainID is 1, testnet varies
if err != nil {
log.Fatalf("Failed to create authorized transactor: %v", err)
}
// 设置GasPrice (可根据网络情况调整)
gasPrice, err := c
lient.SuggestGasPrice(context.Background())
if err != nil {
log.Fatalf("Failed to suggest gas price: %v", err)
}
auth.GasPrice = gasPrice
// 设置GasLimit (可根据代币transfer函数的gas消耗调整,通常建议高于预估值)
auth.GasLimit = uint64(200000) // 200,000 gas
// 创建调用transfer函数的tx数据
// packData, err := tokenAbi.Pack("transfer", toAddress, amount)
// if err != nil {
// log.Fatalf("Failed to pack transfer data: %v", err)
// }
// auth.Value = big.NewInt(0) // 代币转账不需要发送ETH
// tx := types.NewTransaction(auth.Nonce, tokenAddress, auth.Value, auth.GasLimit, auth.GasPrice, packData)
// 更简单的方式:使用bind.NewBoundContract
contract := bind.NewBoundContract(tokenAddress, tokenAbi, client, client, client)
// 调用transfer函数(注意:这里是构建交易,不是直接调用)
transferFn := contract.Transact(auth, "transfer", toAddress, amount)
fmt.Printf("Transfer transaction hash: %s\n", transferFn.Hash().Hex())
fmt.Printf("Waiting for transaction to be mined...")
// 等待交易被打包
receipt, err := bind.WaitMined(context.Background(), client, transferFn)
if err != nil {
log.Fatalf("Failed to wait for transaction mining: %v", err)
}
if receipt.Status == 1 {
fmt.Println("Transaction successfully mined!")
fmt.Printf("Transaction receipt: %+v\n", receipt)
} else {
fmt.Println("Transaction failed!")
fmt.Printf("Transaction receipt: %+v\n", receipt)
}
decimals可能不同,转账时金额需要乘以10^decimals,USDT的decimals是6,转账10 USDT,金额参数应为10 * 10^6。ChainID与你要操作的网络(主网、Ropsten、Goerli、Kovan等)一致。GasLimit设置过可能导致交易失败,设置过高会浪费Gas,可以先用EstimateGas预估一个合理的值。本文详细介绍了如何使用Go语言和go-ethereum库实现以太坊ERC-20代币的转账,从连接节点、准备账户,到构建交易和等待确认,每一步都给出了代码示例
本文由用户投稿上传,若侵权请提供版权资料并联系删除!