Кодирование/декодирование контрактных данных ABI

Как кодировать и декодировать данные ABI?

Может ли кто-нибудь показать мне пример с библиотекой web3js?

Вы про декодирование ввода и вывода вызова контракта? Ое сам договор? Если первое, то почему? web3 предоставит вам методы-заглушки, которые позволят вам вызывать контрактные методы без необходимости делать это самостоятельно.

Ответы (7)

Если вопрос касается параметров abi, вы можете взглянуть на эти два файла web3.js:

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

Хотя эти функции не являются частью публичного web3.jsинтерфейса. В основном потому, что им нужен правильный рефакторинг.

Существует также инструмент командной строки, созданный специально для кодирования вызовов функций и извлечения выходных данных.

https://github.com/ethcore/этаби

Есть альтернативный JS-инструмент, который должен быть готов через пару дней: github.com/jacogr/ethabi-js .

Если вам нужен онлайн-инструмент для кодирования параметров в формат abi, вы можете использовать https://abi.hashex.org/ . Он имеет функциональные возможности для автоматического анализа abi контракта для получения имен функций и типов параметров и предоставляет удобный способ ввода их значений.

Вот пример использования этого сервисавведите описание изображения здесь

веб3 1.0:

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

вы должны получить:0x1829D79cCE6aA43D13E67216b355E81A7FfFB220

Вы также можете попробовать:

https://github.com/ConsenSys/аби-декодер

https://github.com/ethereumjs/ethereumjs-аби

Я изменил библиотеку web3 npm, включив следующую строку

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

после создания объекта Web3.

На стороне клиента вы можете использовать его со следующим кодом.

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

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

Это, конечно, хак и подходит для быстрого тестирования, если бы это был рекомендуемый подход, я мог бы внести изменения в официальную библиотеку web3. Я проверю у них.

Обновление: в web3.js доступен метод getData(), который вы можете использовать для этой цели. Вот ссылка на документацию: https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-methods

Самый простой способ — использовать « аби-декодер ». Я разветвил репозиторий и создал index.html для удобства использования.

Вы можете загрузить и использовать его с: https://github.com/Muhammad-Altabba/abi-decoder (позже вы можете проверить его на https://github.com/ConsenSys/abi-decoder , как только они примут мой запрос на включение )

Чтобы загрузить и запустить с помощью NPM:

npm install abi-decoder
bower install abi-decoder

Затем загрузите https://github.com/Muhammad-Altabba/abi-decoder/index.html в тот же каталог. Затем откройте файл «index.html» в браузере.

Ты получишь:

введите описание изображения здесь

Если вы имеете в виду данные для отправки сообщения, простой способ — закодировать их так:

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

Это payloadименно то, что вы хотите.

Документация по языку солидности имеет формальное объяснение: https://docs.soliditylang.org/en/v0.4.24/abi-spec.html#argument-encoding

TL;DR заключается в том, что первые 4 байта являются сигнатурой функции. Аргументы разбиваются на куски по 32 байта, затем все это объединяется вместе.

Например, возьмем функцию

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

Если бы мы хотели вызвать baz с параметрами 69 и true, мы бы передали всего 68 байт, которые можно разбить на:

0xcdcd77c0: идентификатор метода. Это получается как первые 4 байта хэша Keccak формы ASCII подписи baz(uint32,bool).

0x0000000000000000000000000000000000000000000000000000000000000045: первый параметр, значение uint32 69, дополненное до 32 байт.

0x0000000000000000000000000000000000000000000000000000000000000001: второй параметр - boolean true, дополненный до 32 байт

В целом:0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001

Для динамических аргументов вы кодируете их как их расположение в большом двоичном объекте calldata. Например:

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

Если бы мы хотели вызвать sam с аргументами «dave», true и [1,2,3], мы бы передали всего 292 байта, разбитых на:

0xa5643bf2: идентификатор метода. Это происходит от сигнатуры sam(bytes,bool,uint256[]). Обратите внимание, что uint заменяется его каноническим представлением uint256.

`0x000000000000000000000000000000000000000000000000000000000000000060: расположение части данных первого параметра (динамического типа), измеренное в байтах от начала блока аргументов. В данном случае 0x60.

0x0000000000000000000000000000000000000000000000000000000000000001: второй параметр: boolean true.

0x00000000000000000000000000000000000000000000000000000000000000a0: расположение части данных третьего параметра (динамического типа), измеренное в байтах. В этом случае 0xa0.

0x0000000000000000000000000000000000000000000000000000000000000004: часть данных первого аргумента, она начинается с длины массива байтов в элементах, в данном случае 4. 0x6461766500000000000000000000000000000000000000000000000000000000: содержимое первого аргумента: кодировка UTF-8 (в данном случае равна ASCII) " dave", дополненный справа до 32 байт.

0x0000000000000000000000000000000000000000000000000000000000000003: часть данных третьего аргумента, она начинается с длины массива в элементах, в данном случае 3.

0x0000000000000000000000000000000000000000000000000000000000000001: первая запись третьего параметра.

0x0000000000000000000000000000000000000000000000000000000000000002: вторая запись третьего параметра.

0x0000000000000000000000000000000000000000000000000000000000000003: третья запись третьего параметра.

В целом:0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003