以太坊智能合约示例与漏洞分析——竞拍合约

一、拍卖合约

智能合约定义成员变量、event等,构造函数初始化受益人、拍卖结束时间,如下所示:
在这里插入图片描述
出价的函数如下,标注payable说明函数可以接收转账,require(now <= auctionEnd)检查拍卖是否结束,如果已经结束就抛出异常,然后检查出价是否大于最高出价,然后将出价人记录到bidders数组(因为bids哈希表不支持遍历),然后记录新的最高出价人,记录日志,如下所示:
在这里插入图片描述
结束拍卖的函数如下,首先检查拍卖是否结束,拍卖没有结束就调用该函数就会抛出异常,然后检查是否已经被调过,重复调用会抛出异常,然后将最高出价转给出价人,将钱退回给未中标的人,然后标注函数执行完成,记录日志,如下所示:
在这里插入图片描述

二、收款地址未定义fallback函数的问题

如果一个黑客通过外部账户发起交易调用自己的合约的函数,来发起竞拍,但是该合约账户未定义fallback函数,如下所示:
在这里插入图片描述
竞拍合约退款时,用的是transfer方式,没有调用任何函数,这时会调用fallback函数,而该合约没有定义,所以竞拍合约的退款会抛出异常,引起连锁式回滚,中间执行过程更改的数据结构也会全部还原,所以整个auction函数执行失败,所有人都收不到转账。

code is law
智能合约的规则由代码逻辑决定,由于区块链的不可篡改,发布到区块链上的所有合约都将无法修改,智能合约如果设计不好,有可能会造成以太币锁在里面,永远无法取出来。
所以智能合约必须经过严格的测试,在testnet上用假的以太币测试,确认完全没有问题才能发布。

fallback问题的解决方案

设计由投标者自己取回出价的方式,首先判断拍卖是否截止,检查取回的地址是否为最高出价人,然后判断余额是否大于0,然后将账户余额转给调用合约的人,然后在合约中给对应出价人清0,如下所示
在这里插入图片描述
下面是将最高出价转给受益人:
在这里插入图片描述

三、重入攻击(Re-entrancy Attack)的问题

合约账户收到ETH时,通过addr.send()、addr.transfer()、addr.call.value()()三种方式都会触发addr里的fallback函数。
fallback()函数由用户自己编写,如下所示:
在这里插入图片描述
内部又调用一次withdraw函数,造成退款的递归调用,不停的从竞拍合约中取钱,直到余额不足、汽油费不足以及栈溢出。

重入攻击的解决方案

改为先将收款人清0,再转账,再次调用将没有金额用于转账;另外还可将转账方式改为send,汽油费只有2300,只足够一次转账,如下所示:
在这里插入图片描述

发布了21 篇原创文章 · 获赞 2 · 访问量 4274

猜你喜欢

转载自blog.csdn.net/ice_fire_x/article/details/104278139
今日推荐