本文介绍了Solidity 0.8.31版本的主要更新内容,包括默认EVM目标版本升级为Fusaka、支持CLZ操作码、存储布局支持常量、发布流程变更(ARM binaries, pre-releases)、废弃send()和transfer()等函数、ABI Coder v1将被移除等。

如果你使用Solidity已经有一段时间了,或者你只是刚开始接触它,你就会知道大多数版本升级都会带来底层的改进,以及一些为了准备而做的突破性更改。2025年12月发布的Solidity 0.8.31就是其中一个版本,它表面上看起来并不庞大,但份量很重,尤其是Solidity 0.9.0即将发布。
此版本收紧了底层行为,为即将到来的移除做准备,并将Solidity与Ethereum最新的EVM升级Fusaka对齐。如果你只想编写智能合约,而不必阅读编译器文档,请不要担心,我将介绍什么是新的,什么是变化的,以及在实际项目中真正重要的是什么。
当你编译合约时,Solidity的目标是Ethereum虚拟机的特定版本。每个EVM升级都会添加新的行为。一些更改对开发人员是可见的,例如新的操作码,而另一些更改则在幕后悄悄发生。
在0.8.31版本中,Fusaka成为默认的EVM版本。这在实践中意味着:
你无需做任何事情即可利用最新的EVM指令。
你的合约将使用与以太坊主网在Fusaka更新后遵循的相同逻辑运行。
如果你要部署到较旧的网络,则需要在配置中手动设置EVM版本。
为什么这很重要:大多数项目都希望与以太坊的最新标准保持同步。此更改使之成为默认设置。如果你是从头开始或部署到现代网络,它可以正常工作。
通过EIP-7939引入的新CLZ Count Leading Zeros操作码现在在Solidity中受支持。
如果你曾经需要在Solidity中进行位级计算,尤其是在库中,那么你就会知道手动计算前导零是多么痛苦。人们编写了笨拙的循环或依赖于效率低下的数学运算。现在它已内置到EVM中,并且可以通过内联汇编访问。
pragma solidity ^0.8.31;
contract BitTools {
function countLeadingZeros(uint256 input) external pure returns (uint256) {
assembly {
let result := clz(input)
mstore(0x00, result)
return(0x00, 0x20)
}
}
}
谁真正使用它?
如果你编写标准通证合约或简单的dApp,你可能不需要CLZ。但是,如果你正在构建加密库、优化gas使用量或处理自定义数据结构,它将非常有用。
如果你使用过可升级合约,尤其是通过代理模式,那么你就会知道存储布局有多么棘手。 Solidity 已经允许你手动定义存储槽位置。 现在它允许你在这些定义中使用常量。
这是一个生活质量的升级,但它比看起来更重要。
pragma solidity ^0.8.31;
uint constant OFFSET = 0x10 + 1;
contract DataStore layout at 0xAAAA + OFFSET {
uint256[3] values;
}
这使你可以重用偏移量,避免硬编码数字并防止布局错误。这是一种更安全、更清晰的管理存储的方式,尤其是在较大的代码库或框架中。
如果你正在构建没有升级逻辑的标准合约,则可以忽略此设置。但是对于库、SDK或代理系统,这是朝着正确方向迈出的一步。
如果你在ARM设备、树莓派、Apple M1或M2芯片、ARM云实例上进行构建,则以前编译Solidity有点令人头疼。现在,官方ARM二进制文件可用于Linux。
这意味着:
不再需要在ARM上使用从源代码构建的问题
在基于ARM的服务器上进行更可靠的Docker构建
更轻松地集成到CI管道中
以前,Solidity要么给你一个稳定版本,要么给你一个每晚构建版本。这不太好。每晚构建不稳定,而稳定版本来得太晚,无法及早测试重大更改。
现在你可以访问预发布版本,这些版本类似于beta版本:
提前访问即将推出的功能
完整版发布时减少惊喜
有机会在某些东西破坏你的工具时提供反馈
CLZ操作码实际上首先出现在预发布版本中。期望将来会有更多这样的情况。
如果你仍在使用apt get install solidity通过Ubuntu PPA,则现在该继续前进了。该安装方法将被停止。而是使用:官方二进制版本、从源代码构建、GitHub 版本
社区支持的工具,例如macOS上的Homebrew
这是一种更简洁、更一致的安装体验,尤其是在跨平台的情况下。
0.8.31版本还引入了针对0.9.0中将要删除的功能的弃用警告。如果你仍然使用这些功能,则现在应该开始远离它们。
send() 和 transfer() 即将被移除这些函数曾经是通过限制gas来防止重入的安全发送ETH的方式。但是gas成本已经改变,并且这些限制不再可靠。
改用这个:
(bool success ) = recipient.call{value: amount}("");
require(success, "Transfer failed");
提醒:这不能防止重入。使用ReentrancyGuard或遵循checks-effects-interactions模式。
此时不应再有人使用ABI coder v1。自0.8.0以来,ABI coder v2一直是默认设置,并且支持:
如果你仍然使用v1,则现在该迁移了。
virtual在Solidity 0.9.0中,你将无法再将修饰符标记为virtual。函数仍然可以被覆盖,但是修饰符将变为固定。此更改简化了继承并避免了奇怪的行为。
在将来的Solidity版本中,你将无法直接比较合约
if (contractA < contractB) { ... } // 无效
你需要将它们转换为地址
if (address(contractA) < address(contractB)) { ... } // 有效
这使事情更加明确,并有助于避免逻辑错误。
memory safe assembly 注释将被删除使用注释中的 memory safe assembly 的临时解决方法即将消失。你需要改用新的注释格式,这将提高项目之间的一致性。
Solidity 0.8.31增加了更多的底层功能,但同时也带来了真正的风险。内联汇编跳过了许多Solidity的安全检查,例如类型强制和溢出保护。
仅在以下情况下使用它:
否则,请坚持使用OpenZeppelin或Solady之类的库。
如果你手动定义存储布局,尤其是在可升级的合约中,请格外小心。存储槽数学运算中的一个错误可能会:
如果你必须手动定义布局:
如果你是Solidity的新手,请避免手动布局,除非你遵循经过验证的模式。
Solidity 0.9.0将删除多个功能。 0.8.31为你提供了一个良好的开端。 现在修复这些警告,以避免以后出现意外情况。
设置你的CI以将警告视为错误
不要使用不推荐使用的功能编写新代码
尽快开始清理旧代码
pragma solidity ^0.8.31;
module.exports = {
solidity: "0.8.31"
};
solc_version = "0.8.31"
升级后,运行你的测试,并注意任何弃用警告或行为上的更改。
如果符合以下条件,则应升级:
你正在启动一个新项目
你希望你的代码与最新的EVM更改保持一致
你正在为长期维护做准备
你想要为0.9.0准备好你的合约的未来
如果符合以下条件,则可以等待:
你正在使用旧版本进行审核
你的代码依赖于不推荐使用的功能,并且需要更多的时间来重构
即使你还没有准备好完全升级,也可以使用0.8.31测试你的合约,以了解即将发生的变化。
Solidity 0.8.31表面上看起来可能很安静,但它是今年最重要的版本之一。它为Solidity 0.9.0奠定了基础,清理了过时的模式,并为构建严肃项目的人们引入了小而有意义的功能。
无论你只是在学习Solidity还是在维护大型代码库,现在都是开始准备的正确时机。你将在下一个发行版发布时节省大量工作,并且你的合约将更加简洁、安全且易于长期维护。
Stackademic是一个为程序员、开发者、编码员和工程师提供的学习中心。我们的目标是普及全球的免费编码教育。
- 原文链接: blog.stackademic.com/sol...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!