深⼊理解以太坊Gas機制:零字節地址能節省Gas?
创宇区块链安全实验室
2022-12-22 02:41
本文约2814字,阅读全文需要约11分钟
區塊鏈世界需要Gas就好比汽車需要汽油。那麼,你知道如何節省汽油嗎?下面我們就一起來探究一種前導零節約Gas的方法吧。

前言

前言

前言

一級標題

前言

前段時間在Etherscan 上查看交易時,發現一個很有趣的地址:0x00000000a03396F6F864B496713f2623b6756Be2。這個地址是以0 x 00000000 開頭,抱著探索未知的心理對該地址進行了簡單的搜索,發現該地址並不簡單,它不僅構造獨特同時,還能節省Gas 費。

2.1 Gas Price

什麼是Gas

2.2 Gas Limit

二級標題

Gas 是用於測量在以太坊區塊鏈上執行特定操作所需的計算工作量的單位,即以太坊網絡上的計算單位。我們可以簡單的把Gas 理解為汽油,其保證了以太坊網絡的正常運行。在以太坊區塊鏈上,執行寫入操作都需要支付一定的Gas 費用。

二級標題

在以太坊中,貨幣是以太幣(ether), 1 ether = 1 x 10 18 Wei。在以太坊區塊鏈上進行操作,如發送代幣、調用合約等都要支付相應Gas,且以Wei 作為單位來計算。 Wei 是ETH 原生最小的單位,ETH 消耗的Gas 單位是Gwei, 1 Gwei = 1 x 10 9 Wei。

Gas Price 是以太坊內消耗1 個Gas 對應多少的Gwei,當然交易發送方可以自定義願意支付的每單位Gas 價格。比如交易發送方的一筆交易需要耗費10 Gas,交易發送者願意支付3 Wei/Gas,交易的成本總價就是30 Wei。在我們使用的錢包(如MetaMask)裡都會有調整Gas 費的高級選項,Gas Price 越高,打包的優先級就越高。

1、固有成本

Gas Limit 是消耗Gas 的限制單位,即交易發送方在完成每筆交易時最多能使用的用於執行交易的Gas 量。如果沒有Gas Limit 做限制,可能會導致交易發送方的賬戶餘額因錯誤操作而消耗完,Gas Limit 是安全機制,防止把賬戶中所有ETH 消耗掉。

2.3 固有成本Gas

發送一筆交易的成本包括兩部分:

1、固有成本

2、執行成本

而固有成本由交易的負載決定:

2、調用智能合約函數的負載是執行消息時輸入的數據

一級標題

我們從以太坊黃皮書附錄G 中可得知創建合約和執行交易的相關成本Gas。

一級標題

我們假設$N{zeros}$ 代表的是交易負載中字節為0 的字節總數,$N{nonzeros}$ 代表交易負載中字節不為0 的字節總數,根據黃皮書6.2 章節關於執行的描述,可以得到固有成本。

一級標題

以太坊地址中零開頭的地址\,由於Gas 費用現在比較昂貴,所以優化Gas 變得很重要,優化Gas 費用的方法有很多,這裡我們不一一列舉,本文只以以太坊地址中0 字節降低Gas 費來討論,這是從EVM層面來優化Gas。通過使用比平時更多的0 字節(即漢明重量)的地址,並且在某些情況下,地址開頭有更多的0 字節,我們可以在許多類型的交易中節省汽油。\times 12 = 48 \,漢明重量是一串符號中非零符號的個數。全零符號的漢明重量為0 , 1101 的漢明重量為3 。

在以太坊黃皮書附錄G 中可以看到,使用0 字節時需要4 Gas,而使用非0 字節時需要16 Gas:

每次使用0 字節代替非0 字節時,就可以節省16 個Gas,因此,每次在msg.data 中用一個0 字節代替一個非0 字節,都將給我們節省12 個Gas。在以太坊中,地址是由0 x 開頭的40 個隨機字符的16 進製字符串(20 個字節),當以16 進制形式查看字節串時,由於每對數字(每個字符代表16 個可能的數字之一)構成一個字節(16 2 = 2 8 = 256 位),所以單個16 進制的0 ,或相鄰的0 分佈在兩個不同的字節中,不會減少字節串的漢明重量,所以只有連續2 個16 進制的0 才會減少漢明重量。 0 字節的排序對所產生的Gas 優化也沒有影響(如地址0x00a0009e638D25EFE5a894f6a36F42734477dECa中有2 個0 字節)。

在ERC 20 的transfer() 函數中,msg.sender 的漢明重量沒有區別,而作為transfer() 函數的一部分傳入msg.data 的_to 地址參數就有區別。

使用OpenZeppelin 的StandardToken 作為參考實例。向一個沒有0 字節的地址(如:0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2)進行標準轉賬需要花費35039 Gas,然而向一個有4 個0 字節的地址(如:0x00000000b011402777E34EFf44905BE85e3CdD01,即地址中有4 對0 )進行轉賬只需要34991 Gas,他們相差了$ 35039 - 34991 = 48

  • Gas$。而我們前面說到每次使用0 字節代替非0 字節時,可以節省12 個Gas(而在早先的以太坊版本中,甚至能節省高達64 Gas),這裡的48 Gas 可以表示成$ 4

  • Gas$,和我們從黃皮書中得到的期望值一樣。

  • 而2 個0 字節的地址0x00a0009e638D25EFE5a894f6a36F42734477dECa和上面2 個差值分別都是24 Gas,說明也是符合期望的。

  • 但是如果我們地址尾部存在0 字節時,又容易被短地址進行攻擊,所以以0 x 00 開頭的具有多個0 字節的地址就成為了更好的選擇。如果地址至少有4 個前導0 字節(即8 個前導0 的16 進制編碼格式),那麼每個地址將只需要佔用16 個字節,這樣兩個地址就可以裝入一個32 字節包了。這樣的優化不僅在於使用了$G_{txdatazero}$ 帶來的Gas 優化,而且由於不用從調用數據中讀寫更多的字節,我們還能省下更多的Gas,所以向這樣的地址轉賬時,不管該地址是合約地址還是普通賬戶地址,都能省下5% 左右的費用。

  • 92.47% 的機會在地址上找到0 個0 字節。

後記

優化Gas 的方法有很多,這裡我們就以EVM 底層視角研究了節省Gas 的方法,通過研究我們可以得到一個結論:以太坊地址裡面的00 越多(這裡需要注意是成對出現的0 ,至於原因我們在第4 節中已經提到),不管這個地址是合約地址還是普通地址,不管是轉入地址還是轉出地址,都能夠節省不少的Gas。

參考文章

创宇区块链安全实验室
作者文库