干货 | 理解ERC-20 token合约
这周(译者注:原文发表于9月15日)的早些时候,ERC-20 token接口正式成为了改进协议,明确了其定义。这篇文章会简单介绍各种符合ERC-20标准的token,解释ERC-20的特征和功能,以供读者了解什么是token合约,以及开发者应该如何使用该标准。
ERC-20最初作为一种尝试,旨在为以太坊(Ethereum)上的token合约提供一个特征与接口的共同标准,并且,它现在已经被证明是非常成功的了。ERC-20有很多好处,包括允许钱包显示数以百计不同token的账户余额;创建一个交易工具,只需提供token合约的地址就可以将更多token列入表中。创建ERC-20兼容token的好处很多,以至于在今天,很少有其他token合约用其他方式创建。
Token合约是什么?
现在仍存在着大量关于“token合约到底是什么”的争论。本质上来说,一个token合约就是一个包含了一个对账户地址及其余额的映射的智能合约(Smart Contract)。账户余额表示一种由合约创建者定义的值:一个token合约也许使用余额来表示物理对象,或是表示另一种货币价值,还可以表示持有人的名誉。余额的单位通常被称为token。
当token从一个账户被转移到另一个账户的时候,token合约更新两个账户的余额。比如,一笔从 0x2299…3ab7 到 0x1f59…3492 的10个token的转账将导致余额列表如下图所示进行更新:
如果该token合约允许的话,变更一种token的总供给可能有两种办法。token的总供给可以通过铸造新token来增加。举个例子,铸造出100个token到地址 0x4ba5…ae22 将导致余额如下图所示进行更新:
token的总供给也可以通过“销毁”现有的token来减少。比如, 0x4919…413d 销毁了50个token,这将导致余额如下图所示更新:
销毁token的另一种方式是将token发送到一个未创建私钥的地址,通常来说就是0地址。这会使得这些token不可用,在这方面,它与销毁token有同样的效果,但并没有减少token的总数。比如, 0x93f1…1b09 用此种方式销毁了50个token将导致如下图所示的余额:
简单的token合约在一个从地址到余额的映射中保存上述信息。当更多复杂的情景出现时,比如发放股息,替代性结构或者增补性结构常常要变得更强悍。但是,不管那些操作上的细节的话,对外部可见的token余额总是像上面的图示那样的。
一个ERC-20 token合约的定义
一个ERC-20 合约是通过合约的地址以及它可用的token总供给来定义的,但它通常还提供一些非必须的东西,也是为用户提供更多细节。它们包括该token的名字、标志、小数位。这些中的每一个都会包括在下面的细节中。
在深入到细节之前,理解这件事情是重要的:token合约没有一个中心化的登记处,因此无法保证特定名字和符号的唯一性。一旦你已经创建了一个token合约,你应该请求将它加入公共站点,比如:Etherscan,MyEtherWallet 以及 CoinMarketCap。当然,确保符合网站上的说明可以最大化你的申请被接受的机会。
Token合约的名字
乃是该token合约应该被知道的完整名称,比如“My Token”。名字的长度没有限制,但完整名称在一些钱包应用中更容易显示不完全,所以,最好让名字短一点。
Token合约的标志
乃是该token合约应该被知道的符号,比如“MYT”。广义上,它是股票代码的对应物,而且,虽然没有严格的长度限制,但它在长度上常常是3或4个字母。
小数位
常常是混淆的来源,但经过合理的解释这是非常容易理解的。小数位
意味着一个token的可切分性,从0个小数位(即完全不可切分)到18位小数(几乎是连续的),如果需要,可以有更多的小数位。从技术上来说,小数位
的意义在于显示token价值在屏幕上的时候小数点后面跟着的位数。小数位
存在的理由是以太坊并不处理有小数的数字,只显示整数的数字价值。考虑下面两个例子:
第一个例子是LicenseToken,一个为给定软件产品显示软件许可分配的token合约;持有一个LicenseToken,使用者就可以使用该软件。而持有小于1个的LicenseToken则没有任何意义,所以token创建者将小数位
设为0。一些LicenseToken的持有人账户余额如下。
可以看到,在这里有100份许可,主要被一个账户所持有。当用户购买一份许可的时候,一个token将从持有账户转账到购买者账户。而许可验证者可以查看一个特定的账户是否真的持有一个LicenseToken,然后做出相应的行动。
第二个例子是GoldToken,一个表示物理黄金所有权的token合约。合约创建者希望每单位表示1千克黄金的单位,但同样希望允许用户以克的级别(但不能更低)持有和交易黄金。因为以太坊并不支持小数因此1个token必须表示1克黄金,以及,为了向外界表示1000克作为单一的1Kg单位,小数位
要设置成3
(因为 10^3 克也就是1千克黄金才是token合约创建者希望显示为1token的单位)。一些GoldToken的持有者可以用图像表示在下方。
在这里你可以看到总共有50Kg的黄金被表示出来(每token 1克乘以50,000个token)。
但是,如果小数位
被设成3
,用户的情形就会像下面这样:
可以看到,将小数位
设置成3
在字面上就意味着在显示GoldToken余额的时候,应该有3位数跟在小数点后面。
小数位
经常被称为是一个人性化的元素,因为它允许token合约定义他们希望余额怎样显示给用户。GoldToken并不在内部处理小数位
,也从不将小数位
用在它自己的计算中因为一切都是用克来计算的,但它允许用户使用黄金的共通单位(千克)而不是在合约中使用的单位(克)。
正如在上述GoldToken中显示的,可切分性的观念允许token合约显示非常小的小数值,并且token也常常把小数位
设成18
,以给予token一个近乎连续的价值范围。
总结一下,在决定要取几个小数位
时,下述规则是应该被遵循的:
token合约表示的是一个不可切分的物体吗?(如果是)那么将
小数位
设为0
token合约表示的是一个有特定小数位的物体吗?那么将
小数位
设置到那个数字如果上述两者都不是,请设置
小数位
为18
重要的是要知道小数位对合约创建的影响。被创建的Token数量应该等于token的全部数量,要求是10^小数位
的倍数。正如在GoldToken例子中可以看到的,token创建者希望创建token来表示50千克的黄金,但因为3位小数,他们必须发行50,000 token(50×10^3)来做成这件事。
总供给
是定义一个ERC-20 token合约的最后一个东西,并且,正如我们提到过的,它是唯一的强制参数。虽然在ERC-20说明书中并没有明确提到,但总供给
的概念是简单的:总供给
等于所有余额的和。上面的例子中一直显示着总供给
,所以这里就无需赘述了。
一个ERC-20 token合约的功能
ERC-20 token合约拥有一系列的功能,允许用户发现用户的余额,也允许余额经过验证从一个账户转账到另一个账户。下面来描述一下这些功能。
balance()
函数提供了被一个给定地址持有的token的数量。记住,任何人都可以查到任何地址的余额,正如所有数据在区块链上都是公开的。
从一个地址发送token到另一个地址有两种办法。tranfer()
函数可以从信息发送者那里直接转一些token到林一个地址。记住,人们不会查验接收地址,因此确保接收者按预期的方式行动是发送者的责任。
虽然用transfer()
来发送toke给另一个用户是很棒的,但当token要被用来为一个智能合约中的函数进行支付的时候,它就起不了作用了。这是因为,当智能合约运行的时候,它没办法获得哪个地址转账到哪里的细节,因此也就无法保证调用这个合约的用户已经支付了启动合约要求数量的资金。
想象一下,有一个合约Doer
被部署在网络上。Doer
拥有一个函数dosomething()
,它要求10 Do
token来运行。Joe希望调用dosomething()
,也有50Do
token在他的账户上。Joe怎样能够支付给Doer
以致后者可以成功运行dosomething()
呢?
approve()
和transferFrom()
是两个方程,它们使用一个两步过程,可以解决上面的问题。第一步,一个token持有者给另一个地址(常常是一个智能合约)批准从本地转出一个最大特定数量的token,也就是所谓的配额(allowence)。Token持有者使用approve()
来提供这些信息。
在上述例子中,第二行显示,地址为 0x1f59…3492 的Joe已经允许地址为 0xd8f0…c028 的Doer
从Joe的账户中转出25个token。
一旦一个许可被创建,智能合约就可以从一个用户的配额中占用许可数量的token,作为该合约运行的一部分。继续这个例子。Joe现在可以调用dosomething()
,而dosomething()
可以使用transferFrom()
以从Joe的账户中获得10个Do
token, 然后开始它的工作。如果Joe的账户上没有10个token,或者配额低于10个token,dosomething()
就会当机。
allowance()
函数提供了允许从一个给定地址提取到另一个给定地址的token的数量。记住,任何人都可以查到任何地址的余额,正如所有信息在区块链上都是公开的。重要的是知道,配额是“软性”的,因为所有单独的或者累积的配额可以超过一个地址的余额。在上面展示的表格中,持有者 0x2299…3ab7 许可了最高500个token的转出,但他的余额,如上所示,只有90个token。任何使用allowance()
的合约,在计算可用的token数量的时候,都必须额外考虑用户的余额。
一个ERC-20 token合约中的事件
ERC-20定义了在合约采取了相关行动的时候,两类事件是必须被触发的。第一类事件是Transfer()
,就是放出从一个地址转移到另一个地址的token转移的细节。第二类事件是Approval()
,就是放出从一个地址许可转移token到另一个地址的细节。这些可以被用来跟踪地址余额和配额的变更,而无需查询区块链。
铸造token会发出了一个带有o地址的Transfer()
事件作为源。
当token被销毁的时候,没有事件会发出。因为这一点,ERC-20 token 合约常常通过transfer()
发送token到0地址来销毁token,代替真正的销毁。
超越ERC-20
ERC-20提供了一个良好的基础来构建token合约,但也并不是没有问题。ERC-223协议提供了额外的特性和安全措施,但与ERC-20并不兼容。Token合约的建构在今天还要继续遵循ERC-20,而开发者应该跟踪 ERC-223协议,并为它做出贡献。
原文链接:
https://medium.com/@jgm.orinoco/understanding-erc-20-token-contracts-a809a7310aa5
作者: Jim McDonald
翻译&校对: 阿剑 & Elisa
更多文章:
Ethereum Casper 101 | 初识以太坊 Casper
采访 | ETHNews 对 Vitalik Buterin 的独家专访