跳到主要内容

查询ERC20代币智能合约

首先创建一个ERC20智能合约interface。 这只是与您可以调用的函数的函数定义的契约。

pragma solidity ^0.4.24;

contract ERC20 {
string public constant name = "";
string public constant symbol = "";
uint8 public constant decimals = 0;

function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

然后将interface智能合约编译为JSON ABI,并使用abigen从ABI创建Go包。

solc --abi erc20.sol
abigen --abi=erc20_sol_ERC20.abi --pkg=token --out=erc20.go

假设我们已经像往常一样设置了以太坊客户端,我们现在可以将新的token包导入我们的应用程序并实例化它。这个例子里我们用Golem 代币的地址.

tokenAddress := common.HexToAddress("0xa74476443119A942dE498590Fe1f2454d7D4aC0d")
instance, err := token.NewToken(tokenAddress, client)
if err != nil {
log.Fatal(err)
}

我们现在可以调用任何ERC20的方法。 例如,我们可以查询用户的代币余额。

address := common.HexToAddress("0x0536806df512d6cdde913cf95c9886f65b1d3462")
bal, err := instance.BalanceOf(&bind.CallOpts{}, address)
if err != nil {
log.Fatal(err)
}

fmt.Printf("wei: %s\n", bal) // "wei: 74605500647408739782407023"

我们还可以读ERC20智能合约的公共变量。

name, err := instance.Name(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

symbol, err := instance.Symbol(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

decimals, err := instance.Decimals(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

fmt.Printf("name: %s\n", name) // "name: Golem Network"
fmt.Printf("symbol: %s\n", symbol) // "symbol: GNT"
fmt.Printf("decimals: %v\n", decimals) // "decimals: 18"

我们可以做一些简单的数学运算将余额转换为可读的十进制格式。

fbal := new(big.Float)
fbal.SetString(bal.String())
value := new(big.Float).Quo(fbal, big.NewFloat(math.Pow10(int(decimals))))

fmt.Printf("balance: %f", value) // "balance: 74605500.647409"

同样的信息也可以在etherscan上查询: https://etherscan.io/token/0xa74476443119a942de498590fe1f2454d7d4ac0d?a=0x0536806df512d6cdde913cf95c9886f65b1d3462


完整代码

Commands

solc --abi erc20.sol
abigen --abi=erc20_sol_ERC20.abi --pkg=token --out=erc20.go

erc20.sol

pragma solidity ^0.4.24;

contract ERC20 {
string public constant name = "";
string public constant symbol = "";
uint8 public constant decimals = 0;

function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

contract_read_erc20.go

package main

import (
"fmt"
"log"
"math"
"math/big"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"

token "./contracts_erc20" // for demo
)

func main() {
client, err := ethclient.Dial("https://cloudflare-eth.com")
if err != nil {
log.Fatal(err)
}

// Golem (GNT) Address
tokenAddress := common.HexToAddress("0xa74476443119A942dE498590Fe1f2454d7D4aC0d")
instance, err := token.NewToken(tokenAddress, client)
if err != nil {
log.Fatal(err)
}

address := common.HexToAddress("0x0536806df512d6cdde913cf95c9886f65b1d3462")
bal, err := instance.BalanceOf(&bind.CallOpts{}, address)
if err != nil {
log.Fatal(err)
}

name, err := instance.Name(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

symbol, err := instance.Symbol(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

decimals, err := instance.Decimals(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

fmt.Printf("name: %s\n", name) // "name: Golem Network"
fmt.Printf("symbol: %s\n", symbol) // "symbol: GNT"
fmt.Printf("decimals: %v\n", decimals) // "decimals: 18"

fmt.Printf("wei: %s\n", bal) // "wei: 74605500647408739782407023"

fbal := new(big.Float)
fbal.SetString(bal.String())
value := new(big.Float).Quo(fbal, big.NewFloat(math.Pow10(int(decimals))))

fmt.Printf("balance: %f", value) // "balance: 74605500.647409"
}

solc version used for these examples

$ solc --version
0.4.24+commit.e67f0147.Emscripten.clang

title: 查询ERC20代币智能合约 description: "这本迷你书的本意是给任何想用Go进行以太坊开发的同学一个概括的介绍。本意是如果你已经对以太坊和Go有一些熟悉,但是对于怎么把两者结合起来还有些无从下手,那这本书就是一个好的起点。" image: "https://ipfs.decert.me/QmfZm4ZahZBcpLNoMwNBX5kNLNaQ6PsPRV7oiJXTudvYWy" sidebar_label: "查询ERC20代币智能合约"

概述: 用Go来查询ERC20代币智能合约的教程。

查询ERC20代币智能合约

首先创建一个ERC20智能合约interface。 这只是与您可以调用的函数的函数定义的契约。

pragma solidity ^0.4.24;

contract ERC20 {
string public constant name = "";
string public constant symbol = "";
uint8 public constant decimals = 0;

function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

然后将interface智能合约编译为JSON ABI,并使用abigen从ABI创建Go包。

solc --abi erc20.sol
abigen --abi=erc20_sol_ERC20.abi --pkg=token --out=erc20.go

假设我们已经像往常一样设置了以太坊客户端,我们现在可以将新的token包导入我们的应用程序并实例化它。这个例子里我们用Golem 代币的地址.

tokenAddress := common.HexToAddress("0xa74476443119A942dE498590Fe1f2454d7D4aC0d")
instance, err := token.NewToken(tokenAddress, client)
if err != nil {
log.Fatal(err)
}

我们现在可以调用任何ERC20的方法。 例如,我们可以查询用户的代币余额。

address := common.HexToAddress("0x0536806df512d6cdde913cf95c9886f65b1d3462")
bal, err := instance.BalanceOf(&bind.CallOpts{}, address)
if err != nil {
log.Fatal(err)
}

fmt.Printf("wei: %s\n", bal) // "wei: 74605500647408739782407023"

我们还可以读ERC20智能合约的公共变量。

name, err := instance.Name(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

symbol, err := instance.Symbol(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

decimals, err := instance.Decimals(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

fmt.Printf("name: %s\n", name) // "name: Golem Network"
fmt.Printf("symbol: %s\n", symbol) // "symbol: GNT"
fmt.Printf("decimals: %v\n", decimals) // "decimals: 18"

我们可以做一些简单的数学运算将余额转换为可读的十进制格式。

fbal := new(big.Float)
fbal.SetString(bal.String())
value := new(big.Float).Quo(fbal, big.NewFloat(math.Pow10(int(decimals))))

fmt.Printf("balance: %f", value) // "balance: 74605500.647409"

同样的信息也可以在etherscan上查询: https://etherscan.io/token/0xa74476443119a942de498590fe1f2454d7d4ac0d?a=0x0536806df512d6cdde913cf95c9886f65b1d3462


完整代码

Commands

solc --abi erc20.sol
abigen --abi=erc20_sol_ERC20.abi --pkg=token --out=erc20.go

erc20.sol

pragma solidity ^0.4.24;

contract ERC20 {
string public constant name = "";
string public constant symbol = "";
uint8 public constant decimals = 0;

function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

contract_read_erc20.go

package main

import (
"fmt"
"log"
"math"
"math/big"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"

token "./contracts_erc20" // for demo
)

func main() {
client, err := ethclient.Dial("https://cloudflare-eth.com")
if err != nil {
log.Fatal(err)
}

// Golem (GNT) Address
tokenAddress := common.HexToAddress("0xa74476443119A942dE498590Fe1f2454d7D4aC0d")
instance, err := token.NewToken(tokenAddress, client)
if err != nil {
log.Fatal(err)
}

address := common.HexToAddress("0x0536806df512d6cdde913cf95c9886f65b1d3462")
bal, err := instance.BalanceOf(&bind.CallOpts{}, address)
if err != nil {
log.Fatal(err)
}

name, err := instance.Name(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

symbol, err := instance.Symbol(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

decimals, err := instance.Decimals(&bind.CallOpts{})
if err != nil {
log.Fatal(err)
}

fmt.Printf("name: %s\n", name) // "name: Golem Network"
fmt.Printf("symbol: %s\n", symbol) // "symbol: GNT"
fmt.Printf("decimals: %v\n", decimals) // "decimals: 18"

fmt.Printf("wei: %s\n", bal) // "wei: 74605500647408739782407023"

fbal := new(big.Float)
fbal.SetString(bal.String())
value := new(big.Float).Quo(fbal, big.NewFloat(math.Pow10(int(decimals))))

fmt.Printf("balance: %f", value) // "balance: 74605500.647409"
}

solc version used for these examples

$ solc --version
0.4.24+commit.e67f0147.Emscripten.clang