本文详细介绍了在Solidity智能合约中常见的安全漏洞,包括重入攻击、计算错误、预言机失败/操控、弱访问控制和前置运行攻击。同时提供了一些解决方案和预防措施,帮助开发者提升智能合约的安全性。
本文最初发布于 BuildBear 教程。
本文将带你深入了解 Solidity 中一些最常见的漏洞,例如重入攻击、错误计算、Oracle 失败/操纵、弱访问控制和抢跑攻击。我们还将指导你解决方案和防范技巧,以确保你的合约安全。
那么,什么是重入攻击?想象这样一种情境:你拥有一家糖果店,正在给邻里的孩子们发糖果。一个孩子来找你要糖果,当你打开罐子准备给他们时,他们又要求另一些。在你忙着拿下一个糖果的时候,他们从打开的罐子里偷走了更多的糖果。这样做可不好,对吧?
在重入攻击中也发生类似的事情。恶意合约欺骗合约在第一次函数调用完全完成之前执行不应该执行的代码。这可能导致受害者的合约发放比程序员原本意图更多的资金。
我们的“受害者”合约允许用户存入和提取资金。但攻击者可以在 balance[msg.sender] = 0;
行被执行之前重复调用 withdraw()
,从而偷走更多的以太币。
为了防御这种攻击,我们引入了检查-效果-交互(CEI)模式。正如词序所示,首先我们检查条件,然后修改状态(效果),最后与外部合约交互。让我们来理解一下!
首先,我们检查余额,然后修改余额(效果),最后调用外部函数(msg.sender.send(amount)),这可能是重入攻击的潜在源头(交互)。
智能合约处理的是整数值,没有小数,并且它们会自动向下舍入。
让我给你一个 Solidity 的例子。
这里的 calculate
函数将 a
除以 b
,但如果 b
大于 a
,它会向下舍入到零。当 a
和 b
的除法结果为小数时,它也会向下舍入。
为了避免这种错误,我们将使用 SafeMath 库。
正如你所知,如果你在 Solidity 0.8.x 中编写代码,所有算术运算(如加、减、乘和除)都是安全的。不再需要保护!
尽管 Solidity 0.8.x 有安全措施,但整数除法仍然是一个棘手的问题。如果你将 5 除以 2,你可能预期结果是 2.5,但在 Solidity 中你将得到 2(它会忽略小数并向下舍入)。因此,如果你正在处理分数,你需要正确处理它们。
许多开发者使用的一种方法(这可能会为你节省很多麻烦)是在除法之前先进行乘法:
在这个版本中,乘以精度是在除法之前完成的,从而确保你保持珍贵的准确性。
Oracle 是为智能合约提供现实世界数据的重要外部实体。但它们也有自己的问题,其中最常见的是 Oracle 失败/操纵攻击。为了更好地理解这一点,让我们一步一步来分析。
解决 Oracle 攻击的关键在于去中心化数据来源。让我们分解出最佳实践:
在智能合约中,弱访问控制发生在对谁可以调用合约中的某些函数以及在何种条件下可以这样做的限制实施不当或完全缺失的情况下。就像把你家的门大敞开,却期望没有人未经允许就进入一样。
一个经典的例子是一个只允许拥有者提取资金的函数,但没有对函数调用者进行正确检查。
onlyOwner
修饰符,如果除了拥有者以外的任何人尝试干扰你的合约,这个修饰符将抛出异常。在这个例子中,合约的创建者被设定为拥有者。创建了 onlyOwner
修饰符来限制对敏感函数的访问,例如 mySensitiveFunction
。如果不是拥有者的人尝试调用该函数,修饰符函数将抛出异常,保护我们的合约安全。
想象一下,如果一个玩家看到了你在扑克游戏中即将玩的牌,然后重新安排他的牌组以赢得比赛。这就是抢跑者在区块链上所做的。抢跑者观察区块链上待处理的交易,然后以更高的 gas 价格提交其相同的交易,使得矿工更可能优先执行他们的交易,从而让他们在其他人损失的情况下获利。
🎉🎉 恭喜! 现在,你可以在合约中防止重入攻击、错误计算、Oracle 失败/操纵、弱访问控制和抢跑攻击。
请关注“Solidity 中最常见的漏洞:深入分析 第2部分”
关于 BuildBear :
BuildBear 是一个为团队提供的大规模 dApps 测试平台。它为用户提供自己的私有测试网络,以测试他们的智能合约和 dApps,这些合约可从任何 EVM 链进行分叉。它还提供一个水龙头、浏览器和 RPC 供测试使用。
BuildBear 旨在为团队构建一个大规模测试 dApps 的工具生态系统。
- 原文链接: medium.com/buildbear/mos...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!