6

How can I get the same resulting hash from Keccak-256 ()in solidity and web3.sha3() in web3?

IN solidity using keccak256( address ) and using web3.sha3 ( address ) gives different results.

In web3 the address field is a string while in solidity it is an address.

How can I convert web3 string to an address type field?

I tried converting the address type field to a string in solidity and I still received different results in hashes.

For address to sting in solidity I used

function toString(address x) returns (string) {
    bytes memory b = new bytes(20);
    for (uint i = 0; i < 20; i++)
        b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
    return string(b);
}
2
  • @RichardHorrocks this isn't a sha3 vs keccak256 issue, it's an input argument encoding issue, so I don't believe that particular question is a proper duplicate
    – carver
    Commented Aug 10, 2017 at 17:41
  • Okay, yep, looks like you're probably right - apologies for jumping the gun. +1 :-) Commented Aug 10, 2017 at 18:14

4 Answers 4

8

web3.sha3() takes an encoding parameter to specify that you are passing in a hex address:

address_string = '0x5b2063246f2191f18f2675cedb8b28102e957458';
web3.sha3(address_string, {encoding: 'hex'});

As a general side-note: you have to pay gas costs to do any custom work in Solidity so, when possible, you are best off working on the javascript side.

3

Also, you can perform keccak256( address ) in a constant solidity function locally, and then pass the result into a transaction. Of course, this is not safe for production, if you let users do that in their browser.

2
  • what's the issue with using this for production? it works.
    – k26dr
    Commented Dec 25, 2017 at 7:34
  • 2
    the resulting hash could be moedified before it gets passed into a transaction. "Don't trust the client" doctrine.
    – n1cK
    Commented Dec 30, 2017 at 8:25
3

The latest version of web3 has a web3.utils.soliditySha3 function you can use that mimics Solidity's hashing:

address = '0x407D73d8a49eeb85D32Cf465507dd71d507100c1';
hash = web3.utils.soliditySha3(address); 
1
  • You cannot hash an address in Solidity 0.5.0 anymore Commented Mar 14, 2020 at 13:48
0

It is often easy to use ABI encoding toolkit that does so called "tight packing" or given arguments. You can perform this with one built-in function.

In Solidity


 /**
   * A test method exposed to be called from clients to compare that ABI packing and hashing
   * is same across different programming languages.
   *
   * Does ABI encoding for an address and then calculates KECCAK-256 hash over the bytes.
   *
   * https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
   *
   */
  function calculateAddressHash(address a) public pure returns (bytes32 hash, bytes memory data) {

    // First we ABI encode the address to bytes.
    // This is so called "tight packing"
    // https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
    bytes memory packed = abi.encodePacked(a);

    // Then we calculate keccak256 over the resulting bytes
    bytes32 hashResult = keccak256(packed);

    return(hashResult, packed);
  }


In JavaScript/TypeScript

  import { soliditySha3 } from 'web3-utils';

  // Sign address
  const { signature, v, r, s } = signAddress(user2);

  // This is an address is a hexadecimal format
  const ourData = user2.toLowerCase();

  // https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#id23
  // Convert address to bytes using "tight packing"
  // and them calculates keccak-256 over the resulting bytes
  const ourHash = soliditySha3({t: 'address', v: user2 });

  // We hash data in similar in TypeScript and Solidity
  const { hash, data } = await tokenSwap.calculateAddressHash(user2);
  assert(ourData.toLowerCase() == data.toLowerCase());
  assert(ourHash.toLowerCase() == hash.toLowerCase());

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.