原文: https://monadxyz.substack.com/p/the-security-benefits-of-monad-7884c4c9b398
在过去的三年里,由于链上漏洞,超过四十亿美元的资产被盗;这些损失成为了去中心化应用(DApp)被主流采用的最大障碍之一。主要原因是在以太坊上实现智能合约的安全措施成本很高。在最大限度降低用户 gas 费用的同时,以太坊开发者常常因为要放弃一些额外的安全检查而很难取舍。
一些常见的 gas 优化手段:
- 限制防御性断言的使用,只包含对应用功能至关重要的代码。防御性断言对于保持不变量至关重要,尤其是在代码升级时。
- 使用一些反直觉的技巧来节省 gas,尽管这些技巧牺牲了可读性。例如,将任何函数设为 payable,使用映射代替数组,避免使用库等,都会让代码更难理解,并增加升级时出错的概率。
- 使用能减少链上交互的快捷方式,而更具交互性的设计可能提供更好的安全性。例如,最初的 ERC-20 设计是用户批准应用一个特定数量的代币,但实际上,大多数前端请求的是无限批准,部分原因是为了避免用户重复支付 gas 费用。
大约 250 亿美元的价值以 ERC-20 代币和 NFT 的形式存在于以太坊上,这使的智能合约的安全性风险极高。而 Monad 大幅降低了 gas 成本,使得大部分当前的 gas 优化手段变得不再必要,从而让开发者能够专注于构建应用的最佳版本。
在以太坊中,每个操作码(opcode)都会消耗一定数量的计算单位,即 Gas。计算越多,消耗的 Gas 就越多。当用户调用智能合约中的函数时,他们需要为该函数中操作码所消耗的 Gas 付费。
由于以太坊上的计算资源极为有限,每个操作的成本都非常高。因此,在不影响功能的情况下减少操作次数,对于降低用户成本至关重要。这些优化可以采取多种形式,但每种形式都伴随着一些潜在的风险。
经验丰富的开发者会在智能合约中加入防御性断言,以防止意外情况的发生。顾名思义,防御性断言是一种将预期行为编码为合约逻辑的方式,确保某些条件始终为真。例如,如果某个内部变量预期始终是非负的,开发者可以写出类似 require(var >= 0, 'encountered negative var') 的代码,确保如果该条件不成立,交易会回滚。这种方式有效防御了利用意外情况发起的攻击。
在 DeFi 领域,很多致命漏洞皆由重入攻击(Reentrancy Attack)引发。在重入攻击中,智能合约进入一个意外的状态,通常是在被巧妙构造的合约递归调用后,利用某个逻辑错误进行攻击。重入攻击的核心是合约进入了错误的状态,但没有意识到这一点。通过防御性断言,可以“意识到”这种错误状态,并在错误发生时及时回滚。
防御性断言的作用不仅限于防止重入攻击,还能避免一些常见的低级错误。例如,一个常见的错误是将代币发送到包裹以太坊(WETH)合约中,导致代币永久卡住。虽然经常有关于增加额外检查来阻止这一错误的讨论,但这些检查会增加额外的 Gas 费用,这对没有出现错误的用户来说是个不小的负担。
总体而言,防御性断言是一种有效的安全措施,能够帮助开发者规避常见的漏洞和错误,确保合约的逻辑始终按照预期执行。尽管它会增加 Gas 成本,但在确保合约安全性和防止重大漏洞的情况下,这样的开销是值得的。
仅在 WETH 合约上,由于缺乏这些防护措施,已经损失了超过一百万美元的资产。
有一些巧妙的技巧可以节省 Gas,尽管这些做法可能会牺牲代码的可读性。以下是其中的一些例子:
将函数标记为 “payable”(即使该函数并不打算接收 Ether)减少 Gas 消耗:
使用汇编(Assembly):
避免使用外部库:
更多巧妙的优化技巧:
- https://github.com/0xKitsune/EVM-Gas-Optimizations
- https://github.com/ControlCplusControlV/Yul-Optimization-Tips
可读性提高了理解,而理解又能提升安全性。团队成员和审计人员需要能够轻松理解代码,这样才能识别漏洞,并在进行后续修改时避免引入错误。
在某些情况下,开发者为了 Gas 效率,明确选择了不安全的做法。
ERC-20 授权是一个很好的例子。原始的 ERC-20 规范要求用户为应用程序授权一个特定数量的代币,以便应用程序只能花费预期的数量。但实际上,大多数前端会请求无限量授权,部分原因是为了避免用户重复支付 Gas。如果应用程序的部署者被攻破,攻击者可以直接从给予这些授权的用户钱包中提取资金。
另一个例子是,Solidity 提供了 SafeMath,它用于检查溢出和下溢。一个流行的“技巧”是禁用这些安全检查,以节省一些 Gas:
安全实践非常有必要,但在当前以太坊的状态下,绕过这些实践的确会节省 Gas。
由于计算成本较高,应用开发者目前必须在安全性和成本之间做出权衡。对于既安全又便宜的应用,最简单的路径是大幅降低计算成本。让开发者在编写代码时不必精打细算是一个简单却常被忽视的需求,而在 Monad 中这一点并没有被忽视。
Monad 正在为开发者创造一个无需妥协的环境。迎接下一个十亿用户的道路将需要既安全又易用的应用;而在 Monad 上构建这些应用,便是最佳选择。