Gas和汽車耗油的概念一樣,每輛車在理想情況下(不會折舊)的單位耗油量、油箱容量是不變的,然而油價是會起伏的。同理,已部屬合約的Gas Consumption是固定不變的,真正導致每次部屬同樣合約(程式碼)、呼叫相同函式的 Gasfee 都不一樣的原因來自於 Gas Price 是不斷變動的
如果真的得徹底了解合約中耗費的Gas,我們可以利用 REMIX Debugging Step Detail 取得合約到底執行了哪些 Operation,再利用Ethereum Yellow Paper 中的定義計算 Gas Consumption。也就是說實際上是 Operational Complexity 決定了 Gas Cost。
如何減少 gas 的耗費:
event
而非 storage
&&
或者 ||
來提早結束判斷,或者是在引入 Library 的時候,不要把所有 Library 的所有程式碼都引入,只選擇我們會用到的部分程式碼(有一定風險)。external
可以讓 memory storation 被設為 calldata
。而將參數設為 calldata
而非 memory
可以節省 gas 的原因在於 calldata
參數是唯讀不可改的(可改就需要更多 opCodes 的支援)。bytes32
或 uint
而非 string
。以及最基本的使用 mapping
來避免 Looping 一個 array
。Source: Yellow Paper
在 ConsenSys/gpact 中有使用到 Hidden Parameters 的技巧,可以把 AuthVal 與 Function Selector 包在一起進行呼叫。
補充:Function Selector 太後面會導致 Gas 增加,如果想要更省的話可以把函式分開成獨立的合約 Library Deploy。
即便便用 unchecked
也無法省掉 Casting 還有 /0 的 SafeMath 檢查,但如果使用 Assembly 就可以真的減少,這就是 ABDK 和 Solmate 來做 sqrt 逼近的差別。
或者是產生 Merkle Proof 的時候,OpenZeppelin 使用的方法也是使用組合語言做更有效率的 hash:Source。
最後歡迎大家拍打餵食大學生
0x2b83c71A59b926137D3E1f37EF20394d0495d72d