2

I've got an app that takes various kinds of input via an HTML form, but always ends up sending it to a contract as bytes32. The expectation is that another contract that ultimately consumes the data will cast it into the type that it's expecting, which may be bytes32, uint256 or int256.

For unsigned integers I'm taking a BigNumber object, calling toString(16) on it to get hex, then left-padding it to 64 digits, and appending 0x. But for signed integers, which may be negative, I presumably need to handle the two's complement system; What's the appropriate way to do this?

1
  • 1
    BN.js (a dependency of web3 v1.0) has two methods toTwos and fromTwos that can be used to get the two's complement to an arbitrary length. – Ismael Sep 25 '17 at 4:56
4

Using BN.js as suggested by @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;
}
0

This code works for me:

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
};

```

0

Using only BN.js

let num = -1234;
let bytes32 = "0x"+(new BN(String(num))).toTwos(256).toString('hex',64);

Using web3.js

let num = -1234;
let bytes32 = web3.eth.abi.encodeParameter('int256', String(num));

This is working in smart-contract like this:

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;
    }
}
1
  • Welcome to the Ethereum Stack Exchange! Can you please edit your answer and add a bit more? Did you try with a negative number as the question asks? – eth May 5 '20 at 9:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.