Salus Insights:坎昆升级前,项目开发者必看的几项安全检查
长话短说:坎昆升级临近,本次升级主要包含六个 EIP 提出的执行层变更,EIP-1153、EIP-4788、EIP-4844、EIP-5656、EIP-6780 和 EIP-7516 。EIP-4844 是本次升级的主角,旨在提升以太坊的可扩展性,为L2降低交易成本、提升交易速度。坎昆升级已分别于 1 月 17 日、 1 月 30 日、 2 月 7 日在以太坊 Goerli、Sepolia 和 Holesky 测试网完成升级,并计划在 3 月 13 日在以太坊主网上激活。在升级前,Salus 整理了此次升级的重要安全注意事项,供开发者自行检查。
EIP 提案回顾
官方披露的安全考量
智能合约相关风险
扩展阅读
EIP-4844 介绍了一种新的事务格式,称为"分片 Blob 事务",旨在以简单、向前兼容的方式扩展以太坊的数据可用性。这项提案通过引入包含大量数据的"blob-carrying transactions",这些数据不能被 EVM 执行访问,但可以访问其承诺。这种格式与将来全分片使用的格式完全兼容,为滚动式扩容提供了临时但显著的缓解。
智能合约开发人员应在使用前了解瞬态存储变量的生命周期。由于临时存储会在交易结束时自动清除,因此智能合约开发人员可能会试图避免在调用过程中清除插槽以节省 Gas。然而,这可能会阻止在同一事务中与合约进行进一步的交互(例如,在重入锁的情况下)或导致其他错误,因此智能合约开发人员应小心,仅在临时存储槽被保留时保留非零值。旨在供同一事务中的未来调用使用。SSTORE 否则,这些操作码的行为与和完全相同 SLOAD,因此所有常见的安全注意事项都适用,特别是在重入风险方面。
智能合约开发人员也可能会尝试使用瞬态存储作为内存映射的替代方案。他们应该意识到,当调用返回或恢复时,临时存储不会像内存一样被丢弃,并且应该在这些用例中优先选择内存,以免在同一事务中的重入时产生意外的行为。内存上的瞬态存储成本必然很高,这应该已经阻止了这种使用模式。内存中映射的大多数用法可以通过按键排序的条目列表来更好地实现,并且智能合约中很少需要内存中映射(即作者知道生产中没有已知的用例)。
此 EIP 使每个信标块的带宽要求最多增加约 0.75 MB。这比当今区块的理论最大大小(30 M Gas / 每个 calldata 字节 16 Gas=1.875 M 字节)大 40% ,因此它不会大幅增加最坏情况下的带宽。合并后,区块时间是静态的,而不是不可预测的泊松分布,为大区块的传播提供了保证的时间段。
即使调用数据有限,此 EIP 的持续负载也比可降低调用数据成本的替代方案低得多,因为不需要将 Blob 存储与执行负载一样长的时间。这使得实现这些 blob 必须保留至少一段时间的策略成为可能。选择的具体值是 MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS 纪元,约为 18 天,与建议的(但尚未实施)执行有效负载历史的一年轮换时间相比,延迟要短得多。
-
被调用合约使用该操作码
-
发起调用合约使用该操作码
风险 1 :
相比于传统的 SSTORE 和 SLOAD ,新增的瞬态存储主要改变了数据的存储期限,tstore 存储的数据通过 tload 进行读取,在一笔交易执行结束后该数据将会被释放,而不是同 sstore 一样写入合约被永久性的记录。开发者在使用该操作码时应该认清该操作码的特性,以免错误的使用导致数据不能正确的写入到合约中而造成损失。另外,tstore 的数据属于私有变量,仅合约本身可以访问。如果想要外部使用该数据只能通过参数的形式进行传递或暂存到一个 public stroage 变量中。
风险 2 :
另一个潜在风险是,如果智能合约开发人员不正确管理瞬态存储变量的生命周期,可能导致数据在不应该的时间被清除或错误地保留。如果合约期望在事务的后续调用中使用存储在瞬态存储中的数据,但未能适当地管理这些数据的生命周期,可能会在不同调用之间错误地共享或丢失数据,从而导致逻辑错误或安全漏洞。考虑到类似于 Token 项目的 balance 或者 allowance 数据未能正确的存储将会导致合约逻辑的错误,造成损失。或在对 owner 地址进行设置时使用了该操作码将会导致特权地址不能正确的被记录从而丢失对合约重要参数的修改。
考虑一个智能合约,该合约使用瞬态存储来临时记录一个加密货币交易平台上的交易价格。该合约在每笔交易完成时更新价格,并允许用户在短时间内查询最新价格。然而,如果合约设计没有考虑到瞬态存储在交易结束时被自动清除的特性,那么在一笔交易结束后到下一笔交易开始之前的这段时间内,用户可能会得到一个错误或过时的价格。这不仅可能导致用户做出基于错误信息的决策,还可能被恶意利用,影响平台的信誉和用户的资产安全。
智能合约中的 SELFDESTRUCT 操作允许合约销毁,并将合约余额发送给指定的目标地址。在这种情况下,合约使用 SELFDESTRUCT 销毁以太币,并将销毁的以太币发送给了合约。但是该合约仅能是在同一笔交易中创建的合约(同一笔交易中由本合约或其他合约创建的合约)。否则将仅转账以太而不销毁合约(例如自毁且受益者为自毁合约,这将会不产生任何改变)。这将会影响一切依赖于 selfdestruct 进行提款或其他操作的合约。
一种类似于 1inch CHI Token 的 Gas Token 的工作原理:保持一个偏移量,始终在此偏移量处执行 CREATE 2 或 SELFDESTRUCT。在此更新之后,如果当前偏移量的合约尚未正确自毁,则之后的 CREATE 2 将不能成功的部署合约。
该提案实施并不能导致直接对合约进行攻击,但会损害原有已部署的依赖 selfdestruct 操作的合约的正常逻辑(仅依赖自毁进行资金转移的合约不受到影响,如果后续操作必须要求自毁的合约被删除,则受到影响),导致合约非预期工作,仅对合约以及用户而言,可能导致合约的罢工,损失资金等危害(例如原本利用 create 2 在原地址部署新合约,自毁原合约进行升级的合约,不再能够成功部署)。长远来看,修改某项操作码的功能可能会带来中心化的问题。
例如现有一个金库合约 vault 进行更新: