PUSH0 操作码:Solidity 最新 0.8.20 版本中的一项重大更新

Solidity 0.8.20 版本发布,引入了新的操作码 PUSH0PUSH0 的作用是将常量 0 推送到堆栈上,可以减少合约字节码大小,降低合约部署的 Gas 成本。在以太坊主网使用该操作码时,需要注意其他链可能不支持 PUSH0 操作码,需要选择正确的 EVM 版本。

Solidity 发布了最新版本 Solidity 0.8.20。

而且,和往常一样,随之而来的是相当多的新变化、改进、错误修复等等。

但是,这个版本中有一个强制性的更新,作为智能合约开发者,你必须了解。

那就是 - 包含了一个名为 PUSH0 的新操作码。

Solidity 团队在关于 PUSH0 的官方公告博客中给出的一个快速重要提示

新的编译器将默认目标 EVM 版本切换到上海,这意味着生成的字节码将包含 PUSH0 操作码。

首先,PUSH0 到底是什么?

PUSH0 操作码实际上非常简单。

它是一个只有一项特定任务的指令,即将常量值 ZERO 推送到堆栈上就是这样,相信我。

虽然 PUSH0 最近才被包含在 solidity 版本 加粗0.8.20加粗 中,但自 2021 年 EIP-3855 诞生以来,它的重要性就显而易见了。

在接下来的章节中,我们将更深入地研究这个加粗看似简单加粗的操作码的重要性,并探讨它的关键含义。

到目前为止我们有什么...

如果你快速浏览一下到目前为止我们拥有的与 PUSH 操作相关的操作码(指令 0x60 到 0x7f),你就会意识到我们有从 PUSH1 到 PUSH32 的操作码。

从技术上讲,这意味着我们可以根据需要使用相应的操作码将从 1 字节到 32 字节的任何项目 PUSH 到堆栈上。

PUSH1  = 0x60, // 将 1 字节的项目放在堆栈上。
PUSH2  = 0x61, // 将 2 字节的项目放在堆栈上。
PUSH3  = 0x62, // 将 3 字节的项目放在堆栈上。
PUSH4  = 0x63, // 将 4 字节的项目放在堆栈上。
PUSH5  = 0x64, // 将 5 字节的项目放在堆栈上。
PUSH6  = 0x65, // 将 6 字节的项目放在堆栈上。
PUSH7  = 0x66, // 将 7 字节的项目放在堆栈上。
PUSH8  = 0x67, // 将 8 字节的项目放在堆栈上。
PUSH9  = 0x68, // 将 9 字节的项目放在堆栈上。
PUSH10 = 0x69, // 将 10 字节的项目放在堆栈上。
....
PUSH31 = 0x7e, // 将 31 字节的项目放在堆栈上。
PUSH32 = 0x7f, // 将 32 字节的项目放在堆栈上。

但是,我们没有足够的方法将 ZERO 推送到堆栈上。

因此,为了将 ZERO 推送到堆栈上,我们有变通方法,例如:

  • 使用 “PUSH1 00”:使用 PUSH1 操作码将零推送到堆栈上,
  • 使用多个 DUP 指令来复制零并将它们放在堆栈上,等等。

虽然上面提到的变通方法完成了这项工作,但它们还不够充分。

例如,使用 "加粗PUSH1 00加粗" 被编码为两个字节,并且从技术上讲,比在堆栈上放置零消耗更多的 gas。

并且使用多个 DUP 指令可能会增加合约代码大小,并且不是一种优化的方法。

如前所述,这个新的操作码可能看起来很简单,但它确实解决了所有这些长期以来被忽略的问题。

EIP3855 文档的一部分内容是:

为了正确看待“浪费”,在现有帐户中,340,557,331 字节浪费在 PUSH1 00 指令上,这意味着花费了 68,111,466,200 gas 来部署它们。

在实践中,许多这些帐户与其他帐户共享相同的字节码,因此它们在客户端中的总存储大小较低,但是,无论如何都必须支付部署时间成本。

加粗仅仅为了将零放在堆栈上就浪费了如此惊人的 gas 量。加粗 🤯

