Solidity
如何測量程式碼塊中使用的氣體?
這個答案很好地解釋瞭如何測量程式碼塊中使用的氣體。
在找到答案之前,我實際上一直在使用這種方法:
pragma solidity 0.4.26; import './IERC20Token.sol'; contract Tester { uint256 public gasUsed; function transfer(IERC20Token _token, address _to, uint256 _value) public { uint256 bgn = gasleft(); require(_token.transfer(_to, _value)); uint256 end = gasleft(); gasUsed = bgn - end; } }
然後,簡單地從 Truffle 4.1.16 測試:
const token = await ERC20Token.new('name', 'symbol', 18, SUPPLY); const tester = await Tester.new(); await token.transfer(tester.address, AMOUNT); await tester.transfer(token.address, accounts[0], AMOUNT); const gasUsed = await tester.gasUsed(); console.log(gasUsed.toFixed());
但是,它似乎沒有考慮將儲存變數從非零更改為零的氣體退款。
稍微了解一下這個退款,我相信它會被退回給寄件人(
msg.sender
),甚至是一路退回給原始寄件人(tx.origin
)。所以我正在尋找一種更準確的方法。
我不介意解決方案是否涉及鏈下,例如(使用 web3.js):
const balanceBefore = await web3.eth.getBalance(myAccount); const response = await myContract.methods.myFunc().send({from: myAccount, gasPrice: myGasPrice}); const balanceAfter = await web3.eth.getBalance(myAccount); const gasUsed = response.receipt.gasUsed; // now do something with balanceBefore, balanceAfter, myGasPrice and gasUsed
但結果應該只反映合約中實際程式碼塊的 gas 成本。
例如,它應該避免將交易本身的成本考慮在內。
有人對此有主要線索嗎?
謝謝!
好的,我意識到我可以簡單地使用它,而不必依賴
gasleft()
:pragma solidity 0.4.26; import './IERC20Token.sol'; contract Tester1 { address public to; uint256 public value; function transfer(IERC20Token _token, address _to, uint256 _value) public returns (bool) { to = _to; value = _value; return _token.transfer(_to, _value); } } contract Tester2 { address public to; uint256 public value; function transfer(IERC20Token _token, address _to, uint256 _value) public returns (bool) { to = _to; value = _value; return true; // _token.transfer(_to, _value); } }
然後,從 Truffle 4.1.16 測試:
const token = await ERC20Token.new('name', 'symbol', 18, SUPPLY); const tester1 = await Tester1.new(); const tester2 = await Tester2.new(); await token.transfer(tester1.address, AMOUNT); await token.transfer(tester2.address, AMOUNT); const response1 = await tester1.transfer(token.address, accounts[1], AMOUNT); const response2 = await tester2.transfer(token.address, accounts[2], AMOUNT); console.log(response1.receipt.gasUsed - response2.receipt.gasUsed);