共计 1239 个字符,预计需要花费 4 分钟才能阅读完成。
selfdestruct 函数(自毁函数)由以太坊智能合约提供,用于销毁区块链上的合约零碎。当合约执行自毁操作时,合约账户上残余的以太币会发送给指定的指标,而后其存储和代码从状态中被移除。
selfdestruct 函数尽管能在紧急情况下帮忙开发人员删除智能合约并将合约内的余额转移到指定的地址,但这一个性也被不法分子利用,使它成为了攻打伎俩。让咱们来看个经典游戏“侥幸 7”的案例:
合约代码
破绽剖析
在“侥幸 7”游戏中,玩家每次向 EtherGame 合约中打入一个 ETH,第七个胜利打入 ETH 的玩家将成为 winner。winner 能够提取合约中的 7 个 ETH。玩家每次玩游戏时都会调用 EtherGame.deposit 函数向合约中先打入一个 ETH,随后函数会查看合约中的余额 (balance) 是否小于等于 7,只有合约中的余额小于等于 7 时能力持续否则将回滚。合约中的余额 (balance) 是通过 address(this).balance 取到的,这就意味着咱们只有有方法在产生 winner 之前扭转 EtherGame 合约中的余额让他等于 7 就会使该合约瘫痪。这样咱们的攻打方向就明确了,只有咱们强制给 EtherGame 合约打入一笔 ETH 让该合约中的余额大于 7 这样前面的玩家将无奈通过 EtherGame.deposit 的查看,从而使 EtherGame 合约瘫痪,永远无奈产生 winner。然而 EtherGame.deposit 函数中存在验证:require(msg.value == 1 ether, “You can only send 1 Ether”),这里要求咱们每次只能打一个 ETH 进去,所以通过失常门路是不可能一次向 EtherGame 打入大于 1 枚的 ETH 的,然而咱们又须要打入大于 1 枚的 ETH 到 EtherGame 合约中,所以 selfdestruct 函数就退场了。
攻打合约
攻击者调用攻打函数 attack()销毁合约并将合约中的余额强制转账到“侥幸 7”的游戏合约地址,制作出游戏合约查问余额 address(this).balance 大于 7 的状况,导致函数回退,无奈失常进行游戏的状况,使得游戏合约瘫痪。修复倡议咱们来剖析一下攻击者的思路:利用 selfdestruct 函数强制转账给游戏地址,导致 unit balance = address(this).balance 查问出的 balance 的值大于 7,诱发 require(balance <= targetAmount, “Game is over”); 无奈通过使得游戏合约瘫痪。咱们不难发现攻击者是通过影响 balance 从而达到目标的,那么咱们就让 balance 不受这个影响,在最后先定义 balance,再让 balance 的值只受通过游戏规则内的失常路径的影响,这样就不会呈现 balance 值异样的状况了。
修复的代码:
如果想理解更多的智能合约和区块链常识,欢送到区块链交换社区 CHAINPIP 社区,一起交流学习~
社区地址:https://www.chainpip.com/