Ich erhalte die Meldung „Gasschätzung fehlerhaft mit der folgenden Meldung (siehe unten). Die Ausführung der Transaktion wird wahrscheinlich fehlschlagen. Möchten Sie das Senden erzwingen? Interner JSON-RPC-Fehler.“ im Remix, während Sie die drawWinner-Funktion verwenden
pragma solidity ^0.4.18;
contract RecurringLottery {
struct Round {
uint deployBlock;
uint endBlock;
uint drawBlock;
Entry[] entries;
uint totalQuantity;
address winner;
}
struct Entry {
address buyer;
uint quantity;
}
uint constant public TICKET_PRICE = 1e15;
mapping(uint => Round) public rounds;
uint public round;
uint public duration;
mapping (address => uint) public balances;
// duration is in blocks. 1 day = ~5500 blocks
function RecurringLottery (uint _duration) public {
round = 1;
duration = _duration;
rounds[round].deployBlock = block.number;
rounds[round].endBlock = block.number + duration;
rounds[round].drawBlock = block.number + duration + 5;
}
function buy () payable public {
require(msg.value % TICKET_PRICE == 0);
if (block.number > rounds[round].endBlock) {
round += 1;
rounds[round].deployBlock = block.number;
rounds[round].endBlock = block.number + duration;
rounds[round].drawBlock = block.number + duration + 5;
}
uint quantity = msg.value / TICKET_PRICE;
Entry memory entry = Entry(msg.sender, quantity);
rounds[round].entries.push(entry);
rounds[round].totalQuantity += quantity;
}
function drawWinner (uint roundNumber) public {
Round storage drawing = rounds[roundNumber];
require(drawing.winner == address(0));
require(block.number > drawing.drawBlock);
require(drawing.entries.length > 0);
// pick winner
bytes32 rand = keccak256(
block.blockhash(drawing.drawBlock)
);
uint counter = uint(rand) % drawing.totalQuantity;
for (uint i=0; i < drawing.entries.length; i++) {
uint quantity = drawing.entries[i].quantity;
if (quantity > counter) {
drawing.winner = drawing.entries[i].buyer;
break;
}
else
counter -= quantity;
}
balances[drawing.winner] += TICKET_PRICE * drawing.totalQuantity;
}
function withdraw () public {
uint amount = balances[msg.sender];
balances[msg.sender] = 0;
msg.sender.transfer(amount);
}
function deleteRound (uint _round) public {
require(block.number > rounds[_round].drawBlock + 100);
require(rounds[_round].winner != address(0));
delete rounds[_round];
}
function () payable public {
buy();
}
}
Normalerweise erhalten Sie diesen Fehler, wenn die Codeausführung fehlschlägt. Dies kann an der regulären Ausführung liegen oder daran, dass einer der Reverts einen Fehler abfängt. In Ihrem Fall waren die Reverts ein Problem. Hier erfahren Sie, wie Sie dies herausfinden können:
Diese Funktion ist noch nicht auf Knoten, nur in javascriptVM, die Sie im Remix oder in Ihren Truffle-Tests/Ganache verwenden können, aber es wird empfohlen, dass Sie jetzt damit beginnen; Sie können Ihren Reverts eine Fehlermeldung hinzufügen, dies ist der einfachste Weg, um umfassendere Fehler zu erhalten, IE:
require(condition, "string returned if condition fails");
Beachten Sie, dass ich für dieses Beispiel Javascript vm anstelle von injiziertem web3 verwende. Wenn ich Ihren Code ausführe, ist der erste Fehler, den wir finden können, in der zweiten Anforderung:
require(block.number > drawing.drawBlock, "Can't draw yet");
Wir können nicht zeichnen, bis einige Blöcke vergangen sind. Ich habe die Generierung einiger Blöcke in der VM erzwungen, indem ich andere Funktionen aufgerufen habe. Wenn Sie dies auf Ethereum tun, müssen Sie nur warten.
Nach der Lösung dieses Problems stürzte es in der nächsten Zeile ab:
require(drawing.entries.length > 0, "No entries for that round");
Also habe ich buy() ein paar Mal aufgerufen, indem ich die in TICKET_PRICE angegebene Menge an Ether gesendet habe, dann habe ich überprüft, ob die Einträge hinzugefügt wurden, indem ich rounds(numberOfRound) aufgerufen habe, und nachdem drawWinner(numberOfRound) mit einer gültigen Runde aufgerufen wurde, funktionierte die Funktion korrekt .
Sie sollten einen Anruf erstellen, der Ihnen mitteilt, ob diese Funktion funktioniert oder fehlschlägt, indem Sie diese Bedingungen überprüfen. Auf diese Weise können Sie eine Menge Kopfschmerzen lösen, daran denken, Fehlermeldungen auf Anforderung zu setzen, und wenn Sie alles Schritt für Schritt sehen möchten Schritt, der in Remix bereitgestellte Debugger ist ziemlich nützlich.
TLDR: Damit Ihr Code funktioniert, müssen Sie sicherstellen, dass genügend Blöcke passiert sind und dass die Runde mindestens einen Eintrag hat.
Übrigens gibt es ein paar Schwachstellen in Ihrer Funktion drawWinner(), verwenden Sie sie nicht in der Produktion!
Ich habe Ihren Code auf Remix ausgeführt, alles ist in Ordnung. Vielleicht haben Sie vergessen, die passende Compiler-Version auszuwählen.
0.4.25+commit.59dbf8f1
Das war meins! Ich hoffe es hilft.
In meinem Fall musste ich von Solc-Version 0.8.7 auf 0.8.0 wechseln und es funktioniert.
Sie erhalten einen Gasschätzungsfehler, das bedeutet:
Nguyễn Thái Phương
seineHarshad
assert()
oderrevert()
Bedingung falsch zurückgegeben wird. Daher wurde die Transaktion abgebaut , aber die Ausführung ist fehlgeschlagen.Nguyễn Thái Phương
seineHarshad
require(drawing.winner == address(0));
in diese Zeile:require(drawing.winner != address(0));
in derdrawWinner()
Funktion zu ändern.Nguyễn Thái Phương
seineHarshad
rounds[round].drawBlock = block.number + duration + 5;