JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

EVM 與 Gas

以太坊上每一個節點都步調一致地執行著同一台世界電腦。Gas 就是那只計費表,讓這台電腦的每一步都得花錢——於是程式碼必須付費,也永遠不可能無休止地跑下去。

一台電腦,由所有人一起執行

想像一個巨大的廳堂,裡面擺滿了成千上萬台一模一樣的計算機,每一台前面都坐著一個身處不同大洲的人。有人念出一份步驟清單——把這個加上、把那個存下、把這兩個比一比——然後每一個人都在同一時刻、敲入完全相同的步驟。因為計算機一模一樣、步驟也一模一樣,他們最終都會落到同一個答案上。沒有哪一台計算機說了算;答案不過就是他們全體一致認可的那個。這個廳堂,就是 以太坊虛擬機,通常簡稱為 EVM。

一份 智慧合約,就是這樣一份步驟清單——只寫下一次,然後永久存在鏈上。當你發出一筆呼叫某個合約的 交易,你就是在把它的步驟清單念給整個廳堂聽。以太坊 上的每一個 全節點 都會讓 EVM 重新走一遍這些步驟,並核對自己是否得出了相同的結果。這就是為什麼人們把 EVM 叫做一台單一的全球電腦:它是一台機器,但它的運算被鏡像複製到每一個節點上,於是沒有任何單獨一個節點能在結果上撒謊。

為什麼運算需要一只計費表

但這裡有個麻煩。成千上萬個節點馬上就要免費替你跑這份步驟清單,用的還是他們自己的機器。那麼,是什麼攔著一份粗心——甚或惡意——的合約,不讓它叫所有節點數到一兆,或是繞著圈子永遠跑下去、永不停手呢?只要哪怕一份步驟清單能不受限制地跑,它就能把整台全球電腦凍住。解法妙得很簡單:每一步都收費。給運算貼上的這個價簽,就叫 gas

把 gas 想成計程車裡的一只油表。EVM 執行的每一個操作,都有規則手冊定好的一筆固定 gas 成本——像把兩個數相加這種便宜活兒,花得少;像把一個值寫進永久儲存這種昂貴活兒,花得多。當你的交易在跑,計費表一路往上跳,消耗著一個你出錢灌滿的油箱。跑一份又短又簡單的步驟清單,你只花一點點油;跑一份又長、又頻繁寫儲存的,你就花掉一大筆。這只表把工作量變得可見、也可計費,就像計程車按里程而不是按一口價收費。

gas 上限、gas 價格,與最後的帳單

當你發出一筆交易,你要設定兩個各自獨立的數字,而把它們在腦子裡分清楚是很值得的。gas 上限是油箱的大小——在 EVM 把這筆交易硬生生叫停之前,你允許它最多燒掉多少 gas。它保護你不被一份有缺陷的合約把錢包抽乾。gas 價格則是這一份份 gas,你每一單位願意出多少錢,用以太幣的極小零頭來報價。前者說的是*我準備開多遠*;後者說的是*每公升油我願意付多少*。

你真正要付的帳單,大體上就是這兩個數相乘:實際用掉的 gas × gas 價格。關鍵在於,你是按真正燒掉的 gas 來付費的,而不是按整個油箱——如果你的步驟清單在十萬的上限裡只需要四萬 gas,那沒用掉的六萬會原封退還給你。上限是為了安全的天花板;真實的成本,跟著實際幹完的活兒走。還有一處值得知道的細節:如今的 gas 價格分成兩部分——一部分是網路為每一個 區塊 自動定下、隨後銷毀掉的基礎費,另一部分是你額外加在上面、用來把自己的交易往前推一推的一小筆小費。基礎費不進任何人的口袋,而是被燒掉,從流通中永久抹除。

那麼,為什麼同樣一個動作,在繁忙時段會更貴?因為每一個區塊能容納的 gas 總量是有上限的。當 記憶體池 裡擠滿了同時都想擠進去的人,區塊被塞滿,網路就會一個區塊接一個區塊地自動把基礎費往上抬,直到需求降溫——正是這一部分,讓一個清閒日裡的動作突然變貴。小費則是你插隊往前的槓桿:給得更厚,區塊建構者就更早把你排進去;鏈上清閒時給得少,你照樣進得去。你那個動作所需的 gas 數量幾乎不變——上下浮動的,是每單位的價格,由有多少人在搶同一塊稀缺的區塊空間所決定。

一段微型軌跡,一步一步看

我們來親眼看一份微型合約在計費表上跑一遍。下面是一段 Solidity 程式碼——編寫 EVM 合約最常用的語言。它做的不過是把兩個數相加,再把結果存進永久儲存裡:

contract Tiny {
    uint256 total;

    function bump(uint256 a, uint256 b) public {
        uint256 sum = a + b;   // do the math in memory
        total = sum;           // save it to storage
    }
}
一份極簡的 Solidity 合約:把兩個數相加,再把結果存到鏈上。

EVM 從來看不到這段工整的文字。它跑的是這段程式碼編譯之後落成的一串微型操作,並對每一個計費。看著 gas 油箱一路被抽乾——留意那一筆單獨的寫儲存是怎樣把其餘一切都比得微不足道的,因為讓成千上萬個節點永遠記住一個值,是你能向它們提出的最昂貴的請求:

step  operation        gas    running total
----  ---------------  -----  -------------
 1    PUSH a               3              3
 2    PUSH b               3              6
 3    ADD  (a + b)         3              9
 4    PUSH slot            3             12
 5    SSTORE (save sum) 20000          20012
                                  ^^^^^
                          one storage write
                          dominates the bill
每一個 EVM 操作都有一筆固定的 gas 成本。算術幾乎免費;寫入永久儲存則是遠遠最貴的一步。

把它當成一筆流水帳來讀。那三步算術幾乎撥不動指針;而單單那一筆寫儲存,就貴了上千倍。這是你最該帶走的一條直覺:在 EVM 上,做運算是便宜的,記住東西是昂貴的。優秀的合約作者,會把大量心思花在儘可能少地碰儲存上,原因正在於,gas 就是花在那裡的。

本篇要點

把它收攏到一處,整幅圖就清清爽爽了。EVM 是一台全球電腦,每個節點都步調一致地重跑一遍它,於是它的結果是整個網路可以去驗證、而不是只能去信任的東西。Gas 是給那場運算的每一步定價的計費表:它讓工作必須付費,讓任何合約都沒法永遠迴圈下去,並且——隨著壅塞把每個區塊的基礎費推高又壓低——決定你此刻要付多少。gas 上限給你的風險封頂;gas 價格(一筆被燒掉的基礎費,加上你的小費)定下費率;帳單就是這個費率,乘上你實際用掉的工作量。

現在你能切身體會到,為什麼一條鏈可能只花幾分錢,而另一條要花上幾美元:歸根結底,就看區塊空間有多少、又有多少人在為它出價。引擎和它的計費表都弄明白之後,接下來的幾篇會往上爬一層——去看那些讓合約得以鑄造與轉移價值的 代幣標準,以及驅動整台機器運轉的錢包與應用。