Почему баланс моего счета после заключения договора такой разный?

Я пишу тест для лотерейного контракта:

var Lottery = artifacts.require("./Lottery.sol");

contract('Lottery', function (accounts) {
    var ACC_FABIAN = accounts[0];
    var ACC_RENE = accounts[1];
    var ACC_OTHER = accounts[2];
    var TICKET_PRICE = 1;

    var balance_before = web3.eth.getBalance(ACC_FABIAN).toString(10);

    var lotteryFn = Lottery.deployed();

    it('should buy a ticket for one user', function () {
        var meta;
        return lotteryFn.then(function (instance) {
            meta = instance;
            return instance.buyTicket(200, {from: ACC_FABIAN, value: TICKET_PRICE});
        }).then(function () {
            var buyingTimeFactor;
            meta.calculateBuyingTimeScore.call().then(function (btf) {
                buyingTimeFactor = btf.toNumber();
            });
            // ESTIMATION
            meta.getEstimation.call(ACC_FABIAN).then(function (estimation) {
                assert.equal(estimation.toNumber(), 200, "Estimations are different");
            });
            // BUYING TIME
            meta.getBuyingTime.call(ACC_FABIAN).then(function (buyingTime) {
                assert.equal(buyingTime.toNumber(), buyingTimeFactor, "Buying time not correct");
            });

            // PAYOUT
            meta.payout(200).then(function (response) {
                var balance_now = web3.eth.getBalance(ACC_FABIAN);
                console.log(web3.fromWei(balance_before, 'ether').toString(), web3.fromWei(balance_now, 'ether').toString());
            });
        });
    });
});

Как видите, я проверяю баланс счета до и после заключения контракта. console.log дает мне что-то вроде этого:

97.0711255 97.0326134

Это разница0.0385121 ETH

Откуда это?

Даже с TICKET_PRICE0 я получаю эту разницу. Газ такой дорогой?


Контракт:

contract Lottery {

    // CONSTANTS
    int constant LOTTERY_INTERVAL = 1 days;

    uint256 constant private TICKET_PRICE = 1;

    uint constant FEE_FACTOR = 200; // 0.5 %

    // VARIABLES
    uint256 totalBalance = 0;

    uint totalParticipants = 0;

    uint winnerCounter = 0;

    // Structs
    struct TicketHolder {
    address ticketHolder;
    uint estimation;
    uint buyingTimeScore;
    uint timestamp;
    uint score;
    }

    // Mappings
    mapping (address => TicketHolder) ticketHolders;

    mapping (uint => TicketHolder) ticketHoldersIndex;

    // Arrays
    address[] ticketHoldersAddress;

    address [] winners;

    // Constructor
    function Lottery(){

    }

    //Getters setters
    function getBuyingTime(address ticketHolder) /*internal*/ returns (uint){
        return ticketHolders[ticketHolder].buyingTimeScore;
    }


    function getEstimation(address ticketHolder) /*internal*/ returns (uint){
        return ticketHolders[ticketHolder].estimation;
    }

    function getScore(address ticketHolder) /*internal*/ returns (uint){
        return ticketHolders[ticketHolder].score;
    }


    function getMinute(uint timestamp) /*internal*/ constant returns (uint8) {
        return uint8((timestamp / 60) % 60);
    }

    function setScore(address ticketHolder, uint score) /*internal*/{
        ticketHolders[ticketHolder].score = score;
    }

    function calculateBuyingTimeScore() /*internal*/ returns (uint){
        uint timeBeforeNewRound = 60 - getMinute(now);
        return timeBeforeNewRound * 100 * 100 / 60;
    }

    function calculateDeviationScore(uint courseValue, uint estimatedValue) /*internal*/ returns (uint){
        uint difference = 0;
        if (courseValue >= estimatedValue) {
            difference = courseValue - estimatedValue;
        }
        else if (courseValue < estimatedValue) {
            difference = estimatedValue - courseValue;
        }

        // Calculated standard deviation
        uint deviation = (difference * 10000 / courseValue);
        uint score = 10000 - deviation;
        return score;
    }

    //TODO: add more conditions
    function buyTicket(uint estimation) payable {
        if (msg.value < TICKET_PRICE) throw;
        address ticketHolder = msg.sender;
        uint buyingTimeScore = calculateBuyingTimeScore();
        totalBalance += msg.value;
        ticketHolders[ticketHolder] = TicketHolder(msg.sender, estimation, buyingTimeScore, now, 0);
        ticketHoldersIndex[totalParticipants++] = TicketHolder(msg.sender, estimation, buyingTimeScore, now, 0);
        ticketHoldersAddress.push(ticketHolder);
    }

    function calculateScore(uint courseValue) /*internal*/ {
        if (totalParticipants == 0) throw;
        for (uint participant = 0; participant < totalParticipants; participant++) {
            TicketHolder ticketHolder = ticketHoldersIndex[participant];
            uint deviationScore = calculateDeviationScore(courseValue, ticketHolder.estimation) / 2;
            uint buyingTimeScore = ticketHolder.buyingTimeScore / 2;
            uint totalScore = deviationScore + buyingTimeScore;
            setScore(ticketHolder.ticketHolder, totalScore);
        }
    }

    function determineWinners() /*internal*/ returns (uint){
        uint highestScore = 0;
        for (uint participant = 0; participant < totalParticipants; participant++) {
            TicketHolder ticketHolder = ticketHoldersIndex[participant];
            uint score = ticketHolder.score;
            if (score >= highestScore) {
                winners.push(ticketHolder.ticketHolder);
                winnerCounter++;
                highestScore = score;
            }
        }
        return ticketHoldersAddress.length;
    }

    function payout(uint courseValue) /*internal*/ {
        if (totalParticipants == 0) throw;
        calculateScore(courseValue);
        determineWinners();
        uint256 winAmount = totalBalance / winnerCounter;
        for (uint i = 0; i < winnerCounter; i++) {
            address winnerTicket = winners[i];
            winnerTicket.transfer(winAmount);
        }
    }

}

Ответы (2)

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

Спасибо за Ваш ответ. В этом случае это будет около 10 долларов. Разве это не слишком много для такого крошечного контракта?
Да, но на самом деле это временный результат быстрого роста цен на ETH. Если вы не хотите платить так много, вы можете установить более низкую цену на газ. Просто настройки по умолчанию не очень быстро меняются

Да, это ожидаемо. Поскольку вы вызываете функции, которые вызывают изменение состояния (транзакции блокчейна), и это причина, по которой пользователь по умолчанию, то есть учетные записи [0], теряет газ для выполнения транзакции, и в конечном итоге расход газа приводит к потере баланса.

Проверьте этот ответ , чтобы узнать больше о газе и о том, как рассчитывается комиссия за транзакцию.