Was bedeutet die "Call"-Funktion von Solidity?

address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2;
nameReg.call("register", "MyName"); //1
nameReg.call(bytes4(sha3("fun(uint256)")), a); //2
if(!nameReg.call.value(10)){throw;} //3

Hier heißt es,

Darüber hinaus wird als Schnittstelle zu Verträgen, die nicht der ABI entsprechen, der Funktionsaufruf bereitgestellt, der eine beliebige Anzahl von Argumenten beliebigen Typs entgegennimmt. Diese Argumente werden auf 32 Bytes aufgefüllt und verkettet. Eine Ausnahme ist der Fall, wo das erste Argument auf genau vier Bytes codiert ist. In diesem Fall wird es nicht aufgefüllt, um hier die Verwendung von Funktionssignaturen zu ermöglichen.

  • Sind 1 und 2 legal?
  • Bedeutet das, dass 2 illegal ist?
  • Was bedeutet die 3?

Antworten (1)

Solidity callist eine Low-Level-Schnittstelle zum Senden einer Nachricht an einen Vertrag. Er gibt zurück false, wenn der Unteraufruf auf eine Ausnahme trifft, andernfalls gibt er zurück true. Es gibt keine Vorstellung von einem legalen Anruf, wenn es kompiliert wird, ist es gültige Solidität.

  1. nameReg.call("register", "MyName")ist eine Nachricht, die bestimmte Bytes an nameReg übergibt. Informationen zu den Bytes finden Sie unter: Aufrufe im Stil von nameReg.call("register", "MyName") zwischen Verträgen verstehen

  2. nameReg.call(bytes4(sha3("fun(uint256)")), a)ist eine Nachricht, die eine Funktion namens funaufruft (wenn nameReg sich an die ABI hält) und ihr die rohen, nicht aufgefüllten Daten übergibt a(Sie müssen zuerst korrekt auf 32 Bytes auffüllen, wenn Sie möchten, dass das Verhalten mit der ABIa übereinstimmt . Für die Verwendung von left-padding. ).uint256

Für 3 contract.call.value(...)(...)ist eine Möglichkeit, Ether hinzuzufügen, wenn ein Vertrag aufgerufen wird. if(!nameReg.call.value(10)()){throw;}ist ein Beispiel für die Behandlung des Fehlerfalls des Unterrufs. Beachten Sie die zusätzlichen Klammern value(10)(), die die Fallback-Funktion aufrufen.

callist eine Low-Level-Schnittstelle, und es ist einfacher, eine Funktion direkt aufzurufen, als nameReg.fun(a)im zweiten Beispiel. Der direkte Aufruf ist auch typsicher und ermöglicht die funVerwendung des Rückgabewerts von.

Beachten Sie, dass im Fall von 1 "register"und "MyName"auf 32 Bytes aufgefüllt werden, während in 2 adirekt auf die 4-Bytes verkettet wirdbytes4(sha3("fun(uint256)"))
@eth, meinst du damit, dass der vom Vertrag zurückgegebene Wert ignoriert wird?
@ user2284570 Ja, Solidity callgibt den Rückgabewert einer Vertragsfunktion nicht zurück: Es gibt nur zurück, ob die Funktion auf eine Ausnahme gestoßen ist oder nicht.
So wie ich es verstehe, (bool success, bool returnBytes) = addr.call{...}(abi.encodeWithSignature(...), ...)ist die neue empfohlene Methode, (1) Funktionen aufzurufen, ohne zu werfen, wenn die Funktion nicht aufgerufen werden kann, und (2) Zahlungen an kostenpflichtige Funktionen zu senden. Ich bin mir also ziemlich sicher, dass Chriseths Kommentar callnur für die älteren Versionen gilt.
@LukeHutchison Denke, du hast Recht, wurde positiv bewertet und der Chriseth-Kommentar entfernt. Ich bin mir nicht sicher, wie viel ich den Rest dieser Antwort bearbeiten soll. Fühlen Sie sich frei, eine 2. Antwort zu schreiben, die viel aktueller ist :)