溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

節(jié)約Gas成本的Solidity代碼模式有哪些

發(fā)布時間:2021-12-07 15:14:39 來源:億速云 閱讀:142 作者:iii 欄目:互聯(lián)網(wǎng)科技

本篇內(nèi)容主要講解“節(jié)約Gas成本的Solidity代碼模式有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“節(jié)約Gas成本的Solidity代碼模式有哪些”吧!

在以太坊區(qū)塊鏈上,Gas被用來補償?shù)V工為智能合約的存儲與執(zhí)行所提供的算力。目前以太坊的利用在逐漸增長,而交易手續(xù)費成本也水漲傳告 —— 現(xiàn)在每天的gas成本已經(jīng)高達數(shù)百萬美元。隨著以太坊生態(tài)系統(tǒng)的擴大,Solidity智能合約開發(fā)者也需要關(guān)注gas利用的優(yōu)化問題了。

1、使用短路模式排序Solidity操作

短路(short-circuiting)是一種使用或/與邏輯來排序不同成本操作的solidity合約開發(fā)模式,它將低gas成本的操作放在前面,高gas成本的操作放在后面,這樣如果前面的低成本操作可行,就可以跳過(短路)后面的高成本以太坊虛擬機操作了。

// f(x) 是低gas成本的操作
// g(y) 是高gas成本的操作

// 按如下排序不同gas成本的操作
f(x) || g(y)
f(x) && g(y)

2、刪減不必要的Solidity庫

在開發(fā)Solidity智能合約時,我們引入的庫通常只需要用到其中的部分功能,這意味著其中可能會包含大量對于你的智能合約而言其實是冗余的solidity代碼。如果可以在你自己的合約里安全有效地實現(xiàn)所依賴的庫功能,那么就能夠達到優(yōu)化solidity合約的gas利用的目的。

例如,在下面的solidity代碼中,我們的以太坊合約只是用到了SafeMath庫的add方法:

import './SafeMath.sol' as SafeMath;

contract SafeAddition {
  function safeAdd(uint a, uint b) public pure returns(uint) {
    return SafeMath.add(a, b);
  }
}

通過參考SafeMath的這部分代碼的實現(xiàn),可以把對這個solidity庫的依賴剔除掉:

contract SafeAddition {
  function safeAdd(uint a, uint b) public pure returns(uint) {
    uint c = a + b;
    require(c >= a, "Addition overflow");
    return c;
  }
}

3、顯式聲明Solidity合約函數(shù)的可見性

在Solidity合約開發(fā)種,顯式聲明函數(shù)的可見性不僅可以提高智能合約的安全性,同時也有利于優(yōu)化合約執(zhí)行的gas成本。例如,通過顯式地標(biāo)記函數(shù)為外部函數(shù)(External),可以強制將函數(shù)參數(shù)的存儲位置設(shè)置為calldata,這會節(jié)約每次函數(shù)執(zhí)行時所需的以太坊gas成本。

4、使用正確的Solidity數(shù)據(jù)類型

在Solidity中,有些數(shù)據(jù)類型要比另外一些數(shù)據(jù)類型的gas成本高。有必要了解可用數(shù)據(jù)類型的gas利用情況,以便根據(jù)你的需求選擇效率最高的那種。下面是關(guān)于solidity數(shù)據(jù)類型gas消耗情況的一些規(guī)則:

  • 在任何可以使用uint類型的情況下,不要使用string類型

  • 存儲uint256要比存儲uint8的gas成本低,為什么?點擊這里查看原文

  • 當(dāng)可以使用bytes類型時,不要在solidity合約種使用byte[]類型

  • 如果bytes的長度有可以預(yù)計的上限,那么盡可能改用bytes1~bytes32這些具有固定長度的solidity類型

  • bytes32所需的gas成本要低于string類型

5、避免Solidity智能合約中的死代碼

死代碼(Dead code)是指那些永遠(yuǎn)也不會執(zhí)行的Solidity代碼,例如那些執(zhí)行條件永遠(yuǎn)也不可能滿足的代碼,就像下面的兩個自相矛盾的條件判斷里的Solidity代碼塊,消耗了以太坊gas資源但沒有任何作用:

function deadCode(uint x) public pure {
  if(x < 1) {
    if(x > 2) {
      return x;
    }
  }
}

6、避免使用不必要的條件判斷

有些條件斷言的結(jié)果不需要Solidity代碼的執(zhí)行就可以了解,那么這樣的條件判斷就可以精簡掉。例如下面的Solidity合約代碼中的兩級判斷條件,最外層的判斷是在浪費寶貴的以太坊gas資源:

function opaquePredicate(uint x) public pure {
  if(x < 1) {
    if(x < 0) {
      return x;
    }
  }
}

7、避免在循環(huán)中執(zhí)行g(shù)as成本高的操作

由于SLOADSSTORE操作碼的成本高昂,因此管理storage變量的gas成本要遠(yuǎn)遠(yuǎn)高于內(nèi)存變量,所以要避免在循環(huán)中操作storage變量。例如下面的solidity代碼中,num變量是一個storage變量,那么未知循環(huán)次數(shù)的若干次操作,很可能會造成solidity開發(fā)者意料之外的以太坊gas消耗黑洞:

uint num = 0;

function expensiveLoop(uint x) public {
  for(uint i = 0; i < x; i++) {
    num += 1;
  }
}

解決上述反模式以太坊合約代碼的方法,是創(chuàng)建一個solidity臨時變量來代替上述全局變量參與循環(huán),然后在循環(huán)結(jié)束后重新將臨時變量的值賦給全局變量:

uint num = 0;

function lessExpensiveLoop(uint x) public {
  uint temp = num;
  for(uint i = 0; i < x; i++) {
    temp += 1;
  }
  num = temp;
}

8、避免為可預(yù)測的結(jié)果使用Solidity循環(huán)

如果一個循環(huán)計算的結(jié)果是無需編譯執(zhí)行Solidity代碼就可以預(yù)測的,那么就不要使用循環(huán),這可以可觀地節(jié)省gas。例如下面的以太坊合約代碼就可以直接設(shè)置num變量的值:

function constantOutcome() public pure returns(uint) {
  uint num = 0;
  for(uint i = 0; i < 100; i++) {
    num += 1;
  }
  return num;
}

9、循環(huán)合并模式

有時候在Solidity智能合約中,你會發(fā)現(xiàn)兩個循環(huán)的判斷條件一致,那么在這種情況下就沒有理由不合并它們。例如下面的以太坊合約代碼:

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;
}

10、避免循環(huán)中的重復(fù)計算

如果循環(huán)中的某個Solidity表達式在每次迭代都產(chǎn)生同樣的結(jié)果,那么就可以將其移出循環(huán)先行計算,從而節(jié)省掉循環(huán)中額外的gas成本。如果表達式中使用的變量是storage變量,這就更重要了。例如下面的智能合約代碼中表達式a*b的值,并不需要每次迭代重新計算:

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;
  }
}

到此,相信大家對“節(jié)約Gas成本的Solidity代碼模式有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI