上一篇我们介绍了如何创建ERC20代币的过程,本文我们将介绍利用JSON-API接口对ERC20代币进行的一些开发过程中的相关操作。
1. 发送代币。
ETH的Transaction
有几个重要字段,from
, to
, value
, data
(input
)。
from
: Transaction是由谁发起的。
to
: Transaction发送到哪个地址。
value
: Transaction发送的ETH数量。
data
: 某些api中字段名字叫做input
,含义都一样,代表这个Transaction附带的数据,通常是执行某些智能合约的命令。
在Ethereum JSON-Api 的使用 一文中,我们介绍了JSON-API的一些基本使用,可以先行阅读,便于理解本文一些概念。
代币的发送,也是通过Transaction进行,不同于发送ETH的是,from
是token发送方地址,to
是token的合约地址,value
通常为0,如果不需要ETH随同token一起发送的话。data
是根据不同的token和接收地址,以及数量进行编码得到的,编码格式遵循Ethereum Contract ABI格式。详细的信息可以阅读链接中以太坊的官方文章介绍,此处介绍一下实现的重要细节即可。
通常的token发送,data
部分包括三个部分, 1. 指令的hash;2. 接收账户;3. 数量,由这三个部分拼接而成。
1.指令hash。
回到ERC20的代码中,发送的函数如下,根据ABI编码的规则,我们要通过web3.sha3("transfer(address,uint256)")
方法计算得到值,取前4个字节(8个16进制数)得到Transaction中的指令hash。ERC20标准的transfer
函数的指令hash前8字节为a9059cbb
。
/**
* Transfer tokens
*
* Send `_value` tokens to `_to` from your account
*
* @param _to The address of the recipient
* @param _value the amount to send
*/
function transfer(address _to, uint256 _value) public {
_transfer(msg.sender, _to, _value);
}
2.接收账户。
通常的以太坊账户为20字节(40个16进制数),前面加上0x
。在data部分,需要将40个16进制数前面填充24个0
,总共64个16进制数。
3.数量。
将数量转化成16进制(以1e-18为单位),同样填充若干个0
,填充为64个16进制数。
然后将三个部分拼接而成Transaction的data。例如,向0x299432642dcc4c2f33ff0f5d41b8f4154b82ae2a
地址发送1000个token。data部分凭接如下:
0x
+ a9059cbb
+ 000000000000000000000000299432642dcc4c2f33ff0f5d41b8f4154b82ae2a
(接收地址)+00000000000000000000000000000000000000000000021e19e0c9bab2400000
(接收数量16进制表示,以1e-18为单位)。所以发送的Transaction参数为:
from
: 0x发送地址
;
to
:0x合约地址
;
value
:0x;
data
:0xa9059cbb000000000000000000000000299432642dcc4c2f33ff0f5d41b8f4154b82ae2a00000000000000000000000000000000000000000000021e19e0c9bab2400000
.
2. 查看某地址代币余额。
查看token余额,相当于是查看区块链某个位置上的数据变量值,需要通过JSON-API发送eth.getStorageAt
获得。
contract TokenERC20 {
// Public variables of the token
string public name;
string public symbol;
uint8 public decimals = 18;
// 18 decimals is the strongly suggested default, avoid changing it
uint256 public totalSupply;
// This creates an array with all balances
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
上述ERC20代码中的变量,其中mapping(address => uint256) public balanceOf;
是用于存放每个账户余额的变量。获取的规则是,balanceOf
是第4个参数(name是第0个),将4补充成64个16进制数,即0000000000000000000000000000000000000000000000000000000000000004
.然后按照发送token的规则,将要获取余额的地址补充成64个16进制数。获得input = "64位地址"+"64位变量位置"
的字符串,然后计算得到hash = web3.sha3(input)
。最后通过eth.getStorageAt(contract address, hash, 'latest')
得到这个地址的token余额。