¿Por qué el saldo de mi cuenta después de ejecutar el contrato es tan diferente?

Estoy escribiendo una prueba para un contrato de Lotería:

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());
            });
        });
    });
});

Como puede ver, estoy revisando el saldo de la cuenta antes y después del contrato. El console.log me da algo como esto:

97.0711255 97.0326134

Esta es una diferencia de0.0385121 ETH

¿De dónde viene esto?

Incluso con un TICKET_PRICEvalor de 0 obtengo esta diferencia. ¿Es tan cara la gasolina?


El contrato:

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);
        }
    }

}

Respuestas (2)

Cada transacción de cambio de estado incurre en el costo de la gasolina, puede especificar una cantidad de gasolina más baja cuando llame a la función de contrato, pero tenga en cuenta que si establece una tarifa demasiado baja, su transacción será rechazada.

Gracias por tu respuesta. En este caso rondaría los 10$. ¿No es demasiado para este contrato súper pequeño?
Sí, lo es, pero en realidad es un resultado temporal del rápido aumento del precio de ETH. Si no quiere pagar tanto, puede bajar el precio de la gasolina. Los valores predeterminados simplemente no se han ajustado muy rápido

Sí, esto es lo esperado. Dado que está llamando a las funciones que están causando el cambio de estado (transacciones de cadena de bloques) y esa es la razón por la cual el usuario predeterminado, que es las cuentas [0], está perdiendo gas para ejecutar la transacción y, finalmente, el gasto de gas da como resultado la pérdida de saldo.

Consulte esta respuesta para comprender más sobre Gas y cómo se calcula la tarifa de transacción.