怎样防止ERC20智能合约漏洞

in #cn8 years ago (edited)

最近有有些朋友问到ERC20漏洞的问题,我看了一下网上所有的资料都是关于漏洞的说明,没有给出解决方案。正好借助这个事情给大家普及一下智能合约开发中的一些需要注意的问题。

首先需要给大家说明的是这个所谓的漏洞是BeautyChain项目的ERC20-TOKEN合约的bug,不是以太坊的问题。

实事求是来讲对于程序员来说bug一件非常普遍的事情,只不过发币、转币这个事情直接与钱打交道,因此在所有涉及token业务的时候一定要做好单元测试、功能测试及系统测试,以保证系统的健壮性。

如果你是一名程序员,一定知道数据溢出这个问题。

我们以uint8举例,代表只有8位数字,二进制的方式存储的最大数是11111111,对应我们日常生活的数是2^8 - 1 = 255。

下面的代码就会出现整型溢出。

uint8 number = 255;
number++;

在这种情况下number会直接归0,如果用二进制来表示就会变成00000000。有点类似时间23:59过后就是00:00。
相同的问题uint256也一样,uint256最大数是2^256-1,如果超过这个数值就会溢出,结果就是变量值归零。

在BEC Token中出现的问题就是黑客调用转账方法转了两笔超大数量(0x8000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000)的BEC Token导致数据溢出,钱被转走了,但是账户余额没有变。使用这个漏洞黑客可以非常方便的在两个账户之间进行转账,从而获取大量的BEC Token。

为了让大家彻底搞清楚这次漏洞的细节,避免以后同样的问题出现,下面我来详细分析一下BEC Token的代码。

BEC Token的合约地址是0xc5d105e63711398af9bbff092d4b6769c82f793d,详细代码大家可以访问etherscan.io。在BecToken合约代码的255到267行有一个方法叫batchTransfer,这个方式可能是项目早期用来给用户批量转账用的,但也有可能这段代码压根就没用。就是这个可能没用的方法在批量转账时出现了整型溢出,导致黑客将大量BEC Token转走。

以这次黑客行为为例,简单讲解一下这段代码:

这段代码定义了一个函数batchTransfer,传入两个参数,一个接收者数组,一个金额,返回值是布尔值,范围是public公开。代码基本逻辑是先判断数组的长度,然后将接收者数量与单个金额相乘。如果接收者在0和20之间,转账金额大于0,并且发送地址余额大于要转账的总金额,这时减去发送地址相应数量余额。最后根据接收者大小进行循环,给每个地址转入对应的金额。

以上代码中出现整型溢出的就是257行这段代码:
uint256 amount = uint256(cnt) * _value;
黑客在调用程序时传入一个非常大的金额超出了uint256的范围(2^256-1),导致uint256 amount 这个变量溢出直接归零,在后面的逻辑代码中由于没有对amount进行判断,使得黑客非常在转出金额为0的情况下为目标接收地址转入了大量的BEC代币。

以上就是所谓的batchOverflow漏洞,其实和以太坊没有太大关系,是程序员在编写智能合约时没有对代码进行严格测试才导致出现了这么一个轰动全球的事件。

既然这个问题已经出现了,对于后面从事智能合约开发的朋友希望大家能够从这里吸取经验,防止以后发生同样的问题,这也算BEC漏洞对行业的贡献吧。

其实程序本身的问题很容易解决,麻烦的是已经发出的币怎样处理。

在solidity语言中提供了SafeMath函数库,在BEC Token合约代码一开始就引用了。

在进行代币相关操作时,我们只需要使用SafeMath函数提供的add、sub、mul、div函数就可以保证不会出现整型溢出。

可惜的是在batchTransfer方法中大量使用了SafeMath进行代币的操作,唯独在一开始计算转账总金额的时候没有使用。

那么很显然,我们只需要对这段代码进行简单修改就可以修复漏洞,修改后的程序如下:

但由于以太坊代码即法律的特性无法进行代码的修改,因此只能重新发布一个新的合约,将这个合约销毁。

以上就是我对BEC 合约代码漏洞的分析和解决方法,希望能够对大家有所帮助。
另外,我们团队制作的《智能合约开发系列课程》二期正在报名中,如果你想从事智能合约开发请与我联系。
我的微信253841918。

Sort:  

出问题的原因和解决方法我都看懂了,那BEC算是毁了?

基本算是吧,我看交易所一直没有交易量,估计是挂了。

寫的好~都看懂了

Coin Marketplace

STEEM 0.05
TRX 0.33
JST 0.072
BTC 63861.94
ETH 1780.62
USDT 1.00
SBD 0.47