Как я могу получить фактическое количество газа, потребляемого при sendTransaction
тесте на трюфель?
В следующем тесте buyer
отправляет amount
50 ETH на контракт:
const EmptyContract = artifacts.require("EmptyContract");
const BigNumber = web3.BigNumber;
contract('Test', function(accounts) {
it("should work", async () => {
let contract = await EmptyContract.new({ from: accounts[1] });
let amount = web3.toWei(50, 'ether');
let buyer = accounts[2];
// BALANCE BEFORE TX
let balanceBefore = web3.eth.getBalance(buyer);
// SEND TX
let hash = await contract.buy.sendTransaction({from: buyer, value: amount});
// BALANCE AFTER TX
const balanceAfter = web3.eth.getBalance(buyer);
let tx = await web3.eth.getTransaction(hash);
const gasUsed = tx.gas;
const gasCost = tx.gasPrice.mul(gasUsed);
console.log("BEFORE", balanceBefore.toNumber());
console.log("amount sent", amount);
console.log("gas price", tx.gasPrice.toNumber());
console.log("gas used", gasUsed);
console.log("gas cost", gasCost.toNumber());
console.log("AFTER", balanceAfter.toNumber());
console.log("CHECKSUM", balanceAfter.add(gasCost).add(amount).toNumber());
assert.equal(balanceBefore.toNumber(), balanceAfter.add(gasCost).add(amount).toNumber());
});
});
Затем buyer
проверяется баланс. Так должно быть
[баланс до транзакций] = [баланс после транзакций] + [отправленная сумма] + [стоимость газа]
Но это не удается, печать:
BEFORE 100000000000000000000
amount sent 50000000000000000000
gas price 100000000000
gas used 6721975
gas cost 672197500000000000
AFTER 49997862200000000000
CHECKSUM 100670059700000000000
:
AssertionError: expected 100000000000000000000 to equal 100670059700000000000
Контракт очень простой:
pragma solidity ^0.4.18;
contract EmptyContract {
function buy() public payable { }
}
Кажется, что стоимость транзакции на 0,6700597 ETH меньше, чем значение, возвращаемое tx
.
Я следил за стоимостью газа транзакции в тестовом примере с трюфелем, но это не помогло.
Есть идеи?
Вы должны умножить gasUsed
для gasPrice
. Содержится gasUsed
в квитанции об операции. Пока gasPrice
находится в самой транзакции. Действительно, в вашем случае вы пытаетесь умножить значение gasPrice
для gas
, предоставленное отправителем (которое может быть выше, чем gasUsed
). ссылка: getTransaction , getTransactionReceipt
Итак, вот как должен выглядеть ваш код, чтобы быть правильным
const hash = await contract.buy.sendTransaction({from: покупатель, значение: сумма}); // БАЛАНС ПОСЛЕ ТХ const balanceAfter = web3.eth.getBalance(покупатель); const tx = await web3.eth.getTransaction(хеш); константная квитанция = ожидание web3.eth.getTransactionReceipt(хэш); const gasCost = tx.gasPrice.mul(receipt.gasUsed);
или вы также можете фактически сохранить getTransactionReceipt
вызов, если вы вызываете свой метод напрямую (в этом случае вы должны получить результат, который также содержит ссылку на получение транзакции )
const txInfo = await contract.buy({от: покупатель, значение: сумма}); // БАЛАНС ПОСЛЕ ТХ const balanceAfter = web3.eth.getBalance(покупатель); const tx = await web3.eth.getTransaction(txInfo.tx); const gasCost = tx.gasPrice.mul(txInfo.receipt.gasUsed);
Альтернатива: вы можете использовать truffle-cost . Это позволяет вам регистрировать стоимость транзакций вместо продолжительности теста с помощью следующего синтаксиса:
result = await truffleCost.log(
yourContract.yourFunction()
);
Пожалуйста, смотрите ссылку для установки (или я должен объяснить здесь?).
Отказ от ответственности: я разработчик truffle-cost.
Роберт
web3.eth.getTransaction(hash).gas
иweb3.eth.getTransactionReceipt(hash).gasUsed
разные. В чем смысл бывшего?мирг
web3.eth.getTransaction(hash).gas
, это значение, предоставленное пользователем. Покаweb3.eth.getTransactionReceipt(hash).gasUsed
это газ, используемый транзакцией. Поэтомуgas
должно быть >=gasUsed
для выполнения транзакции. Конечно, вы не могли знать раньше, сколько газа будет использовать ваша транзакция, поэтому пользователь должен увеличить газ, чтобы быть уверенным, что транзакция будет выполнена.gasUsed
часто <=gas
и разница (неиспользованный газ) возвращается немедленно.