Как оценить стоимость вызова метода смарт-контракта?

После успешного развертывания этого смарт-контракта в тестовой сети Ethereum

https://testnet.etherscan.io/address/0x27c042342C9ba937214117e11A4970A6145034cB

Можно ли рассчитать, сколько газа потребуется для вызова данного метода смарт-контракта?

Чтение Как оценить газ для функции без каких-либо входных параметров? и сколько стоит использование контракта? и Каковы ограничения для оценки газа и когда ее оценка может быть существенно ошибочной? не помогло мне, как ожидалось...

Вот как создать экземпляр смарт-контракта в командной строке консоли geth:

// creation of contract object
var aContract = web3.eth.contract([ { "constant": true, "inputs": [], "name": "queryNumEscrows", "outputs": [ { "name": "", "type": "uint256", "value": "0" } ], "type": "function" }, { "constant": true, "inputs": [ { "name": "escrowId", "type": "uint256" } ], "name": "queryStatus", "outputs": [ { "name": "status", "type": "uint256", "value": "0" } ], "type": "function" }, { "constant": false, "inputs": [ { "name": "seller", "type": "address" }, { "name": "thirdParty", "type": "address" } ], "name": "start1", "outputs": [ { "name": "escrowId", "type": "uint256" } ], "type": "function" }, { "constant": false, "inputs": [ { "name": "escrowId", "type": "uint256" } ], "name": "revoke", "outputs": [ { "name": "amount", "type": "uint256" } ], "type": "function" }, { "constant": false, "inputs": [ { "name": "escrowId", "type": "uint256" } ], "name": "release", "outputs": [ { "name": "amount", "type": "uint256" } ], "type": "function" }, { "constant": false, "inputs": [ { "name": "seller", "type": "address" }, { "name": "thirdParty", "type": "address" } ], "name": "start", "outputs": [ { "name": "", "type": "uint256" } ], "type": "function" }, { "constant": false, "inputs": [], "name": "kill", "outputs": [], "type": "function" } ]);

// initiate contract for an address
var sc = aContract.at('0x27c042342C9ba937214117e11A4970A6145034cB');

// view code
eth.getCode(sc.address);

Теперь я хочу отправить эту транзакцию в смарт-контракт, но я хотел бы заранее знать, сколько газа это займет:

sc.start.sendTransaction("0x90e8682b63d7922a3e942d4bbd4c88095634a17b", "0x47978a69f410d0f61850c92acdb0d4c464d70937", {from:"0x3b877e80b5c0b29d88f3768ed4292b35fdd93a9d", value:"0x3b9aca00"});

чтобы избежать этого сообщения:

"Warning! Error encountered during contract execution [Out of gas]".

Я предполагаю, что следует использовать следующий метод json-rpc:

https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas

Я прочитал в документах, что:

When calling SCs => data: DATA - (optional) Hash of the method signature and encoded parameters.

Но не понимаю, как закодировать имя метода, параметры и ABI в поле данных. Есть идеи?

Или есть другой способ решения этой проблемы?

Спасибо.

На ethereum.stackexchange.com/questions/7557/… есть рабочий пример . Затем найдите на этом сайте ABI, чтобы определить кодировку.
Спасибо, это хорошая отправная точка...

Ответы (2)

В документации мало деталей, и мне потребовалась целая вечность, чтобы понять правильный путь с помощью ваших ссылок, в любом случае, вот что работает для меня:

Протестировано на Geth: 1.6.7 - стабильная, web3.js: 0.20.2 Parity/v1.7.2 и тестовая сеть Kovan.

В качестве примера я буду использовать минимальный токен:

pragma solidity ^0.4.0;

contract minimalToken {

     mapping (address => uint256) public balanceOf;

    function minimalToken(uint256 initialSupply) {
        balanceOf[msg.sender] = initialSupply;
    }

    function transfer(address _to, uint256 _value) {
        require(balanceOf[msg.sender] >= _value);
        require(balanceOf[_to] + _value >= balanceOf[_to]);
        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;
    }
}

Я сосредоточусь на методе перевода, который принимает 2 аргумента (адрес, сумма) для перевода:

    var contract = web3.eth.contract(contractABI).at("0x8caaa1f263ff14d0276ff1a1a6ed15c51159d6e0");
    var receiverAddress = '0x00Ce6C92856A657979E7728005DBc9acD002Eb09';
    var callData = contract.transfer.getData(receiverAddress, 2000);

    var gasEstimate = web3.eth.estimateGas({
        from: web3.eth.coinbase,
        to: "0x8caaa1f263ff14d0276ff1a1a6ed15c51159d6e0",
        data: callData
    });

    var gasPrice = web3.eth.gasPrice;

    console.log('gas Price: ' + gasPrice);
    console.log('Estimated Transaction gas: ' + gasEstimate);

// gas Price: 21000000000
// Estimated Transaction gas: 34207

Одна вещь, которая меня сбила с толку, заключалась в том, что я продолжал получать ошибки транзакции из-за того, что не включил поле from: в транзакцию.

Надеюсь это поможет.

Если вы хотите знать это в процессе разработки , вы можете получить хорошую оценку, используя testrpc для имитации блокчейна. После отправки транзакции он сообщит вам об использовании газа в терминале.

Если вы столкнулись с ошибками из-за нехватки газа, вы также можете использовать testrpc (или браузер-солидность), чтобы определить, что это действительно ошибка из-за нехватки газа. Другие ошибки (выбросы, неверный поиск в массиве и т. д.) будут отображаться как OOG для большинства узлов. testrpc и browser-solidity скажут вам, если это что-то другое.