Fehlerhafte Gasschätzung mit folgender Meldung

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

}

Antworten (5)

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!

Bei der Verwendung der REMIX-IDE musste ich darauf achten, dass ich den Wert auf den TICKET_PRICE setze. Siehe Bild, wo es einzustellen ist.

Geben Sie hier die Bildbeschreibung ein

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.

Vielen Dank, aber ich habe immer noch diesen Fehler "Transaktion abgebaut, aber Ausführung fehlgeschlagen" mit der DrawWinner-Funktion
Dies geschieht, wenn eine Ihrer assert()oder revert()Bedingung falsch zurückgegeben wird. Daher wurde die Transaktion abgebaut , aber die Ausführung ist fehlgeschlagen.
wie kann ich es reparieren ?
Versuchen Sie, diese Zeile: require(drawing.winner == address(0));in diese Zeile: require(drawing.winner != address(0));in der drawWinner()Funktion zu ändern.
immer noch der gleiche Fehler :((
Sie müssen warten, bis die von Ihnen erwähnte Blockgröße + 5 erreicht ist, wie Sie erwähnt haben:rounds[round].drawBlock = block.number + duration + 5;

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:

  1. Sie haben nicht genug ETH, um diese Transaktion durchzuführen
  • Wenn dies der Fall ist, besorgen Sie sich mehr ETH
  1. Sie haben nicht genügend ERC20-Token, um diese Transaktion durchzuführen (wie LINK, DAI usw.)
  • Wenn dies der Fall ist, besorgen Sie sich mehr ERC20-Token oder finanzieren Sie Ihren Vertrag mit LINK.
  1. Sie haben ein anderes Problem mit Ihrem Logikbruch.
  • Wenn dies der Fall ist, aktualisieren Sie bitte die Frage mit Kommentaren.