¿Cómo codificar y decodificar datos ABI?
¿Puede alguien mostrarme un ejemplo con la biblioteca web3js?
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.js
interfaz 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.
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.
web3 1.0:
web3.eth.abi.decodeParameter('address', '0000000000000000000000001829d79cce6aa43d13e67216b355e81a7fffb220')
tu deberías recibir:0x1829D79cCE6aA43D13E67216b355E81A7FfFB220
también puedes probar:
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:
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 payload
justo 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 bytesEn 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
nick johnson