This is not a question about the issue with Ethereum using a non-standard sha3. I have found the right JS hashing library, and am able to get matching hashes in JS and Solidity on byte strings. What I am wondering is how to represent a uint when passing it to the JS hash lib so that it results in the same hash as created by Solidity sha3.

'0x' + keccak(
// 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

// 0x5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
  • 1
    Update: Solidity's keccak256 produces identical results to its sha3 so everything in this thread applies to keccak256.
    – eth
    Nov 21, 2016 at 10:15

3 Answers 3


Jehan's answer is great, but we need to explain one more thing: Why does sha3(1) in solidity produce b10e2d...fa0cf6?

This is because solidity's sha3 function hashes its inputs based on the argument types. Thus the value 1 will generate a different hash if it is stored as bytes8, bytes16, bytes32, etc. Since sha3(1) is being passed 1 as a number literal, it is converted into the smallest necessary type, uint81.

8 bits fit into 2 hex characters, so if you pad your input to 2 characters you will get the same result in web3:


web3.sha3(leftPad((1).toString(16), 2, 0), { encoding: 'hex' })
// 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2

Likewise, you can cast the number on the solidity side:


// uint is equivalent to uint256
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6


// note that the value is padded by 64 characters to fit 256 bits
web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

A note about BigNumber types:

They don't work automatically with web3.sha3. You have to convert them to hex first.


sha3(uint(100 ether))
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273


// the .slice is to remove the leading '0x'
web3.sha3(leftPad(web3.toHex(web3.toWei(100)).slice(2).toString(16), 64, 0), { encoding: 'hex' })
// c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273


I wrote a small lib that provides a version of web3.sha3 that exactly matches the behavior of sha3 in Solidity. Hopefully this clears up all your hashing woes :). https://github.com/raineorshine/solidity-sha3


Solidity use HEX values internally.

> web3.sha3(web3.toHex(1))
  • 1
    I'm getting web3.sha3(web3.toHex(1)) === 8a07523229fdc48491a5e56c76620ba40639eb940e6a2fbdf62b2799b4c86643
    – Jehan
    Apr 6, 2016 at 3:26
  • This is not really a full answer, see my answer.
    – Jehan
    May 4, 2016 at 5:16

Solidity's sha3 function hashes the byte representation of a uint. That is, the number in hex (base 16), padded to 32 bytes. 32 empty bytes in hex representation is 64 zeros.

To do this in JS, we can utilize the infamous left-pad package:

const jsHashWeb3 = web3.sha3(leftPad((1).toString(16), 64, 0), { encoding: 'hex' })
// b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6
  • In Solidity, sha3(1) produces 0x5fe7f9...dcffd2, not b10e2d...fa0cf6 as your code produces. Could you explain? Jul 12, 2016 at 1:07
  • I know the feeling. Unfortunately I cannot explain. Maybe a typo on my part, it's been a couple of months. I've been using the snippet that I posted about here: github.com/ethereum/web3.js/issues/445. It doesn't cover all edge cases, but it's been working for me.
    – Jehan
    Jul 14, 2016 at 1:39

Your Answer

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

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