译者 / blockgeeks
编辑 / guoxi
人们常说:“钱不是万能的,但没钱是万万不能的”。在某种程度上,经济基础影响甚至是决定了开源应用的发展。 就拿以太坊来说,以太坊项目于2014年7月23日开启众筹,长达42天的众筹时间里共为以太坊募集了3.1万个比特币,在当时总价值超过了1800万美金。充裕的资金是以太坊项目成功的关键,也是其创造辉煌的有力保障。 同样的,以太坊平台上的去中心化应用开发者也都需要“启动资金”。所以一时间,各式各样的众筹活动充斥全网。无以规矩,不成方圆。由于全网没有一个统一的众筹标准,不同通证之间的交易难度不亚于绕过交易所购买加密货币,这严重制约了通证的流通性和以太坊的发展。 ERC-20标准的出现解决了上述的难题。在本文中,我们将从智能合约的出现开始,结合以太坊平台众筹活动存在的问题,着重讲述ERC-20标准的细则,并分析ERC-20通证的未来。
ERC-20通证对整个加密货币世界产生了举足轻重的影响,它造就了数十亿美元的ICO产业,也促进了加密货币走向主流。ERC-20标准就是有着这样的魔力,在我们了解ERC-20通证是什么以及它们如何影响加密世界之前,让我们先来回顾一些基础知识。
当一位自称中本聪(Satoshi Nakamoto)的匿名开发人员创建比特币时,伴随而生的区块链技术和加密货币概念走进了人们的视野。从某些方面来说,比特币可以看作是一场巨大的革命。比特币的出现使得人民所有和人民所控的货币体系成为可能,也就是说你可以绕过银行,将比特币发送给任何拥有比特币钱包的人。
为了更好地描述和区分区块链技术,人们通常把比特币的底层区块链称为“第一代区块链”。但不能否认的是,比特币的交易方式存在很大的局限性。
事实证明,加密货币市场中的交易并不总是比特币设想的那么简单。
如果你想通过一个简单的一对一交易向你的朋友转一些钱,那么在这种情况下比特币是完全可以胜任的。
但是,如果你想为转账设置一些条件,比如你的朋友在特定期限内完成一定量的任务后,你才会转账给他,那么这种复杂的交易该怎么实现呢?你该如何编写交易代码来实现这种复杂场景下的交易?
这个问题困扰着加密世界中的每一个人,直到天才少年 Vitalik Buterin 创建了以太坊,这个问题才得到了解决。
Vitalik Buterin意识到区块链技术不应该仅仅局限为一个支付手段,它应该有更多的应用场景。于是他在网站上这么写道:
“以太坊是一个运行智能合约的去中心化平台,在以太坊上,应用程序完全按照自身的代码运行,没有任何停机,审查,欺诈或第三方干扰的可能性。这些应用程序运行在定制的区块链上,这是一个全球共享的强大基础架构,可以在上面转移价值以及声明财产的所有权。”
简而言之,以太坊计划成为一个去中心化的超级计算机,任何地方的任何人都可以租用一些算力来创建可以在以太坊平台上运行的去中心化应用程序(decentralized applications ,Dapps)。
那么,你该如何制作这些Dapps?为此,我们需要首先来研究智能合约。
智能合约是自动执行的合约。当外界触发了某些代码执行的条件后,智能合约就会按照代码中的指令自动执行。
智能合约是以太坊生态系统中执行任务的工具。当有人想要在以太坊中完成特定任务时,他们会生成一个智能合约。
智能合约可帮助你以简单的格式编码实现复杂的交易细节。智能合约的概念由计算机科学家、密码学大牛尼克·萨博(Nick Szabo)在1993年左右提出来。根据他的设想,智能合约在现实生活最贴近的实例就是自动售货机。
当你想要购买自动售货机中的商品时,你只需将现金存入自动售货机,然后选择你想要的商品,自动售货机会给你商品和找零。在这个过程中,你直接与自动售货机进行交互,而无需任何第三方参与。
你只需要遵循以下流程:
就会得到你想购买的商品。
假设你和你的朋友爱丽丝希望使用智能合约来进行交互。
智能合约也会以同样的方式运行。你在智能合约中锁定一些以太币(以太坊通证),智能合约运行的触发逻辑为爱丽丝完成一些任务后,智能合约会自动解锁资金并将资金发送到她的数字钱包。
智能合约开辟了一个全新的舞台以服务于开发人员的创造和创新。但是,创新离不开资金的支持,开发人员需要一条获得项目资助的途径。
怎么来做呢?用ICO。
ICO(Initial Coin Offerings,首次通证发行)是IPO(Initial Public Offerings, 首次公开募股)在加密货币世界中的实现。
而且与IPO相比, ICO对企业更加友好,原因有以下几点:
在我们深入了解ICO的工作原理之前,你还需要知道通证是什么,简单地说,Dapp开发人员需要提供一些东西作为投资者的回报,这些“东西”被称为通证。
一般来说,通证代表其特定生态系统中的某些东西。它可以是价值,股份,投票权或其他任何东西。通证并不限于某个特定角色,它可以在其生态系统中发挥很多作用。
说到这里你可能会问,通证可以扮演的“角色”都有什么?
好的,到目前为止我们已经了解了智能合约,ICO以及通证是如何运作的。然而,在这里我们遇到了第一个障碍,让我们来通过一个街机的例子说明它。
想象一个老式的视频游戏街机。在玩游戏之前,你需要做以下事情:
到这里,相信你肯定能找出街机和智能合约平台的相似之处。
简单来说,游戏街机就是一个Dapp,而游戏币就是你在Dapp中的通证。你需要持有这些通证才能访问Dapp的服务。
但是这个系统存在一个问题。
为了能投入街机的插槽中,游戏币被设定为特定的尺寸形状。那么问题来了,如果某些街机被设定为不支持圆形游戏币而仅支持方形的游戏币呢?
为了顺利开展业务,街机店的老板必须制定一个基本规则,就是所有街机必须设定为只接收圆形游戏币,不能接收其他形状的游戏币。
从本质上讲,这就是ERC-20标准的来源。
在早期,就ICO过程而言,似乎每个ICO通证都在试图“重新发明轮子”。这些通证中的每一个都有自己单独的函数库,这导致了许多新问题。
要在以太坊平台之上建立一个健康的生态系统,建立在它之上的Dapp之间的无缝交互是其中的核心。但是,如果我们有两个通证,叫做Token Alpha和Token Beta,两者有着不同的智能合约结构,会发生什么?
如果这样,开发人员需要仔细研究这些智能合约,并准确地分析这些通证之间如何相互作用。
显然这对于可拓展性来说并不是一个好兆头。
如果现在有100个不同的通证,对应着100个不同的智能合约,那么首先要确定所有这些通证之间转移所需的所有资格和条件,这个过程需要进行大量复杂的计算。这根本就不是一个理想的通证转移场景。
所以说业界急需解决方案,在2015年11月19日,Fabian Vogelsteller提出了一个巧妙的解决方案。
根据维基百科,ERC-20标准是一个:
“以太坊通证必须遵守的规则列表,它使开发人员能够编程写出新通证在以太坊生态系统中执行的功能。由于ERC-20通证具有部署简单、可以与其他以太坊通证标准兼容的优势,它受到了ICO众筹公司的广泛欢迎。”
简单来说,ERC-20标准是一个以太坊通证规则和条例的指南,有助于建立一个使用基于以太坊的智能合约以创建其通证的蓝图。
ERC-20标准命名的背后, “ERC”( Ethereum Request for Comment)代表以太坊征求意见,而数字“20”则代表分配给该征求意见的编号。
到现在你已经明白了ERC-20标准是什么,接下来让我们进一步剖析它,看看这个标准的背后都有些什么。
符合ERC-20标准的通证都遵循一系列规则,以便满足通证共享,通证之间交换或转移和数字钱包等应用场景。ERC-20标准包含3个可选规则和6个强制性规则。
6个强制性规则如下:
另一方面,3个可选规则是:
为了更好地描述,在查看6个强制性规则之前,先让我们首先来学习这3个可选规则。
首先,即使没有强制要求为你的通证命名,但为其提供一个用于识别的身份仍然很重要。声明名称的代码如下:
string public constant name =“Token Name”;
接下来我们来说简写符号,同样的,我们也不能低估它的重要性。OmiseGO就是一个很好的例子,OmiseGO和OMG是同一种通证的不同叫法,但人们通常对它的简称OMG更加熟悉。可以说,一个吸引人的简写符号有助于树立更好的品牌形象。这个简写符号的设定方式为:
string public constant symbol =“SYM”;
最后,我们来谈谈通证的可分性,也就是通证的最小可行单位。可分性为0意味着通证的最小单位为1。另一方面,可分性为2意味着通证最小单位为0.01。ERC-20标准中允许的最大小数位数是18位,具体的声明方法如下:
uint8 public constant decimals = 18;
好的,现在让我们来分析6条强制性规则。
1. 总供应量(totalSupply)
totalSupply()函数用来表示创建的ERC-20通证的总数。此功能的目的是确定在生态系统中流通的通证总数。
总供应量代码如下所示:
contract MyERCToken {
uint256 _totalSupply = 1000000;
function totalSupply() constant returns (uint256 theTotalSupply) {
theTotalSupply = _totalSupply;
return theTotalSupply;
}
}
2. 余额(balanceOf)
balanceOf()函数返回特定地址(在本例中为智能合约的所有者)的帐户中剩余通证数目。
余额代码如下所示:
contract MyERCToken {
// Create a table so that we can map addresses
// to the balances associated with them
mapping(address => uint256) balances;
// Owner of this contract
address public owner;
function balanceOf(address _owner) constant returns (uint256 balance) {
// Return the balance for the specific address
return balances[_owner];
}
}
3. 批准(approve)
一旦检查完余额,智能合约所有者可以批准用户从智能合约地址提取指定数量的通证。批准功能还会根据通证的总供应量检查交易,以确保没有丢失或产生额外的通证。换句话说,它消除了伪造通证的可能。
注意:“msg.sender”是智能合约所有者的地址。
contract MyERCToken {
// Create a table so that we can map
// the addresses of contract owners to
// those who are allowed to utilize the owner's contract
mapping(address => mapping (address => uint256)) allowed;
function approve(address _spender, uint256 _amount) returns (bool success) {
allowed[msg.sender][_spender] = _amount;
// Fire the event "Approval" to execute any logic
// that was listening to it
Approval(msg.sender, _spender, _amount);
return true;
}
}
4. 发送(transfer)
因此,既然已完成所有检查并且智能合约知道用户完成交易所需通证的数量,则智能合约所有者可以使用transfer()函数向他们发送通证。
此功能使得智能合约的所有者可以很轻易地将给定数量的通证发送到一个用户账户中,就像传统的加密货币交易一样,允许将一定数量的通证从总供应量中发送到用户帐户中。
contract MyERCToken {
mapping(address => uint256) balances;
// Note: This function returns a boolean value
// indicating whether the transfer was successful
function transfer(address _to, uint256 _amount) returns (bool success) {
// If the sender has sufficient funds to send
// and the amount is not zero, then send to
// the given address
if (balances[msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[msg.sender] -= _amount;
balances[_to] += _amount;
// Fire a transfer event for any
// logic that's listening
Transfer(msg.sender, _to, _amount);
return true;
} else {
return false;
}
}
}
5. 从…发送(transferFrom)
嗯......等等。
我们已经有了transfer()函数,为什么我们还需要另一个?
那么,让我们通过一个例子来看看为什么transferFrom()函数是ERC-20智能合约的一个重要补充。
比如说,有一些费用是需要我们每个月定期支付的,它可能是你的租金,账单等等。事实上,你不需要真的自己动手支付所有这些金额,你可以与银行建立自动付款协议来处理这些付款。
这就是transferFrom()功能允许你做的事情。它可以帮助你给指定的账户自动付款。
代码如下:
contract MyERCToken {
mapping(address => uint256) balances;
function transferFrom(address _from, address _to, uint256 _amount) returns (bool success) {
if (balances[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[_from] -= _amount;
balances[_to] += _amount;
Transfer(_from, _to, _amount);
return true;
} else {
return false;
}
}
}
注意:即使golem GNT通证是最受欢迎的通证之一,但是它不能被归结为ERC-20通证,因为它的智能合约中没有approve()和transferFrom()这两个函数。
6. 限额(allowance)
为了准确地执行交易,智能合约需要知道的一个最重要数据就是用户的余额。毕竟,用户至少应该拥有与交易金额相等的通证才能进行交易。
这就是为什么ERC-20智能合约还包括包含allowance()函数的原因。 如果用户没有所需的最小通证数,则allowance()函数会取消该交易。
代码如下:
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
那么,既然我们已经看到了各个函数的工作原理,那么让我们来看看汇总到一起后的ERC-20通证智能合约。
这是GitHub上的一段代码:
pragma solidity ^0.4.15;
contract MyERCToken
{
// Create a table so that we can map addresses
// to the balances associated with them
mapping(address => uint256) balances;
// Create a table so that we can map
// the addresses of contract owners to
// those who are allowed to utilize the owner's contract
mapping(address => mapping (address => uint256)) allowed;
// In this case, the total supply
// of MyERCToken is fixed, but
// it can very much be changed
uint256 _totalSupply = 1000000;
// Owner of this contract
address public owner;
function totalSupply() constant returns (uint256 theTotalSupply) {
// Because our function signature
// states that the returning variable
// is "theTotalSupply", we'll just set that variable
// to the value of the instance variable "_totalSupply"
// and return it
theTotalSupply = _totalSupply;
return theTotalSupply;
}
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _amount) returns (bool success) {
allowed[msg.sender][_spender] = _amount;
// Fire the event "Approval" to execute any logic
// that was listening to it
Approval(msg.sender, _spender, _amount);
return true;
}
// Note: This function returns a boolean value
// indicating whether the transfer was successful
function transfer(address _to, uint256 _amount) returns (bool success) {
// If the sender has sufficient funds to send
// and the amount is not zero, then send to
// the given address
if (balances[msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[msg.sender] -= _amount;
balances[_to] += _amount;
// Fire a transfer event for any
// logic that's listening
Transfer(msg.sender, _to, _amount);
return true;
} else {
return false;
}
}
function transferFrom(address _from, address _to, uint256 _amount) returns (bool success) {
if (balances[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[_from] -= _amount;
balances[_to] += _amount;
Transfer(_from, _to, _amount);
return true;
} else {
return false;
}
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
// Triggered whenever approve(address _spender, uint256 _value) is called.
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
// Triggered when tokens are transferred.
event Transfer(address indexed _from, address indexed _to, uint256 _value);
}
现在我们知道ERC-20标准是什么了,但使用它有什么好处呢?
缺陷1:transfer()错误
尽管ERC-20通证具有很多优良品质,但金无足赤,人无完人,它也受到了很多批评。就比如说,以太坊网络中共有两种账户,一种是外部拥有账户(externally owned accounts,EOA),由拥有者私钥控制。另一种是智能合约账户,由智能合约代码控制。
如果你想与一个外部拥有账户进行交互,你可以使用transfer()函数发送所需的通证。但是,如果你想使用transfer()函数将通证发送给智能合约帐户,那么你将遇到一个可能会造成几百万美元损失的问题。
transfer()函数的一个大问题是,一旦被执行,即使交易已成功完成,接收方也不会收到转账通知。
一位名叫“Dexaran”的开发人员(他后来提出了ERC-223标准)最早发现这一点,按照他的说法:
“通证的交易是智能合约内部变量的变化,即发送方的”余额“将减少,接收方的”余额“将增加。”
因此,如果接收方是智能合约,则发送方必须通过“approve()”和“transferFrom()”两个函数的组合使用机制来转移通证,而如果接收方是外部拥有账户,则发送方必须通过“transfer()”函数转移通证。
如果用户由于失误选择了错误的函数,那么通证将卡在智能合约内(智能合约将无法识别交易),而且并没有可行的方法来提取被卡住的通证。
不知道ERC-20标准的开发人员是否认为用户在开发通证时永远不会犯这样的错误?“
那么,这对于“approval()”和“transferFrom()”两个函数的组合使用来说是一个很好的例子吗?
不,这种组合使用也存在问题。这是一种不安全的操作,大大增加了受到双重支付攻击的可能性。
缺陷2:准入门槛太低
另一个很广泛的批评是,ERC-20标准让人们可以轻而易举地创建自己的通证。结果就是,加密货币市场上充斥着大量不必要的,甚至更糟的是,骗钱的ICO和通证。
虽然ERC-20通证确实对加密生态系统的发展至关重要,但事实仍然是ERC-20标准可能已经过时了。
人们已经在尝试更新的标准,如ERC-223,ERC-777等等。但是,截至目前,ERC-20标准仍是通证的首选标准,Dexaran指出了其中的主要原因:
变化总是缓慢的,看起来我们肯定需要再等一段时间才能告别ERC-20标准转向其他标准。但是,我们不能错误地将ERC-20标准视为“不好的”。
还是那句话,金无足赤,人无完人。ERC-20标准的存在对加密货币世界产生了深远的影响,所以它当然应该得到应有的尊重。
原文链接: https://blockgeeks.com/guides/erc20-tokens-origin-story/