Solidity
為什麼執行合約後我的賬戶餘額如此不同?
我正在為彩票契約編寫測試:
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
這是從哪裡來的?
即使 a
TICKET_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 以及如何計算交易費用的更多資訊。