Solidity

為什麼執行合約後我的賬戶餘額如此不同?

  • July 2, 2017

我正在為彩票契約編寫測試:

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

這是從哪裡來的?

即使 aTICKET_PRICE為 0,我也能得到這種差異。煤氣這麼貴?


契約:

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

}

每個狀態變化的交易都會導致費用通知 gas,您可以在呼叫合約函式時指定較低的 gas 量,但請記住,如果您將費用設置得太低,您的交易將被拒絕。

是的,這是意料之中的。由於您正在呼叫導致狀態更改(區塊鏈交易)的函式,這就是預設使用者的原因,即帳戶

$$ 0 $$為執行交易而損失gas,最終gas支出導致餘額損失。 查看此答案以了解有關 Gas 以及如何計算交易費用的更多資訊。

引用自:https://ethereum.stackexchange.com/questions/19222