ERC20-Übergabe - Anrufer erwartet Rücksendung, aber keine geliefert - was passiert?

Wenn jemand die ERC20-Funktion transfer() ohne den Rückgabewert wie folgt implementiert:

function transfer(address to, uint256 value) public {
    require( ... usual checks ... );
    balances_[msg.sender] -= value;
    balances_[to] += value;

    emit Transfer(to, value);
}

Aber ein aufrufender Vertrag erwartet den Rückgabewert:

  function transfer(address to, uint256 value) public returns (bool)

und ruft die Funktion irgendwie so auf:

ERC20 token = (ERC20)someaddress;
if (!token.transfer(to,amt)) { ... }

Angenommen someaddress, es ist richtig, was passiert?

Ich stelle mir vor, dass die Übertragungsfunktion ok laufen würde, aber nichts zurückgeben würde, was dazu führen würde, dass der Aufrufer ein false erhält . Die Salden würden aktualisiert und ein Ereignis ausgegeben.

Hab ich recht? Würde der Anruf fehlschlagen? Eine Ausnahme?

Vielen Dank!

Antworten (1)

Das Gelbe Papier gibt die Antwort. Und die Antwort ist, dass das Verhalten undefiniert und unvorhersehbar ist. Der Aufruf wird nicht fehlschlagen, also werden Token übertragen, aber dem Rückgabewert kann nicht vertraut werden und er ist undefiniert (in dem Sinne, dass wir im Allgemeinen nicht vorhersagen können, was er sein wird).

Das zweite Bild unten zeigt, dass der Speicher des Anrufers (der Smart-Vertrag, der den anderen Vertrag anruft) durch diesen Funktionsaufruf nicht aktualisiert wird. Der Aufrufer liest also aus einem Teil seines eigenen Speichers, der Null sein kann, oder irgendetwas anderes, und wertet diesen als booleschen Wert aus, den zurückgegebenen Wert – was bedeutet, dass er falsch ist, wenn der Speicher zuvor nicht deklariert oder auf Null gesetzt wurde , und dass es wahr ist, wenn dieser Teil des Speichers auf einen Wert ungleich Null gesetzt wurde, der Compiler jedoch festgestellt hat, dass dieser Wert ungleich Null nicht mehr benötigt wird.

Definition der Ausgangsdaten

Teil der Definition des CALL-Opcodes
Dieses letzte Bild zeigt einen Teil der Definition des Opcodes CALL. µ[5]gibt den Beginn des Speichers an, in dem das Ergebnis des Aufgerufenen gespeichert wird, µ[6]ist die Ausgabegröße, die der Aufrufer erwartet, und nist in unserem Fall die Größe der Ausgabe des Aufgerufenen, die 0 ist. Also kein Speicher in der aufrufenden VM aktualisiert, sodass der Aufrufer einfach liest, was an der Speicherstelle vorhanden ist µ[5], µ[5]+µ[6]bevor der Aufruf stattfindet, und dies als Rückgabewert interpretiert. Ich glaube, dass dieser Wert in den meisten (allen?) Fällen 0x0 (falsch) sein wird, sodass der Anrufer das Ergebnis des Angerufenen als falsch interpretieren wird.

Ich habe diesen Code nicht ausgeführt, ich habe nur die Antwort abgeleitet. Wenn Sie sicher sein wollen, dass diese Antwort richtig ist, sollten Sie selbst einige Tests durchführen oder hoffen, dass jemand, der klüger ist als ich, antwortet :)