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);
  • @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 Aug 10 '17 at 17:41
  • Okay, yep, looks like you're probably right - apologies for jumping the gun. +1 :-) – Richard Horrocks Aug 10 '17 at 18:14

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.


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.

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

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); 
  • You cannot hash an address in Solidity 0.5.0 anymore – Mikko Ohtamaa Mar 14 '20 at 13:48

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, privacy policy and cookie policy

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