Gas 的考虑

Gas在 [gas] 一节中有更详细的描述,在智能合约编程中是一个非常重要的考虑因素。gas是限制以太坊允许交易消耗的最大计算量的资源。如果在计算过程中超过了gas限制,则会发生以下一系列事件:

  • 引发“out of gas”异常。

  • 函数执行前的合约状态被恢复。

  • 全部gas作为交易费用交给矿工,不予退还。

由于gas由创建该交易的用户支付,因此不鼓励用户调用gas成本高的函数。因此,程序员最大限度地减少合约函数的gas成本。为此,在构建智能合约时建议采用某些做法,以尽量减少函数调用的gas成本。

避免动态大小的数组

函数中任何动态大小的数组循环,对每个元素执行操作或搜索特定元素会引入使用过多gas的风险。在找到所需结果之前,或在对每个元素采取行动之前,合约可能会用尽gas。

避免调用其他合约

调用其他合约,尤其是在其函数的gas成本未知的情况下,会导致用尽gas的风险。避免使用未经过良好测试和广泛使用的库。库从其他程序员收到的审查越少,使用它的风险就越大。

估算gas成本

例如,如果你需要根据调用参数估计执行某种合约函数所需的gas,则可以使用以下过程;

  1. var contract = web3.eth.contract(abi).at(address);
  2. var gasEstimate = contract.myAweSomeMethod.estimateGas(arg1, arg2, {from: account});

gasEstimate 会告诉我们执行需要的gas单位。

为了获得网络的 gas价格 可以使用:

  1. var gasPrice = web3.eth.getGasPrice();

然后估算 gas成本

  1. var gasCostInEther = web3.fromWei((gasEstimate * gasPrice), 'ether');

让我们应用我们的天然气估算函数来估计我们的+Faucet+示例的天然气成本,使用此书代码库中的代码:

  1. code/truffle/FaucetEvents

我们以开发模式启动truffle,并执行一个JavaScript文件+gas_estimates.js+,其中包含:

gas_estimates.js: Using the estimateGas function

  1. var FaucetContract = artifacts.require("./Faucet.sol");
  2. FaucetContract.web3.eth.getGasPrice(function(error, result) {
  3. var gasPrice = Number(result);
  4. console.log("Gas Price is " + gasPrice + " wei"); // "10000000000000"
  5. // Get the contract instance
  6. FaucetContract.deployed().then(function(FaucetContractInstance) {
  7. // Use the keyword 'estimateGas' after the function name to get the gas estimation for this particular function (aprove)
  8. FaucetContractInstance.send(web3.toWei(1, "ether"));
  9. return FaucetContractInstance.withdraw.estimateGas(web3.toWei(0.1, "ether"));
  10. }).then(function(result) {
  11. var gas = Number(result);
  12. console.log("gas estimation = " + gas + " units");
  13. console.log("gas cost estimation = " + (gas * gasPrice) + " wei");
  14. console.log("gas cost estimation = " + FaucetContract.web3.fromWei((gas * gasPrice), 'ether') + " ether");
  15. });
  16. });

truffle开发控制台显示:

  1. $ truffle develop
  2. truffle(develop)> exec gas_estimates.js
  3. Using network 'develop'.
  4. Gas Price is 20000000000 wei
  5. gas estimation = 31397 units
  6. gas cost estimation = 627940000000000 wei
  7. gas cost estimation = 0.00062794 ether

建议你将函数的gas成本评估作为开发工作流程的一部分进行,以避免将合约部署到主网时出现意外。