Wie werden ABI-Daten codiert und decodiert?
Kann mir jemand ein Beispiel mit der web3js-Bibliothek zeigen?
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.js
Schnittstelle 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.
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.
web3 1.0:
web3.eth.abi.decodeParameter('address', '0000000000000000000000001829d79cce6aa43d13e67216b355e81a7fffb220')
Du solltest erhalten:0x1829D79cCE6aA43D13E67216b355E81A7FfFB220
Sie können auch versuchen:
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:
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 payload
ist 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 BytesIn 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 Fall0xa0
.
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
Nick Johnson