ERC20智能合约的approve千万别这样写

最近智能合约安全事件频发,从BEC到SMT,从HXG到FXE等,最近这几个智能合约出的问题,大都是由于整数溢出漏洞导致的。大家对整数溢出是不是都杯弓蛇影了?我们是不是应该在所有的地方都加上安全检查,确保我们的代码没有问题呢?可是这样真的好吗?

我们先来看看这段代码:

这是ERC20接口中的approve函数的一个实现。乍一看,这个代码是不是很完美。仔细看,我们注意到,在函数最开始的地方有这样一行:

approve的时候对当前余额进行检测,要求授权的_amount小于或等于当前余额。这样写貌似还很有道理,但真的是这样吗?

首先我们看这样写有没有必要。

假设执行approve函数的时候,能够满足上面这个条件。如果在后续操作能够根据正常逻辑产生和这个条件相违背的状态,就可以认为这样的判断是没有任何意义的。

实际存在以下一些可能性,使得approve过的allowance大于用户对应余额的情况。

在approve之后,token的所有者自己通过transfer函数,把token转走,导致余额小于allowance。

approve给多个人,其中一个人进行transferFrom操作后,可能导致余额小于之前给其他人approve过的值。

既然无法在后续操作里保证,授权的allowance大于余额,我们就可以得出结论,在approve里加上这样的验证是没有意义的。有人可能会说,那加上这个除了多耗一点gas,那也没什么问题啊。真的没有什么问题吗?

最近我们在和去中心化交易所DDEX合作审计该平台上的ERC20 token的智能合约,发现一个比较严重的问题。目前的去中心化交易所,很多都用到了0x protocol或者类似的协议。在0x的智能合约里,进行转账的时候,通过Exchange合约的fillOrder函数完成转账。

其中fillOrder函数中由以下代码来实现转账:

去中心化的交易所需要准备一个中间账户,也就是上面代码中的msg.sender,来发起交易。具体转账过程如下:

把卖出订单的Token转给一个交易所的中间账户

由该中间账户给卖出账户转入WETH

买入账户向中间账户转入WETH

中间账户向买入账户转入Token

而这四步转账都是通过一个TokenTransferProxy合约完成。中间账户需要向该合约approve足够的allowance。而0x提供的合约并不提供approve过程,需要交易所提供的中间账户提前准备好这个approve工作。

然而如果这个中间账户并没有提前拥有交易的token,由于这个检测

无法提前完成approve,这样的问题给去中心化交易所带来了较大的困扰。

在各种去中心化交易所中,甚至中心化的交易所中类似的情况并不少见。因此我们强烈推荐大家在写ERC20智能合约时不要这么写,不要加上这样一个判断。

如果万一已经发布的ERC20 token合约已经这么写了,我们有什么办法吗?

当交易所遇到这种情况的时候,只能由项目方向交易所的中间账户打一笔足够大的token,才能保证能够approve成功,而且限制以后发生的交易额不能超过此数量的限制。

我们使用SECBIT的一个内部工具,对提供源码的22681个ERC20 Token智能合约进行了一次扫描,发现了21个智能合约存在此问题,其中有3个合约的交易量较大。涉及的Token包括:

IDH

GZR

ADE

SAINT

BULB

ZZZ

KTM

ETI-P

ZORRO01

ZORRO02

现在去中心化交易所将越来越多,为了不影响项目token未来的交易的流动性,我们建议各token仔细检查合约是否存在该问题,如果可能,尽早进行修正。

SECBIT(安比)实验室是谁?

安比(SECBIT)实验室专注于区块链与智能合约安全问题,全方位监控智能合约安全漏洞、提供专业合约安全审计服务,在智能合约安全技术上开展全方位深入研究,致力于参与共建共识、可信、有序的区块链经济体。

安比(SECBIT)实验室创始人郭宇,中国科学技术大学博士、耶鲁大学访问学者、曾任中科大副教授,后担任知名金融科技公司副总裁。专注于形式化证明与系统软件研究领域十余年,具有丰富的金融安全产品研发经验,是国内早期关注并研究比特币与区块链技术的科研人员之一。研究专长:区块链技术、形式化验证、程序语言理论、操作系统内核。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180615G1U93N00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券