进入 PUSH0 操作码

现在有了 PUSH0,我们将能够一次性解决所有这些问题。

PUSH0 操作码将允许我们直接将常量 0 值推送到堆栈上,而无需使用多个 DUP 指令或其他操作码的组合。

有了新的 PUSH0 操作码,我们现在有了:

  • 加粗将零推送到堆栈上的充分机制,加粗
  • 加粗减少合约字节码大小,因为我们可以用 PUSH0 替换相当多的操作码,加粗
  • 加粗最大限度地减少使用 DUP 指令来复制堆栈上的零,等等加粗

验证时间

这是 Web3 的人,所以 👇

不要信任,去验证。

让我们尝试用一个例子来验证上述所有关于 PUSH0 操作码的细节,看看它是否真的能产生奇迹。🪄

我们将以这个小合约为例,

contract PushZero_Test{
    uint256 public num;

    function set(uint256 _n) public{
        num = _n;
    }
}

然后,让我们编译和部署这个合约:

  • 首先,使用旧版本,如加粗0.8.19 或 0.8.16 等。加粗
  • 然后使用最新版本,加粗0.8.20。加粗

结果呢?🤔

  1. 合约代码大小

➡️ 使用旧版本的合约字节码大小 = ~678 个字符

➡️ 使用 0.8.20 版本的合约字节码大小 = ~646 个字符

  1. 部署 Gas 成本 ⛽️

➡️ 使用旧版本的合约部署成本 = ~61511 gas

➡️ 使用 0.8.20 版本的合约部署成本 = ~58909 gas

作为这个简短实验的结果,我们可以清楚地验证,通过包含 PUSH0 操作码,我们现在有了:

  • 减少了合约代码大小,并且
  • 减少了合约部署 gas 成本

嗯,这个操作码的魔力很好。🧐

加粗不要跳过实验。加粗

加粗也尝试自己验证一下加粗

☢️ Solidity 开发者重要警告

虽然 PUSH0 操作码现在包含在最新的 solidity 编译器中,但在 ETH 主网以外的任何其他链上使用它时,你需要小心。

仍然有一些其他的链,如 L2,它们不识别 PUSH0 操作码。因此,如果你尝试使用最新的编译器在任何不支持此操作码的链上部署合约,你的合约部署将失败。

你可能会收到这样的错误 👇

因此,在这种情况下,你必须确保已选择正确的 EVM 版本。在此处了解有关选择正确 EVM 目标版本的更多信息:HERE

好的,解密者们,希望这有帮助。

再见。👋🏻

用于 Solidity ABI 编码的深度心智模型:第 1 部分\ 用于 Solidity ABI 编码的深度心智模型:第 1 部分![为什么要学习 Solidity 的难题 [ABI 编码系列:第 0 部分]] (https://www.decipherclub.com/content/images/size/w600/2025/06/ChatGPT-Image-Jun-8--2025--07_07_45-PM.png)\ 为什么要学习 Solidity 的难题 [ ABI 编码系列:第 0 部分 ] \ \ Solidity 很简单。\ \ 它是一种简单而美丽的语言。\ \ 随着优秀的教育资源、课程、开发工具和 LLM 的兴起,学习和编写 Solidity 从未如此简单。\ \ 但这是一个残酷的现实——如果每个人都很容易上手,那么我在 SUI-Move 中的第一个迷你项目 - 第 2 部分\ 我在 SUI-Move 中的第一个迷你项目 - 第 2 部分我对 Move 智能合约的初次体验 - 第 1 部分\ 我对 Move 智能合约的初次体验 - 第 1 部分 \ \ 我最近尝试了一种新的智能合约语言 MOVE。\ \ 该语言的灵感来自 Rust,因此对于 Solidity 开发人员来说并不直观。\ \ 但是,使用它构建超级有趣。\ \ 在本系列文章中,我旨在介绍 Move 语言及其功能。

  • 原文链接: decipherclub.com/push0-o...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
decipherclub
decipherclub
江湖只有他的大名,没有他的介绍。