Nicht deterministische Gasverwendung derselben Funktion

Umfeld

Truffle v4.1.8 node 10.0.0 pragma solidity ^0.4.21;

Ausgabe

Ich rufe die claimRefundFunktion in meinem Smart Contract mit Metamask auf. Beim Aufruf der Funktion mit 37081 Gaslimit bei 20 gwei Gaspreis gibt die Transaktion 36924 Gas aus und wird mit EVM Revert rückgängig gemacht.

Wenn ich die Parameter auf 58080 Gaslimit bei einem Gaspreis von 20 gwei ändere, wird die Transaktion bestanden und 24721 Gas ausgegeben.

Der Code ist unten gezeigt:

   /**
   * @param investor Investor address
   */
  function refund(address investor) public {
    require(state == State.Refunding);
    uint256 depositedValue = deposited[investor];
    deposited[investor] = 0;
    investor.transfer(depositedValue);
    emit Refunded(investor, depositedValue);
  }
  }


  function claimRefund() public {
    require(isFinalized);
    require(!goalReached());

    vault.refund(msg.sender);
  }

Frage

Wie ist es möglich, dass derselbe Anruf zu unterschiedlichen Gasausgaben führt? Außerdem, wie kann eine Funktion versagen, nachdem sie mehr Gas verbraucht hat, und bestanden werden, nachdem sie weniger Gas verbraucht hat?

Das Anzeigen des Codes für goalReached()würde auch helfen.
Testen Sie gegen Ganache oder ein anderes Testnetz wie Ropsten? Welche Version des Compilers verwendest du? Es gab einen Fehler in solc, der ein seltsames Verhalten bei der Schätzung des Gasverbrauchs verursachte github.com/ethereum/solidity/issues/3687 und hier reddit.com/r/ethdev/comments/82p78k/… .

Antworten (1)

Das Problem ist, dass die Menge an Gas, die Sie liefern müssen, manchmal größer ist als die Menge, die tatsächlich abgezogen wird.

Dies geschieht, weil beim Löschen des Speichers, wie beim Löschen des Guthabens aus deposited[investor], eine Gasrückerstattung erfolgt, die von Ihrem insgesamt abgezogenen Gas abgezogen wird. Diese Rückerstattung wird jedoch erst am Ende der Transaktion gutgeschrieben und kann daher nicht zur Bezahlung der darauf folgenden Schritte verwendet werden, in diesem Fall Ihres transferAnrufs und Ihrer RefundedVeranstaltung.