4

The documentation says that sha3 calculates the hash of the tightly packed arguments. Numbers seem to be converted to ASCII chars.

Consider using sha3(values) in Solidity with the type int8[3] values, and the Javascript array let values = [-1, 0, 1];, how can I calculate the web3.sha3(...) hash in Javascript to get the same result as in Solidity?

What I tried so far:

web3.sha3(values.map((x) => String.fromCharCode(x)).join(''))

Also, why are these two different:

> sha3([int8(-1), int8(0), int8(1)])
0x485d3017777c5ed1be9073116ba54b48f208c386ab83497d9c3a015a8382849e
> sha3(int8(-1), int8(0), int8(1))
0x8404dcb0a81bbb8eccbf96f10e1874b12380080d2143c02c8e44db200aaff384

I found this issue on Github, which doesn't seem to handle my case of negative numbers. Maybe I should convert to uint in Javascript?

2 Answers 2

4

I finally found the solution.

The function given in this issue was the starting point. To make it work with negative numbers, I had to change it to this:

function solSha3 (...args) {
    args = args.map(arg => {
        if (typeof arg === 'string') {
            if (arg.substring(0, 2) === '0x') {
                return arg.slice(2);
            } else {
                return web3.toHex(arg).slice(2);
            }
        }

        if (typeof arg === 'number') {
            if (arg < 0) {
              return leftPad((arg >>> 0).toString(16), 64, 'F');
            }
            return leftPad((arg).toString(16), 64, 0);
        } else {
          return '';
        }
    });

    args = args.join('');

    return '0x' + web3.sha3(args, { encoding: 'hex' });
}
1
  • Thanks, really helped. Update: web3.sha3 to web3.utils.sha3
    – Senju
    Jun 17, 2019 at 15:42
0

if you can to specify the types of the values you're on the safe side

given the solidity function

    function getHash(
        bytes32 bidID,
        uint256 date,
        int256[] volumes_Wh,
        uint256[] prices_mCent) public view returns (bytes32) {
        return keccak256(abi.encodePacked(bidID, date, volumes_Wh, prices_mCent));
    }
  async function hashIt () => {
    const bid = {
       bidID: (() => {
         let s = ''
         const bytes = randombytes(32)
         for (let i = 0; i < 32; i++) {
           s += ('0' + (bytes[i] & 0xFF).toString(16)).slice(-2)
         }
         return s
       })(),
       date: (new Date()).getTime(),
       volumes_Wh: [111, 222, 333, 444, 555],
       prices_mCent: [111, 222, 333, 444, 555]
     }
    console.log(await bids.getHash(`0x${bid.bidID}`, bid.date, bid.volumes_Wh, bid.prices_mCent))
    console.log(web3.utils.soliditySha3(
      {t: "bytes32", v: `0x${bid.bidID}`},
      {t: "uint256", v: bid.date},
      ... bid.volumes_Wh.map(vol => ({t: "int256", v: vol})),
      ... bid.prices_mCent.map(price => ({t: "uint256", v: price}))
    ).toString('hex'))
    assert.equal(true, true)
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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