0%

ETH十二---美链

美链

​ 上篇文章The DAO的例子是2016年发生的,美链这个例子是2018年四月才发生的,出问题的智能合约叫做美链—Beauty Chain。

上图中的ERC是以太坊发行代币的一个标准,ERC:Ethereum Request for comments。

​ 以太坊上面发行着各种各样的代币,以太币的价格上涨的一个原因是因为ICO(Initial Coin offering),这些发行的代币没有自己的区块链,而是以智能合约的形式运行在以太坊的EVM平台上,发行这个代币的智能合约对应的是以太坊状态中的一个结点,这个结点有它自己的状态余额,相当于这个智能合约一共有多少个以太币,相当于这个发行代币的智能合约总的资产有多少个以太币,然后在这个合约里,每个账户上有多少个代币,这个是作为存储树中的变量存储在智能合约的账户里的,代币的发行、转账、销毁,都是通过调用智能合约中的函数来实现的,这个也是和以太坊中的以太币不太一样的地方,他不想以太坊那样,通过挖矿来维护一个底层的基础链。以太坊上每个账户有多少个以太币,这个是直接保存在状态数上的变量,然后转账的时候以太坊上两个账户之间转账,只通过发布一个交易到区块链上,这个交易会打包到发布的区块里,而代币要转账的话,是智能合约的两个账户之间通过调用智能合约的函数就可以完成。

​ 每个代币可以指定自己的发行规则,比如说某一个代币是可以1个以太币兑换100个代币,比如说从你的外部账户给智能合约发进去一个以太币,那么这个智能合约就可以给你在这个合约里的代币账户上发送100个代币。每个账户上有多少个代币的这些信息都是维护在存储树中(发行这个代币的智能合约的存储树里面)。

​ 以太坊平台的出现为各种代币的发行提供了很大的方便,包括EOS(使用DOPS协议形成的共识),这个在上线前,也是作为以太坊上的一个代币的形式发行的,这个EOS本身的目标是做成一个基础链,和以太坊要竞争的。

​ batchTransfer的实现:

上图的函数有两个参数,第一个参数是接受代币的接收者的数组的地址,在函数体里,要检查一下接受者的个数要小于等于20个,第二个参数中的value是转账的金额(给每个人转多少),函数体里先算一下总的金额,每人发送value个代币,一共要amount个代币,然后检查一下发起调用的这个账户确实是有这么多代币,然后把发起调用的账户上的代币数目减去amount,之后用一个循环给每一个接收者接受value的代币。会有什么问题?这和上一个例子不是同一个问题,否则就没必要再举例了……

问题出在计算总数amount上,如果value的值非常大,就是给每个receiver发送的value都很大的话,这个乘法可能溢出,发生溢出之后,amount可能是一个很小的值,所以从调用的账户上去减的时候,减的是很小的一部分代币,但是底下给每个receiver增加的代币数目仍然是value,这样做的结果相当于系统当中凭空多发行了很多的代币。

上图中红框中都是接受了很大数量的代币。

这个事情应该给我们一个什么样的反思?在写代码的时候一定要检查数值溢出的问题。

首先用ab得到c,然后用c/a看能不能得到b,如果发生溢出的话,assert会抛出异常。ab会不会精度丢失,c再除a得到的c是否还是ab的结果?但是这个问题在solidity里面是不存在的,因为ab都是整数。