# EIP-3855 如何讓合約更精簡

By [Blockchain Builder](https://paragraph.com/@blockchain-builder) · 2023-03-20

---

（Cover designed by jannoon028 / Freepik）

> 作者：Irara @ imToken Labs 校稿：[Nic](https://medium.com/@twedusuck)、[Cyan](http://http//)、[ChangWu](http://http//) @ imToken Labs；FengYi @ imToken Wallet

本文將深入介紹 Ethereum Opcode 的最新成員：`PUSH0`

在過去，我們只能使用 `PUSH1 0x00`（= 0x6000）來達成將數值 0 存入 EVM 的 Stack 中，而上海升級中包含諸多 EIP 之一的 EIP-3855 提案則引入了 `PUSH0`（= 0x5F）這項新的 Opcode 來達成相同的效果。透過節省 1 Byte 的指令空間（0x6000 → 0x5F），減少了智能合約編譯後的 Bytecode 大小，進一步降低智能合約部署的成本。

而本文將會快速地帶到 EVM、Bytecode 與 Opcode 的基本概念，並一步一步地帶你瞭解 PUSH0 的核心意義和對現有合約的影響。

> 文章會從 EVM、Opcode 到 PUSH0 詳細說明，若您為區塊鏈開發人員，我們可用一句話函蓋整篇文章： EIP-3855 引入新 Opcode：PUSH0（0x5F）來取代 PUSH1 0x00（0x6000），因減少 1 Byte 指令空間，所以減少了部署智能合約的 200 Gas，所有合約加總一年大約可省 1,362.23 ETH。

1、EVM 與 Opcode 概念
-----------------

在介紹 EIP-3855 之前，我們先來簡單了解 Ethereum 中最重要的 EVM 概念！

### EVM（Ethereum Virtual Machine）

我們為了讓智能合約在獨立且安全的環境中執行，而從 Ethereum 節點中會切出一塊具有儲存、執行等功能的運算環境，我們將之稱之為 EVM 虛擬機

而這個 EVM 具備執行智能合約所需的堆疊、記憶體、紀錄 Gas 費用及儲存下一行指令位址等各種必要元件，以便完成開發人員要求的各種計算

![EVM 架構，原圖連結：https://ethereum.org/en/developers/docs/evm/](https://storage.googleapis.com/papyrus_images/8451163357c975de2624aefad6a74322e19497e8fecf8cf25af4d60496663751.png)

EVM 架構，原圖連結：https://ethereum.org/en/developers/docs/evm/

### Bytecode 與 Opcode

我們用 Solidity 等語言所撰寫的智能合約，要先編譯成一連串 EVM Opcode，這一連串 Opcode 稱為 Bytecode。我們接著來進行一段簡單的操作就會比較清楚！

> 有興趣的讀者可以透過 [EtherVM](https://ethervm.io/) 了解更多關於 Opocde 的介紹。

首先，我們先在 [Remix](https://remix.ethereum.org/) 上編譯下方這份簡易的加法智能合約，編譯完成後就可從 artifacts 資料夾中看到包含此智能合約 Bytecode 與 Opcode 的 Json 資訊檔

    // SPDX-License-Identifier: GPL-3.0
    
    pragma solidity >=0.8.2 <0.9.0;
    
    contract AddContract {
        function addFunction(uint256 x, uint256 y) public pure returns (uint256) {
            return x + y;
        }
    }
    

![Remix 智能合約線上編譯工具](https://storage.googleapis.com/papyrus_images/611db5e0e039fc7a1a50e2554ca34f55badc24115fd04c2e29bc37649ec4c299.png)

Remix 智能合約線上編譯工具

與此同時，這個智能合約也已部署到 Goerli 測試網中，我們可點選在 [Etherscan](https://goerli.etherscan.io/address/0xd4a2d43f33663a92fc0a34f9fe823c8f6dcda3c2#code) 上的【Switch To Opcodes View】鈕從 Bytecode 切換到 Opcode 觀看模式。這時，即可得知一連串 Opcode 稱為 Bytecode

![Etherscan 區塊鏈瀏覽器](https://storage.googleapis.com/papyrus_images/d28108336bff38670aff4ff427bc6157c9896568fcdbf1ab592ca5b2152fc542.png)

Etherscan 區塊鏈瀏覽器

這裡就只截取這份合約部份的 Opcode

![部份 Bytecode 與 Opcode 對照表](https://storage.googleapis.com/papyrus_images/a7bfe64ae55c5ab86faf5fe39392d8697f2df5d5abdf9606d5c50a4a9a6241e1.png)

部份 Bytecode 與 Opcode 對照表

2、EIP-3855 概念整理
---------------

現在我們有了 EVM、Bytecode、Opcode 的概念後，那 EIP-3855 到底要改進什麼問題呢？

前面的例子中，我們了解到若想要將一個零的值推到 Stack 中，這個動作會被編譯成「PUSH 0x00」（兩個 Byte，分別是 0x60 及 0x00，其中 0x00 代表零的值，所以 0x6000 整整佔了 2 個 Byte 的 Storage 空間！

> 1 Byte Bytecode 空間需要支付 200 Gas 的費用
> 
> 另外，執行 1 個 PUSH1 的操作需支付 3 Gas，而 PUSH0 也是，所以 PUSH0 主要是減少編譯後的程式碼大小，但實際上執行時的 Gas 消耗和 PUSH1 是一樣的

我們來看一下以下關於 `Push1 0x00` 指令在 2020 年的統計數據：

![截取自下方附錄 2](https://storage.googleapis.com/papyrus_images/d1908df06784d53bd69c0ca51917aa0f02e0cdb20ede984a43a69228acafdd71.png)

截取自下方附錄 2

`Push1 0x00` 指令佔了 2020 年全年度智能合約 Bytecode 的 4.57% 之多（同時也為 PUSH 系列指令之首），它被如此常用，以致於幾乎所有的智能合約中都可看到它的身影！

這時，如果我們新增一個 Opcode 來做和 `PUSH1 0x00` 完全一樣的事，是否就可以再減少 1 個 200 Gas 的空間消耗？

答案是可以的！EIP-3855 即將會在這一次的上海升級中在 Opcode 中引入一條 `PUSH0` 新指令，而這個新指令的編號是 0x5F！

> 會選擇 0x5F 做為 `PUSH0` 的原因，除了 0x5F 在上海升級前沒有被使用外（空的），而且它也剛好是在 `PUSH1`（0x60）指令的前一個編號！是一個連續且有意義的指令空間

![0x5F 及 0x60 的 Opcode 指令編號，圖片來源：https://ethervm.io/](https://storage.googleapis.com/papyrus_images/6d54cc85cc3ca8334fc8d7b6fdffdc9dc36392a44fb992837f679766af538546.png)

0x5F 及 0x60 的 Opcode 指令編號，圖片來源：https://ethervm.io/

3、EIP-3855 帶來的改變
----------------

將 0x6000 指令瘦身至 0x5F 有一個最重要的改變，就是部署合約時的 Gas 費用變便宜了！程式碼中每個使用到 `PUSH1 0x00` 的地方都可以因為這個改變而省下 200 Gas！

那我們一樣以 2020 全年度使用 340,557,331 次 0x6000 指令來計算，大約需耗費 340,557,331 x 200 Gas = 68,111,466,200 Gas。接著若以 1 Gas 需支付 20 GWei 來計算，也就是可以為整個網路省下整整約 1,362.23 ETH，而且各個 Ethereum 節點也可省下不少儲存空間

此外，對於開發人員來說，也可減少使用一些特殊優化手段來減少 `PUSH1 0x00` 的 200 Gas 開銷，例如使用 DUP 指令（將 Stack 中指定的值，如：0 值推到 Stack 中）等。使用 0x5F 代表著可減少開發人員進行各種優化成本與風險，也利於估算智能合約的 Gas 費用

4、文章重點整理與結論
-----------

### 重點整理

*   EIP-3855 將減少部署智能合約時的 Bytecode 大小
    
*   此外，EIP-3855 也可減少過去開發人員在進行各種優化上的成本與風險
    

### 結論

本文介紹了 Ethereum 的 EVM（Ethereum Virtual Machine）及 Opcode 的概念，並且深入探討了 EIP-3855 改進的重要意義與影響。一旦這次的上海升級完成，就可減少開發人員部署合約時所需的儲存空間費用，而 EIP-3855 提案和新的特性，也將吸引更多的開發者加入到以太坊的生態中。感謝您閱讀本文！

5、參考資料與附錄
---------

### 參考資料

*   中文
    
    *   以太坊虛擬機
        
        *   [https://ethereum.org/zh/developers/docs/evm/](https://ethereum.org/zh/developers/docs/evm/)
            
*   英文
    
    *   EIP-3855 提案
        
        *   [https://eips.ethereum.org/EIPS/eip-3855](https://eips.ethereum.org/EIPS/eip-3855)
            
    *   EIP-3855 英文討論區
        
        *   [https://ethereum-magicians.org/t/eip-3855-push0-instruction/7014](https://ethereum-magicians.org/t/eip-3855-push0-instruction/7014)
            
    *   EVM Codes 列表
        
        *   [https://www.evm.codes/](https://www.evm.codes/)
            
    *   Ethereum Virtual Machine Opcodes
        
        *   [https://ethervm.io/](https://ethervm.io/)
            
    *   PDF - ethereum-evm-illustrated
        
        *   [https://takenobu-hs.github.io/downloads/ethereum\_evm\_illustrated.pdf](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)
            

### 附錄 1：關於 EIP-3855 常見問題

#### EIP-3855 提案通過後是否可提升 TPS（每秒交易數）？

TPS 增長量不大，因為實際在主網上部署合約的交易並不多，假設在一個區塊內有 10 筆部署合約交易（已是相當多）的狀況，若每個合約部署只「一次性」省約 25 個 `PUSH0`（25 \* 200 \* 10 = 50,000 gas ），所以 TPS 可提升的有限。

#### 一般 Solidity 開發人員如何應用此 EIP-3855 提案？

一般 Solidity 開發人員要等到上海升級完成才能享受到程式碼大小變小的好處，EIP-3855 主要是讓 Solidity 編譯器（將 Solidity 程式碼編譯成 Bytecode，而此 Bytecode 可對應不同的 Opcode）將所有 `PUSH1 0x00` 改為 `PUSH0`，以節省空間、減少 gas 等好處。

### 附錄 2：2020 年「PUSH」系列指令數量統計表

此表格參考 [EIP-3855](https://ethereum-magicians.org/t/eip-3855-push0-instruction/7014) 中作者之一 [Hugo De la cruz](https://github.com/hugo-dc) 所統計的 [2020 全年度 Ethereum Opcode 數量](https://gist.github.com/hugo-dc/1ca4682d60098282d7e499bdd0b01fca)（區塊高度：8,567,259 ~ 8,582,058 及 12,205,970 ~ 12,817,405）表格，並進行延伸計算

![2020 年 PUSH 系列指令數量統計表](https://storage.googleapis.com/papyrus_images/d02fb89f3ba77d903279032fbd435983fc0471c55bafc01700961102878163c4.png)

2020 年 PUSH 系列指令數量統計表

---

*Originally published on [Blockchain Builder](https://paragraph.com/@blockchain-builder/eip-3855)*
