Solidity v0.8.15 修复了两个重要的错误,改进了内联启发式算法,并为错误和事件添加了一个.selector 成员。
重要错误
第一个错误是一个优化器错误,如果此类操作的结果没有从同一个汇编块中读回,则会导致内联汇编中的内存写入操作被移除。此错误仅在使用默认的传统编译器管道(通过 IR 的新编译器管道不受影响)时才会触发,并且仅在从未访问过周围代码中定义的 Solidity 变量的汇编块中才会发生。此错误仅影响 0.8.13 和 0.8.14 版本,我们强烈建议这些版本的使用者更新其编译器。虽然我们认为这个问题不太可能在实际应用中出现并被发现,这大大降低了整体严重程度,但如果确实发生,可能会导致严重问题。查看关于内联汇编内存副作用的优化器错误 获取更多信息。
第二个错误可能导致对存储中 bytes 数组执行 .push() 操作时,如果该数组最初是从内存或 calldata 中复制的,则会追加未正确初始化为零的字节。同样,此错误仅在使用传统代码生成管道时才会触发。查看 将脏字节数组复制到存储时的错误 获取更多信息。
值得注意的新功能
Yul 优化器中的改进的内联启发式算法
编译器过去在决定是否内联函数方面非常保守。这是因为内联很容易增加堆栈压力,并导致令人头疼的“堆栈过深”错误。
现在,由于 IR 管道提供了将变量从堆栈移动到内存的机制,我们能够放松内联所需的条件。优化器现在将内联略微更大的函数,只要没有阻止使用该机制。如果你想从中受益,请确保你的内联汇编块是 内存安全的。
我们的基准测试表明,此更改显着减少了字节码大小(这会影响部署成本),而对运行时燃气消耗的影响较小。下表显示了我们在使用基于 IR 的管道运行我们 CI 中几个实际项目的测试套件时观察到的 0.8.14 和 0.8.15 之间的总体差异
项目 | 字节码大小 | 部署燃气 | 运行时燃气 |
---|---|---|---|
ENS | -4.85% ✅ | -0.29% ✅ | |
Euler | -2.43% ✅ | -1.68% ✅ | -2.08% ✅ |
Gnosis Safe | -3.87% ✅ | -4.31% ✅ | -0.02% ✅ |
Gnosis Protocol v2 | -3.95% ✅ | -2.55% ✅ | -0.07% ✅ |
Perpetual Pools | -4.55% ✅ | -2.64% ✅ | -1% ✅ |
Pool Together | -7.09% ✅ | -5.59% ✅ | -0.37% ✅ |
PRBMath | -3.56% ✅ | -3.49% ✅ | |
Trident | -9.84% ✅ | -7.98% ✅ | -6.26% ✅ |
Uniswap v3 | -4.32% ✅ | -4.53% ✅ | -1.24% ✅ |
Yield Liquidator | -7.13% ✅ | -6.08% ✅ | -0.5% ✅ |
OpenZeppelin | -7.83% ✅ | -6.01% ✅ | -0.28% ✅ |
错误和事件选择器
外部函数的选择器可以通过 .selector 成员访问。现在此成员也可以在 非匿名事件 和 自定义错误 上使用。
请注意,对于事件,选择器代表主题 0,它与错误和函数选择器不同,不会被截断为 4 个字节。
新的或改进的文档
悬空引用
我们最近收到了关于语言功能的正常使用可能会导致用户留下悬空引用,并导致存储中的数据被覆盖的安全漏洞报告。不幸的是,这是当前语言设计的一个自然结果,而不是可以简单修复的错误。Solidity 严格限制了对值类型的引用的使用,但将对数组的数组元素的引用存储在局部变量中,以及调整大小的能力一直意味着引用的目标可能会消失。新报告的案例发现,有一些不寻常的模式可能会在意外的情况下产生悬空引用。为了让这更加透明并提高认识,我们准备了一个新的文档部分,详细介绍了该主题:存储数组元素的悬空引用。感谢币安智能合约安全团队和红队的 Kuroi 报告了这个问题!
完整变更日志
重要的错误修复
- 代码生成:在复制 bytes 数组时,避免将脏字节写入存储。
- Yul 优化器:保留内联汇编块的所有内存副作用。
语言功能
- 为非匿名事件 E 添加 E.selector 以访问 32 字节选择器主题。
编译器功能
- LSP:添加对语义高亮的初步支持。
- 类型检查器:警告有关涉及对存储 bytes 执行多次 push 操作的赋值,这可能会使引用失效。
- Yul 优化器:通过 IR 代码生成和纯 Yul 编译改进内联启发式算法。
错误修复
- ABI 编码器:在对来自存储的空字符串进行编码时,不要为数据添加多余的空槽。
- 公共子表达式消除器:以最大 2000 个大小的块处理汇编项。这有助于避免在代码优化期间进行极其耗时的搜索。
- Yul 优化器:在 returndatacopy 可能执行超出范围的读取并无条件地作为超出燃气而恢复的情况下,不要删除 returndatacopy。以前,任何写入到从未读过的内存的 returndatacopy 都会被删除,而没有考虑超出范围的条件。
衷心感谢所有为此次版本发布做出贡献的贡献者!
从这里下载 Solidity 的新版本 这里。