Как получить стоимость транзакции в модульном тесте Truffle?

Как я могу получить фактическое количество газа, потребляемого при sendTransactionтесте на трюфель?

В следующем тесте buyerотправляет amount50 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.

Я следил за стоимостью газа транзакции в тестовом примере с трюфелем, но это не помогло.

Есть идеи?

Ответы (2)

Вы должны умножить 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);
Спасибо! Я не понимаю, почему web3.eth.getTransaction(hash).gasи web3.eth.getTransactionReceipt(hash).gasUsedразные. В чем смысл бывшего?
Как я объяснил в посте web3.eth.getTransaction(hash).gas, это значение, предоставленное пользователем. Пока web3.eth.getTransactionReceipt(hash).gasUsedэто газ, используемый транзакцией. Поэтому gasдолжно быть >= gasUsedдля выполнения транзакции. Конечно, вы не могли знать раньше, сколько газа будет использовать ваша транзакция, поэтому пользователь должен увеличить газ, чтобы быть уверенным, что транзакция будет выполнена. gasUsedчасто <= gasи разница (неиспользованный газ) возвращается немедленно.

Альтернатива: вы можете использовать truffle-cost . Это позволяет вам регистрировать стоимость транзакций вместо продолжительности теста с помощью следующего синтаксиса:

result = await truffleCost.log(
  yourContract.yourFunction()
);

Пожалуйста, смотрите ссылку для установки (или я должен объяснить здесь?).

Отказ от ответственности: я разработчик truffle-cost.