ABI-Daten des Verschlüsselungs-/Decodierungsvertrags

Wie werden ABI-Daten codiert und decodiert?

Kann mir jemand ein Beispiel mit der web3js-Bibliothek zeigen?

Sprechen Sie über die Dekodierung der Ein- und Ausgabe eines Aufrufs zu einem Vertrag? Oder der Vertrag selbst? Wenn ersteres, warum? web3 stellt Ihnen Stub-Methoden zur Verfügung, mit denen Sie Vertragsmethoden aufrufen können, ohne dies selbst tun zu müssen.

Antworten (7)

Wenn es um abi-Parameter geht, können Sie sich diese beiden web3.js-Dateien ansehen:

https://github.com/ChainSafe/web3.js/blob/0.20.7/test/coder.encodeParam.js https://github.com/ChainSafe/web3.js/blob/0.20.7/test/coder .decodeParam.js

Obwohl diese Funktionen nicht Teil der öffentlichen web3.jsSchnittstelle sind. Hauptsächlich, weil sie einen geeigneten Refactor benötigen.

Es gibt auch ein Befehlszeilentool, das speziell zum Codieren von Funktionsaufrufen und zum Abrufen von Ausgabedaten erstellt wurde.

https://github.com/ethcore/ethabi

Es gibt ein alternatives JS-Tool, das in wenigen Tagen fertig sein sollte: github.com/jacogr/ethabi-js

Falls Sie ein Online-Tool zum Codieren von Parametern im abi-Format benötigen, können Sie https://abi.hashex.org/ verwenden . Es verfügt über eine Funktion zum automatischen Analysieren von Vertrags-Abi, um Funktionsnamen und Parametertypen zu erhalten, und bietet eine bequeme Möglichkeit, ihre Werte einzugeben.

Hier ist ein Beispiel für die Verwendung dieses DienstesGeben Sie hier die Bildbeschreibung ein

web3 1.0:

web3.eth.abi.decodeParameter('address', '0000000000000000000000001829d79cce6aa43d13e67216b355e81a7fffb220')

Du solltest erhalten:0x1829D79cCE6aA43D13E67216b355E81A7FfFB220

Sie können auch versuchen:

https://github.com/ConsenSys/abi-decoder

https://github.com/ethereumjs/ethereumjs-abi

Ich habe die web3-npm-Bibliothek geändert, indem ich die folgende Zeile eingefügt habe

Web3.SolidityCoder = require('./lib/solidity/coder');

nachdem das Web3-Objekt erstellt wurde.

Auf der Clientseite können Sie es mit folgendem Code verwenden.

web3 = require('web3'); // This will import the web3 library.

web3.SolidityCoder.encodeParams([types array], [values array])
web3.SolidityCoder.decodeParams([types array], encodedData)

Dies ist natürlich ein Hack und eignet sich zum schnellen Testen. Wenn dies ein empfohlener Ansatz wäre, könnte ich Änderungen an die offizielle web3-Bibliothek übertragen. Ich werde mich bei ihnen erkundigen.

Update: In web3.js ist eine getData()-Methode verfügbar, die Sie für diesen Zweck verwenden können. Hier ist der Link zur Dokumentation: https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-methods

Der einfachste Weg ist die Verwendung von " abi-decoder ". Ich habe das Repository gegabelt und index.html für eine einfache Verwendung erstellt.

Sie können es herunterladen und verwenden von: https://github.com/Muhammad-Altabba/abi-decoder (Sie können es später unter https://github.com/ConsenSys/abi-decoder überprüfen, sobald sie meine Pull-Anforderung akzeptieren )

So laden Sie NPM herunter und führen es aus:

npm install abi-decoder
bower install abi-decoder

Laden Sie dann https://github.com/Muhammad-Altabba/abi-decoder/index.html in dasselbe Verzeichnis herunter . Öffnen Sie dann die Datei "index.html" im Browser.

Sie erhalten:

Geben Sie hier die Bildbeschreibung ein

Wenn Sie die Daten zum Senden einer Nachricht meinen, können Sie sie einfach so codieren:

contract = web3.eth.contract(abi).at(cAddr);
payload = contract['transfer'].getData(to, amont);

Das payloadist genau das, was Sie wollen.

Die Solidity-Sprachdokumentation enthält die formale Erklärung: https://docs.soliditylang.org/en/v0.4.24/abi-spec.html#argument-encoding

Die TL; DR ist, dass die ersten 4 Bytes die Funktionssignatur sind. Argumente werden in 32-Byte-Blöcke aufgeteilt, dann wird alles miteinander verkettet.

Nehmen Sie zum Beispiel die Funktion

function bar(bytes3[2]) public pure {}

Wenn wir baz mit den Parametern 69 und true aufrufen wollten, würden wir insgesamt 68 Bytes übergeben, die sich aufteilen lassen in:

0xcdcd77c0: die Methoden-ID. Dieser wird als die ersten 4 Bytes des Keccak-Hashes aus der ASCII-Form der Signatur baz(uint32,bool) abgeleitet.

0x0000000000000000000000000000000000000000000000000000000000000045: der erste Parameter, ein uint32-Wert 69 aufgefüllt auf 32 Bytes

0x0000000000000000000000000000000000000000000000000000000000000001: der zweite Parameter - Boolean True, aufgefüllt auf 32 Bytes

In Summe:0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001

Für dynamische Argumente codieren Sie sie als ihre Position im Anrufdaten-Blob. Zum Beispiel:

function sam(bytes, bool, uint[]) public pure {}

Wenn wir sam mit den Argumenten "dave", true und [1,2,3] aufrufen wollten, würden wir insgesamt 292 Bytes übergeben, aufgeteilt in:

0xa5643bf2: die Methoden-ID. Dies wird von der Signatur sam(bytes,bool,uint256[]) abgeleitet. Beachten Sie, dass uint durch seine kanonische Darstellung uint256 ersetzt wird.

`0x0000000000000000000000000000000000000000000000000000000000060: die Position des Datenteils des ersten Parameters (dynamischer Typ), gemessen in Bytes vom Beginn des Argumentblocks. In diesem Fall 0x60.

0x0000000000000000000000000000000000000000000000000000000000000001: der zweite Parameter: boolean wahr.

0x00000000000000000000000000000000000000000000000000000000000000a0: die Position des Datenteils des dritten Parameters (dynamischer Typ), gemessen in Bytes. In diesem Fall 0xa0.

0x0000000000000000000000000000000000000000000000000000000000000004: der Datenteil des ersten Arguments, er beginnt mit der Länge des Byte-Arrays in Elementen, in diesem Fall 4. 0x6461766500000000000000000000000000000000000000000000000000000000: der Inhalt des ersten Arguments: die UTF-8-Kodierung (in diesem Fall gleich ASCII) von " dave", rechts auf 32 Byte aufgefüllt.

0x0000000000000000000000000000000000000000000000000000000000000003: der Datenteil des dritten Arguments, er beginnt mit der Länge des Arrays in Elementen, in diesem Fall 3.

0x0000000000000000000000000000000000000000000000000000000000000001: der erste Eintrag des dritten Parameters.

0x0000000000000000000000000000000000000000000000000000000000000002: der zweite Eintrag des dritten Parameters.

0x0000000000000000000000000000000000000000000000000000000000000003: der dritte Eintrag des dritten Parameters.

In Summe:0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003