Wie mache ich das Äquivalent von Soliditys bytes32 (a_signed_integer) in JavaScript?

Ich habe eine App, die verschiedene Arten von Eingaben über ein HTML-Formular entgegennimmt, sie aber immer als bytes32. Die Erwartung ist, dass ein anderer Vertrag, der die Daten letztendlich verbraucht, sie in den erwarteten Typ umwandelt, der bytes32, uint256oder sein kann int256.

Für Ganzzahlen ohne Vorzeichen nehme ich ein BigNumberObjekt, rufe toString(16)es auf, um Hex zu erhalten, fülle es dann mit der linken Maustaste auf 64 Ziffern auf und hänge 0x. Aber für ganze Zahlen mit Vorzeichen, die negativ sein können, muss ich vermutlich mit dem Zweierkomplementsystem umgehen; Was ist der geeignete Weg, dies zu tun?

BN.js (eine Abhängigkeit von web3 v1.0) verfügt über zwei Methoden toTwos, fromTwosmit denen das Zweierkomplement auf eine beliebige Länge gebracht werden kann.

Antworten (3)

Verwendung von BN.js wie von @Ismael vorgeschlagen:

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

Dieser Code funktioniert bei mir:

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

```

Verwenden Sie nur BN.js

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

Verwenden von web3.js

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

Dies funktioniert im Smart-Contract wie folgt:

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;
    }
}
Willkommen beim Ethereum Stack Exchange! Können Sie bitte Ihre Antwort bearbeiten und ein bisschen mehr hinzufügen? Haben Sie es mit einer negativen Zahl versucht, wie die Frage fragt?