Codificación/descodificación de datos ABI del contrato

¿Cómo codificar y decodificar datos ABI?

¿Puede alguien mostrarme un ejemplo con la biblioteca web3js?

¿Estás hablando de decodificar la entrada y salida de una llamada a un contrato? Oe el contrato en sí? Si es lo primero, ¿por qué? web3 le proporcionará métodos de resguardo que le permitirán llamar a métodos de contrato sin tener que hacerlo usted mismo.

Respuestas (7)

Si la pregunta es sobre abi params, puede echar un vistazo a estos dos archivos 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

Aunque estas funciones no forman parte de la web3.jsinterfaz pública. Principalmente porque necesitan un refactor adecuado.

También hay una herramienta de línea de comandos creada especialmente para codificar llamadas a funciones y recuperar datos de salida.

https://github.com/ethcore/ethabi

Existe una herramienta JS alternativa, que debería estar lista en un par de días: github.com/jacogr/ethabi-js

En caso de que necesite una herramienta en línea para codificar parámetros en formato abi, puede usar https://abi.hashex.org/ . Tiene funcionalidad para analizar automáticamente el abi del contrato para obtener nombres de funciones y tipos de parámetros y proporciona una manera conveniente de ingresar sus valores.

Aquí hay un ejemplo del uso de este servicio.ingrese la descripción de la imagen aquí

web3 1.0:

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

tu deberías recibir:0x1829D79cCE6aA43D13E67216b355E81A7FfFB220

también puedes probar:

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

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

Modifiqué la biblioteca web3 npm incluyendo la siguiente línea

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

después de que se crea el objeto Web3.

En el lado del cliente, puede usarlo con el siguiente código.

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

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

Esto, por supuesto, es un truco y es adecuado para pruebas rápidas, si este fuera un enfoque recomendado, podría enviar cambios a la biblioteca web3 oficial. Voy a consultar con ellos.

Actualización: hay un método getData() disponible en web3.js que puede usar para este propósito. Aquí está el enlace a la documentación: https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-methods

La forma más fácil es usar " abi-decoder ". Bifurqué el repositorio y creé index.html para facilitar su uso.

Puede descargarlo y usarlo desde: https://github.com/Muhammad-Altabba/abi-decoder (más tarde puede consultarlo en https://github.com/ConsenSys/abi-decoder una vez que acepten mi solicitud de extracción )

Para descargar y ejecutar usando NPM:

npm install abi-decoder
bower install abi-decoder

Luego descargue https://github.com/Muhammad-Altabba/abi-decoder/index.html en el mismo directorio. Luego abra el archivo "index.html" en el navegador.

Conseguirás:

ingrese la descripción de la imagen aquí

Si te refieres a los datos para enviar un mensaje, una forma simple es codificarlos así:

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

Es payloadjusto lo que quieres.

Los documentos del lenguaje de solidez tienen la explicación formal: https://docs.soliditylang.org/en/v0.4.24/abi-spec.html#argument-encoding

El TL; DR es que los primeros 4 bytes son la firma de la función. Los argumentos se dividen en fragmentos de 32 bytes, luego todo esto se concatena.

Por ejemplo, tome la función

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

Si quisiéramos llamar a baz con los parámetros 69 y true, pasaríamos 68 bytes en total, que se pueden descomponer en:

0xcdcd77c0: el ID del método. Esto se deriva como los primeros 4 bytes del hash Keccak de la forma ASCII de la firma baz(uint32,bool).

0x0000000000000000000000000000000000000000000000000000000000000045: el primer parámetro, un valor uint32 69 rellenado a 32 bytes

0x0000000000000000000000000000000000000000000000000000000000000001: el segundo parámetro - booleano verdadero, rellenado a 32 bytes

En total:0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001

Para los argumentos dinámicos , los codifica como su ubicación en el blob de calldata. Por ejemplo:

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

Si quisiéramos llamar a sam con los argumentos "dave", true y [1,2,3], pasaríamos 292 bytes en total, divididos en:

0xa5643bf2: el ID del método. Esto se deriva de la firma sam(bytes,bool,uint256[]). Tenga en cuenta que uint se reemplaza con su representación canónica uint256.

`0x0000000000000000000000000000000000000000000000000000000000000060: la ubicación de la parte de datos del primer parámetro (tipo dinámico), medida en bytes desde el inicio del bloque de argumentos. En este caso, 0x60.

0x0000000000000000000000000000000000000000000000000000000000000001: el segundo parámetro: booleano verdadero.

0x00000000000000000000000000000000000000000000000000000000000000a0: la ubicación de la parte de datos del tercer parámetro (tipo dinámico), medida en bytes. En este caso, 0xa0.

0x0000000000000000000000000000000000000000000000000000000000000004: la parte de datos del primer argumento, comienza con la longitud de la matriz de bytes en elementos, en este caso, 4. 0x6461766500000000000000000000000000000000000000000000000000000000: el contenido del primer argumento: la codificación UTF-8 (igual a ASCII en este caso) de " dave", rellenado a la derecha a 32 bytes.

0x0000000000000000000000000000000000000000000000000000000000000003: la parte de datos del tercer argumento, comienza con la longitud de la matriz en elementos, en este caso, 3.

0x0000000000000000000000000000000000000000000000000000000000000001: la primera entrada del tercer parámetro.

0x0000000000000000000000000000000000000000000000000000000000000002: la segunda entrada del tercer parámetro.

0x0000000000000000000000000000000000000000000000000000000000000003: la tercera entrada del tercer parámetro.

En total:0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003