如何編寫智慧合約,最佳化以太坊gas的消耗

買賣虛擬貨幣
在以太坊區塊鏈上,gas是一種執行費,用於補償礦工為智慧合約提供算力所需的計算資源。網路的使用逐漸增加,當前的gas成本每天達數百萬美元。隨著生態系統的不斷髮展,gas最佳化的價值也將隨之增長。以下將介紹一些常見的gas最佳化模式。gas節能模式您可以在程式碼中使用以下模式來減少gas消耗。Short-circuitingShort-circuiting是一種策略,當一個操作使用||或&&。此模式的工作原理是首先對低成本操作排序,以便在第一個操作計算為true時跳過(Short-circuiting)高成本操作。// f(x) is low cost
// g(y) is expensive// Ordering should go as followsf(x) || g(y)f(x) && g(y)不必要的庫(libraries)庫(libraries)通常只為少數用途而匯入,這意味著它們可能包含大量對您的智慧合約來說是多餘的程式碼。如果您可以安全有效地實現智慧合約中從庫(libraries)匯入的函式,那麼最好這樣做。
import './SafeMath.sol' as SafeMath;contract SafeAddition {  function safeAdd(uint a, uint b) public pure returns(uint) {    return SafeMath.add(a, b);  }}
contract SafeAddition {  function safeAdd(uint a, uint b) public pure returns(uint) {    uint c = a + b;    require(c >= a, "Addition overflow");    return c;  }
}顯式函式可見性顯式函式可見性通常可以在智慧合約安全性和gas最佳化方面提供好處。例如顯式標記外部函式會強制將函式引數儲存位置設定為calldata,這樣每次執行函式時都可以節省gas。正確的資料型別在Solidity中,某些資料型別比其他資料型別更昂貴。重要的是要意識到可以使用的最有效的型別。以下是有關資料型別的一些規則。
· 儘可能使用uint型別代替string型別。· 與uint8相比,型別uint256所儲存的gas更少。· 型別位元組應該在byte []之上使用。· 如果可以限制位元組的長度,請使用從位元組1到位元組32的最小數量。· 使用bytes32型別比使用string型別便宜。gas消耗模式
以下這些模式會增加gas成本,應避免使用。無效程式碼(Dead code)無效程式碼是永遠不會執行的程式碼,因為它的計算是基於一個總是返回false的條件。function deadCode(uint x) public pure {  if(x < 1) {    if(x > 2) {
      return x;    }  }}不明確的斷言(Opaque predicate)某些條件的結果無需執行即可知道,因此不需要計算。
function opaquePredicate(uint x) public pure {  if(x > 1) {    if(x > 0) {      return x;    }  }
}迴圈中昂貴的操作(Expensive operations in a loop)由於昂貴的SLOAD和SSTORE操作碼,管理儲存中的變數比管理記憶體中的變數要昂貴得多。因此,不應在迴圈中使用儲存變數。uint num = 0;function expensiveLoop(uint x) public {  for(uint i = 0; i < x; i++) {
    num += 1;  }}該模式的解決方法是建立一個代表全域性變數的臨時變數,並在迴圈完成後,將臨時變數的值重新分配給全域性變數。uint num = 0;function lessExpensiveLoop(uint x) public {
  uint temp = num;  for(uint i = 0; i < x; i++) {    temp += 1;  }  num = temp;}
迴圈的持續結果(Constant outcome of a loop)如果迴圈的結果是可以在編譯期間推斷的常數,則不應使用它。function constantOutcome() public pure returns(uint) {  uint num = 0;  for(uint i = 0; i < 100; i++) {    num += 1;
  }  return num;}迴圈融合(Loop fusion)有時在智慧合約中,您可能會發現有兩個具有相同引數的迴圈。 在迴圈引數相同的情況下,沒有理由使用單獨的迴圈。function loopFusion(uint x, uint y) public pure returns(uint) {
  for(uint i = 0; i < 100; i++) {    x += 1;  }  for(uint i = 0; i < 100; i++) {    y += 1;  }
  return x + y;}迴圈重複計算如果迴圈中的表示式在每次迭代中產生相同的結果,則可以將其移出迴圈。當表示式中使用的變數儲存在儲存器中時,這一點尤其重要。uint a = 4;uint b = 5;
function repeatedComputations(uint x) public returns(uint) {  uint sum = 0;  for(uint i = 0; i <= x; i++) {    sum = sum + a * b;  }}
與單側迴圈結果的比較如果在迴圈的每個迭代中執行比較但每次的結果都相同,則應將其從迴圈中刪除。function unilateralOutcome(uint x) public returns(uint) {  uint sum = 0;  for(uint i = 0; i <= 100; i++) {    if(x > 1) {
      sum += 1;    }  }  return sum;}

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;