幾乎每一條新公鏈的首頁都會寫「完全相容 EVM」。這句話聽起來像技術承諾,更像需要被追問的廣告詞:合約能否不改位元組碼直接部署?錢包與瀏覽器能否只換 RPC 端點就接入?還是僅僅「可以用 Solidity 寫」?這三件事在工程上相差極大,對外傳播時卻經常被壓成同一句話。
對一條既要保留 EVM 相容、又要把執行模型改成平行的鏈來說,這不是修辭問題,而是每天都要守住的工程約束。改了排程順序、加了衝突偵測與多引擎之後,如何保證對合約作者可見的行為仍與以太坊主網一致,才是「相容」二字真正值錢的地方。前文 《Bitroot 定位》 已經說明 Bitroot 為什麼堅持完整 EVM 相容;本文把「完整」拆成可核查的四層。
位元組碼層:相容的最小單位是操作碼,不是語法
EVM 從不執行 Solidity 原始碼,它執行的是編譯後的操作碼序列:圍繞堆疊、記憶體與儲存的指令集,外加帳戶模型——每個地址有 nonce、餘額、程式碼雜湊與獨立的儲存樹。嚴格相容意味著操作碼語意、Gas 計價、堆疊深度限制、帳戶狀態讀寫規則都與以太坊的目標硬分叉對齊。在這個前提下,一份未經重新編譯的位元組碼,理論上應在另一條鏈上得到相同的狀態轉換結果。
這個標準決定了遷移成本的下限。位元組碼層級的相容意味著:已稽核的合約不必為了「換鏈」而整份重審語法層的差異;依賴 CREATE2 地址推導、或依賴特定操作碼 Gas 成本做防重入設計的合約,不會因為底層計價悄悄改變而行為跑偏。反過來說,若一條鏈只是「支援用 Solidity 寫」,開發者拿到的只是語法上的熟悉感——一旦觸及冷門操作碼或 Gas 假設,行為隨時可能漂移。
還需要核對硬分叉的對齊範圍:同一份位元組碼在 Shanghai、Cancun 或更新分叉下的合法操作碼集合並不完全相同。專案若聲稱相容,應寫明對齊到哪一次以太坊升級,而不是用一個模糊的「EVM」概括所有歷史狀態。遷移團隊可以用主網已部署合約的 runtime 位元組碼做對照部署,檢查程式碼雜湊與關鍵呼叫路徑的返回值。
平行執行會額外對這一層加壓。樂觀平行可能先並行預執行再驗證回滾,但對合約作者而言,最終提交的狀態轉換仍必須等價於某個確定的串列次序(通常是區塊內的交易順序)。若平行排程改變了可見的最終狀態,那就不叫相容,而是換了一台虛擬機。關於正確性邊界與串列化等價,可參見 《樂觀並行控制(OCC)入門》。把平行執行放回更寬的擴容座標系,也可對照 《區塊鏈擴容地圖》 與 《EVM 單執行緒瓶頸》:相容性要守住的,是合約作者依賴的確定性語意,而不是單執行緒解譯器本身。
預編譯層:同一地址,不同實作就是不相容
以太坊把一部分昂貴運算做成預編譯合約,固定在 0x01–0x0a 等地址上,例如橢圓曲線配對、模冪、雜湊。應用與函式庫大量硬編碼這些地址與 Gas 成本。一條鏈若改了預編譯集合、地址映射或返回值語意,表面上還能跑 Solidity,實際上已經踩穿了相容邊界——許多稽核過的函式庫會在鏈上直接失敗或算出錯誤結果。
「假相容」的常見形態包括:只實作常用的預編譯、擅自加入自訂預編譯卻複用以太坊的保留地址,或改了 Gas 卻不改文件。對遷移團隊來說,正確的驗收方式不是看白皮書有沒有寫「EVM 相容」,而是對照目標硬分叉的預編譯表做差分測試:同一輸入、同一呼叫資料,主網與目標鏈的返回值與 Gas 消耗是否一致。配對與模冪這類路徑尤其值得覆蓋,因為它們既昂貴又常被橋、證明驗證與密碼學函式庫依賴。
平行 EVM 本身不要求改動預編譯語意;真正的風險來自「為了加速而特化」的誘惑。任何為了吞吐量而做的預編譯改動,都應視為顯式的協議差異,而不是悄悄塞進「相容」的敘事裡。團隊若引入自訂預編譯來加速特定運算,也應使用明確未被佔用的地址空間,並在差異文件中寫清楚,避免與以太坊的保留地址衝突。
JSON-RPC 層:工具鏈活不活,取決於介面而不是口號
合約能部署,不等於生態能接入。錢包、區塊瀏覽器、索引器、監控系統依賴的是 JSON-RPC:eth_call、eth_getLogs、eth_estimateGas、eth_getTransactionReceipt 等。欄位含義、錯誤碼、日誌索引規則、pending 與 latest 的語意若與以太坊客戶端的習慣不一致,前端與基礎設施就得寫適配層——遷移成本會從「換 RPC」膨脹成「重做一整條維運鏈路」。
值得單獨強調的是 eth_estimateGas 與 trace 類介面。平行執行下,預估 Gas 若沒有按最終的串列語意模擬,可能系統性地偏低或偏高;除錯工具若拿不到與主網同構的 trace,Foundry 的 fork 測試與事故檢討都會變得更困難。因此,JSON-RPC 相容不是「能連上 MetaMask」這麼低的門檻,而是開發與維運的日常路徑是否可無感複用。過濾器訂閱、eth_feeHistory、與 EIP-1559 相關的欄位是否齊全,也往往決定現成 SDK 能否少改設定就上線。
索引與瀏覽器還依賴穩定的日誌順序與收據欄位。若平行執行改變了「何時可見」的中間狀態,但最終收據與主網同構,應用層通常仍可接受;若最終收據欄位缺失或錯誤碼體系私有化,生態工具就得各自分叉維護。相容性驗收應把「唯讀呼叫 + 發交易 + 拉日誌 + 估 Gas」當成一條閉環,而不是只測部署成功。
工具鏈層:Foundry 與 Hardhat 是相容性的終審法庭
對多數團隊而言,相容性的終審不在白皮書,而在本地:forge test、Hardhat 指令碼、OpenZeppelin 合約、常用驗證外掛能否對著目標鏈的 RPC 原樣跑通。Foundry(Forge / Cast / Anvil)已成為許多新專案的預設測試框架;Hardhat 仍覆蓋大量存量倉庫。兩者都假設:編譯器輸出的位元組碼、鏈上預編譯,以及 RPC 行為與以太坊足夠接近。
實用的驗收清單可以很短,但必須可重複:
- 用同一 Solidity 版本與最佳化器設定編譯,部署的位元組碼雜湊是否與主網部署一致(或差異是否僅來自可解釋的不可變參數)。
- 對關鍵預編譯做差分測試。
- 用 Anvil / Hardhat Network fork 目標鏈狀態,跑現有的整合測試。
- 用錢包只改 chainId 與 RPC,完成簽章、發送、收據確認的全流程。
- 對專案核心合約跑一次不變式測試:餘額守恆、權限檢查、重入防護在目標鏈上是否仍成立。
任何一步失敗,都說明「相容」仍有缺口。Bitroot 選擇把複雜度放在執行環境的平行排程,而不是要求開發者改寫 Solidity 或更換工具鏈,正是為了讓上述路徑盡量保持成立;相關工程敘述亦可對照 《Bitroot 平行化 EVM 技術解析》 與 《多引擎平行執行設計》。與 《平行執行的三條路線》 對照可以看到:堅持位元組碼相容,意味著放棄一部分可透過新帳戶模型換取的平行度上限,換來的是開發者生態的遷移半徑。
如何讀「EVM 相容」聲明
把行銷句拆成四個是非題:位元組碼語意是否對齊目標硬分叉?預編譯表是否一致?JSON-RPC 是否覆蓋主網常用方法且語意同構?Foundry / Hardhat 的現有專案能否少改或不改地跑通?四個「是」才接近嚴格相容;任一「否」都應被寫成明確的差異文件,而不是藏在相容口號後面。
平行執行可以改變吞吐量與衝突下的延遲分布,但不應該改寫合約作者依賴的確定性語意。熱點負載下使用者感知到的重試與延遲變化,屬於效能與工作負載問題,應與「語意是否相容」分開討論——前者見後續 《衝突熱點與工作負載》 與 《效能指標詞典》。若一條鏈用平行換來了更快的基準數字,卻讓工具鏈與位元組碼行為變得不可預測,那是用短期的效能海報透支長期的生態——而生態網路效應,才是 EVM 路線真正想買到的東西。
下一篇將按讀者角色給出只指向已發布文章的閱讀路徑,避免把不同背景的問題混成一篇誰也讀不透的長文。
