Ich schreibe einen Test für einen Lotterievertrag:
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());
});
});
});
});
Wie Sie sehen, überprüfe ich den Kontostand vor und nach Vertragsabschluss. Die console.log gibt mir so etwas:
97.0711255 97.0326134
Dies ist ein Unterschied von0.0385121 ETH
Wo kommt das her?
Auch bei a TICKET_PRICE
von 0 bekomme ich diesen Unterschied. Ist das Benzin so teuer?
Der Vertrag:
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);
}
}
}
Jede zustandswechselnde Transaktion verursacht Gaskosten, Sie können beim Aufruf der Vertragsfunktion eine niedrigere Gasmenge angeben, aber denken Sie daran, dass Ihre Transaktion abgelehnt wird, wenn Sie eine zu niedrige Gebühr festlegen.
Ja, das wird erwartet. Da Sie die Funktionen aufrufen, die eine Zustandsänderung (Blockchain-Transaktionen) verursachen, und das ist der Grund, warum der Standardbenutzer, dh Konten [0], Gas verliert, um die Transaktion auszuführen, und schließlich führt der Gasverbrauch zu einem Kontoverlust.
Überprüfen Sie diese Antwort , um mehr über Gas und die Berechnung der Transaktionsgebühr zu erfahren.
Fabian Lürz
Tjaden Hess