# EIP-663:SWAPN、DUPN 和 EXCHANGE 指令
# 注意事項
本文並沒有經過作者外的其他審查者審核,因此若內容有誤,請到 issue 區提出問題,我會儘速修改,謝謝。
# 1. 摘要(Abstract)
- 以前,EVM 只能使用
SWAP1
到SWAP16
、DUP1
到DUP16
,也就是只能操作頂層的 16 個資料。 - 現在要新增三個指令:
SWAPN
、DUPN
、EXCHANGE
,就能存取更深層的資料了。
# 2. 動機(Motivation)
- EVM 的堆疊最多可容納 1024 個資料,但原先只能輕鬆存取最頂層的 16 個項目,對於更深層的資料必須透過寫入記憶體或依賴編譯器最佳化,這會使程式變得複雜且效率降低。
- 在 EVM 上實作函式時,函式的輸入輸出參數數量經常超過 16 個,導致編譯器必須進行複雜的排程工作。
- 某些編譯器在進行堆疊最佳化(相當於變數管理)時,需要交換不同深度位置的資料,目前必須執行三條指令才能完成交換,新增的指令將可一步到位。
# 3. 新增的三個指令(Specification)
1. DUPN (opcode = 0xe6)
2. SWAPN (opcode = 0xe7)
3. EXCHANGE (opcode = 0xe8)
- 在舊的「非 EOF」格式中,遇到這三個指令會直接回傳錯誤並停止執行(維持現有行為)。
- 只有在新格式(EOF1)中才會啟用這三個指令。
# 3.1 立即參數(Immediate)
這三個指令後面都必須跟隨一個 8 位元(0~255)的參數 imm
:
- DUPN、SWAPN:
n = imm + 1
- EXCHANGE:
n = (imm >> 4) + 1
m = (imm & 0x0F) + 1
# 4. 驗證規則(Validation)
- 禁止使用跳躍指令跳轉到這三個新指令的立即參數位元組。
- 當堆疊深度不足時,不能執行這三個指令:
- DUPN:執行前必須有 ≥ n 個資料,執行後資料數【+1】
- SWAPN:執行前必須有 ≥ n+1 個資料,執行後深度不變
- EXCHANGE:執行前必須有 ≥ n+m+1 個資料,執行後深度不變
# 5. 執行語義(Execution Semantics)
- DUPN:將第 n 個資料(從上往下計算)複製到堆疊頂端
- SWAPN:將第 n+1 個資料和頂端資料交換位置
- EXCHANGE:將第 n+1 個資料和第 n+m+1 個資料交換位置
這三個指令的 Gas 費用皆為 3。
# 6. 範例說明(Examples)
為了更清楚說明,以下提供三個範例並附上 ASCII 圖示,展示各指令執行前後的堆疊狀態。
# 例子 1:DUPN 2
(複製第 3 個資料)
- 指令:
DUPN 2
- 計算:
n = 2 + 1 = 3
- 動作:複製第 3 個位置的資料 (C) 到堆疊頂端
初始堆疊(頂端在上):
│ E │ ← 第 1 個
│ D │ ← 第 2 個
│ C │ ← 第 3 個
│ B │ ← 第 4 個
│ A │ ← 第 5 個
執行後:
│ C │ ← 新的頂端(C 複製到頂端)
│ E │ ← 原第 1 個
│ D │ ← 原第 2 個
│ C │ ← 原第 3 個
│ B │ ← 原第 4 個
│ A │ ← 原第 5 個
# 例子 2:SWAPN 3
(交換第 5 個資料與頂端)
- 指令:
SWAPN 3
- 計算:
n = 3 + 1 = 4
,要交換第 (n+1)=5 個和頂端 - 動作:交換 E ↔ A
初始堆疊:
│ E │ ← 頂端
│ D │
│ C │
│ B │
│ A │ ← 第 5 個
執行後:
│ A │ ← 原第 5 個
│ D │
│ C │
│ B │
│ E │ ← 原頂端
# 例子 3:EXCHANGE 0x02
(交換第 2 個與第 5 個資料)
- 指令:
EXCHANGE 0x02
- 計算:
n = (0x02 >> 4) + 1 = 0 + 1 = 1
m = (0x02 & 0x0F) + 1 = 2 + 1 = 3
- 要交換第 (n+1)=2 個和第 (n+m+1)=5 個
- 動作:交換 D ↔ A
初始堆疊:
│ E │
│ D │ ← 第 2 個
│ C │
│ B │
│ A │ ← 第 5 個
執行後:
│ E │
│ A │ ← 原第 5 個
│ C │
│ B │
│ D │ ← 原第 2 個
# 7. 設計理念(Rationale)
- 為什麼使用立即參數? 避免動態參數變化,讓靜態分析更簡單,方便於程式檢查。
- 為什麼限制在 255? 堆疊最深也只有 1024,256 的深度除了已經比 16 有顯著改善,且以達 1/4 的總深度。在日常使用情境中不容易出現更多的需求,此外,再增加一個位元會將會帶來過大的成本且也沒如此強烈的需求。
- 為什麼要有 EXCHANGE? 編譯器有時需要一次交換兩個不同深度的位置,EXCHANGE 能夠一條指令完成,不需要使用三條指令。
# 8. 向前相容性(Backwards Compatibility)
- 這三個 opcode 在之前並未被使用,不會影響現有程式碼;只有在 EOFv1 格式中才會生效。