25. ETH 美链

很多代币在以太坊做ICO,Initial coin offering. 致使以太币价格大涨。

这些发行的代币没有自己的区块链,而是以智能合约的形式运行在以太坊的EVM平台上,发行代币的智能合约对应的是以太坊状态树中的一个节点,这个节点有他自己的账户余额,就相当于这个智能合约一共有多少个以太币,就是这个发行代币的智能合约他的总资产是多少个以太币,然后在合约里每个账户有多少代币是作为存储树中的变量,存储在智能合约的账户里,代币的发行,转账,销毁都是通过调用智能合约中的函数来实现的,每个代币都可以制定自己的转换规则,比如1个以太币=100个代币,比如外部账户给这个智能合约转一个以太币,智能合约就会给你在合约里的代币账户发送100个代币,每个账户的余额都是维护在发行代币的智能合约的存储树里面。

ERC: Ethereum request for comments.

美链的代币叫BEC,比如我有很多BEC,给十个不同的账户发送代币,调用这个batchTransfer 函数,每个人发送100个代币,那么这个batchTransfer函数先从我的账户上扣掉1000个代币,然后给十个账户分别增加100个代币。

batchTransfer函数的实现 

 batchTransfer函数有两个参数,第一个参数是数组,接收(代币)者的地址,函数中规定接受者的数目最多是20个,第二个参数value是转账的金额,先算一下总金额amount,recevier的数目和每人接收的代币计算;然后检查一下发起调用的账户msg.sender确实是有这么多代币的。之后把发起账户的代币数目减去amount,下面一个循环是给每一个接收者接收value这么多的代币。

这次的问题出在红框中的乘法如歌value值特别大的时候,乘法有可能溢出,发生溢出之后算出的amount可能是一个很小的值,所以后面从调用者的账户减去的时候是一部分很小的代币,但是底下仍然是按照value给每个receiver增加这么多代币。这样做造成了系统中凭空多发行了很多代币。

攻击细节

一堆数字是函数调用的参数,函数有两个参数,分别对应那串数字的前两行,第一个参数是地址,第一行给出的实际上是第一个参数出现的具体位置,这里是16进制的,40也就是64,也就是说第一个参数出现在第64个字节的位置,每一行是32个字节,所以实际上是从第2号开始出现的。第二行是这个value的值,这是个很大的数,前面是8,后面都是0,第三行是这个数组的具体内容,数组的长度,是2,接下来两行是两个接收的地址。

参数的特征:第二行amount是8,再乘以2,算出来的amount恰好溢出为0,add(value)的时候还是加原来特别大的那一串数目。

 

红框中是接收地址接收的代币,每个地址都接收到了很大一部分代币, 

被攻击之后暂停提币的功能,防止黑客携款逃走。两天之后回滚交易,事件影响没有The DAO影响深远。

反思

在进行数学运算的时候一定要考虑溢出的可能性。solidity有一个safeMath库,里面提供的操作运算都会自动检测有没有出现溢出。

C语言里,两个数相乘会有一定的精度损失,再除以一个数,不一定会得到和另外一个数一模一样的数。但是在solidity里面是不存在的,因为都是整数,256位的整数。

 

Logo

一站式 AI 云服务平台

更多推荐