Anruf mit Vertragsinstanz im Vergleich zu Anruf mit gehashter Methoden-ID

Soweit ich weiß, gibt es zwei Möglichkeiten, eine Funktion in einem anderen Vertrag aufzurufen.

1.) Verwendung der 4-Byte-Methoden-ID ----> address.call(bytes4(sha3('foo()'))

2.) Verwendung der Vertrags-ABI ---> contractInstance.foo()

Ich habe mich gefragt, ob jemand erklären könnte, warum ein Anruf mit der bytes4-Methoden-ID nur einen Gasmangel anzeigen kann, während ein Anruf mit dem ABI tatsächliche Werte zurückgeben kann. Ich vermute, es hat etwas mit dem ABI zu tun, aber ich würde gerne verstehen, was hier unter der Haube vor sich geht. Vielen Dank.

Antworten (1)

Ich bin mir nicht sicher, was Sie meinen, wenn Sie die Vertrags-ABI innerhalb eines Vertrags verwenden. Ich denke, Sie meinen, wenn wir einen Vertrag in einen anderen Vertrag importieren und auf eine Instanz davon zugreifen, indem wir einen Verweis darauf erstellen, z contractInstance = externalContract(contractAddress).

Letztendlich gibt es Rückgabewerte, wenn wir einen Vertrag importiert haben, weil wir bei der Kompilierung wissen, welche Art und Größe von Daten jeder Funktionsaufruf zurückgeben wird. Wir können dann die Rückgabedaten in den richtigen Variablentyp einfügen. Wenn wir jedoch eine Funktion direkt auf einer Adresse aufrufen, wissen wir nicht, welche Art und Größe die Rückgabewerte haben, da diese Details nicht in der Blockchain gespeichert werden. Die Funktion gibt nur Rohdaten zurück. Das bedeutet, dass wir nicht wissen, in welcher Art von Variable der Rückgabewert nach dem Aufruf dieser Funktion gespeichert werden soll, also ist es einfach nicht erlaubt.

Als Randnotiz können Sie seit dem Byzantium-Fork tatsächlich Rückgabewerte erhalten, address.call()wenn Sie einige Assembler-Anweisungen direkt danach ausführen. Insbesondere die returndatacopy()Anweisung, die im Dokument zu sehen ist . Und eine Beispielverwendung ist in einem aktualisierbaren Proxy-Vertrag zu sehen, den ich geschrieben habe (Beachten Sie, dass das Beispiel den Delegiertenruf verwendet, sich aber genauso verhalten sollte wie die Verwendung von Anruf). Dieser Ansatz gibt immer noch nur Rohdaten zurück und erstellt keine Art von Variable, in der sie leben können.

Ok das war super danke. Können Sie erklären, was eine Vertrags-"Instanz" unter der Haube ausmacht? Ist es der Bytecode?
Außerdem grabe ich dein solidity-playground repo aus :-)
Ich bin froh! Vielleicht kann es nützlich sein! Zur Vertragsinstanz. Im Kontext von Solidity ist es nur eine High-Level-Darstellung von etwas, das letztendlich, wie Sie vorgeschlagen haben, in Bytecode kompiliert/konvertiert wird. Wenn der Compiler während der Kompilierung eine Zeile erreicht, die einen anderen Vertrag aufruft, wechselt er zu der Datei, die in der import-Anweisung angegeben ist, die diesen Vertrag darstellt, und prüft, ob alle Typen (von Argumenten und Rückgabewerten) mit denen identisch sind, die aufgerufen werden. Es wird einen Fehler auslösen, wenn dies nicht der Fall ist, oder es gibt ein Kompatibilitätsproblem, andernfalls wird es für die Bereitstellung in Bytecode konvertiert.