Tengo una aplicación que acepta varios tipos de entrada a través de un formulario HTML, pero siempre termina enviándolo a un contrato como bytes32
. La expectativa es que otro contrato que finalmente consuma los datos los transformará en el tipo que espera, que puede ser bytes32
, uint256
o int256
.
Para enteros sin signo, tomo un BigNumber
objeto, toString(16)
lo llamo para obtener hexadecimal, luego lo relleno a la izquierda a 64 dígitos y agrego 0x
. Pero para los enteros con signo, que pueden ser negativos, presumiblemente necesito manejar el sistema de complemento a dos; ¿Cuál es la forma adecuada de hacer esto?
Usando BN.js como lo sugiere @Ismael:
function numStringToBytes32(num) {
var bn = new BN(num).toTwos(256);
return padToBytes32(bn.toString(16));
}
function bytes32ToNumString(bytes32str) {
bytes32str = bytes32str.replace(/^0x/, '');
var bn = new BN(bytes32str, 16).fromTwos(256);
return bn.toString();
}
function padToBytes32(n) {
while (n.length < 64) {
n = "0" + n;
}
return "0x" + n;
}
Este código funciona para mí:
var utf8 = require('utf8');
function padToBytes32(n) {
while (n.length < 64) {
n = n + "0";
}
return "0x" + n;
}
function fromUtf8(str) {
str = utf8.encode(str);
var hex = "";
for (var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i);
if (code === 0) {
break;
}
var n = code.toString(16);
hex += n.length < 2 ? '0' + n : n;
}
return padToBytes32(hex);
};
// not tested yet...
function toUtf8(hex) {
// Find termination
var str = "";
var i = 0, l = hex.length;
if (hex.substring(0, 2) === '0x') {
i = 2;
}
for (; i < l; i += 2) {
var code = parseInt(hex.substr(i, 2), 16);
if (code === 0) {
break;
}
str += String.fromCharCode(code);
}
return utf8.decode(str);
};
module.exports = {
fromUtf8,
toUtf8
};
```
Usando solo BN.js
let num = -1234;
let bytes32 = "0x"+(new BN(String(num))).toTwos(256).toString('hex',64);
Usando web3.js
let num = -1234;
let bytes32 = web3.eth.abi.encodeParameter('int256', String(num));
Esto está funcionando en un contrato inteligente como este:
pragma solidity ^0.5.0;
contract TestConversion {
int256 val;
function set(bytes32 _val) public {
val = int256(_val);
}
function get() public view returns(int256){
return val;
}
}
ismael
toTwos
quefromTwos
se pueden usar para obtener el complemento a dos en una longitud arbitraria.