6

I am working on implementing a smart contract application in which, on and off-chain calculations will exist. I will have to calculate the Hash Function of multiple integers with Python and Solidity. But Solidity and Python give different results respectively as shown below.

Solidity Code:

The Output for (a=1, b=2, c=3) is: 49776295142305522338649292811956300178326541500117443588869412604416814650524

Python Code:

The Output for (a=1, b=2, c=3) is: 45637690538541992090000098772847886457082422231295691457910964509567538102535

I need to understand how Solidity encodes the input integers and passes them to the hash function, How this could be done in Python?

1

3 Answers 3

4

I would check out the Web3.py library, specifically the function Web3.soliditySha3

This will work for computing the hash you need:

from web3 import Web3

print(int(Web3.soliditySha3(['uint256', 'uint256', 'uint256'], [1 ,2, 3]), 16))
4
  • 2
    Note that this will change in v4, which is now released in beta. soliditySha3 will return a bytes-like object, so you would do: print(Web3.toInt(Web3.soliditySha3(...)))
    – carver
    Commented Nov 16, 2017 at 18:33
  • It gives the following error, it seems I have to instantiate the Web3 class and there is no empty constructor option there. TypeError: unbound method soliditySha3() must be called with Web3 instance as first argument (got list instance instead) Commented Nov 17, 2017 at 11:16
  • I created an instance by: w3 = Web3(TestRPCProvider()). and after that everything works now. Thank you all so much. Commented Nov 17, 2017 at 12:03
  • seems like breaking changes between versions. Like @carver said, you'll also have to switch to using Web3.toInt instead of int() because soliditySha3 returns a bytes-like object in v4
    – natewelch_
    Commented Nov 17, 2017 at 13:25
2

As of v5 of the Web3.py library, you would do:

from web3 import Web3, EthereumTesterProvider

w3 = Web3(EthereumTesterProvider())
print(w3.toInt(w3.solidityKeccak(['uint256', 'uint256', 'uint256'], [1, 2, 3])))

49776295142305522338649292811956300178326541500117443588869412604416814650524

There's also this:

print(w3.toInt(w3.keccak(
    b'\x00'*31 + b'\x01' +
    b'\x00'*31 + b'\x02' +
    b'\x00'*31 + b'\x03')))

49776295142305522338649292811956300178326541500117443588869412604416814650524
1
from web3 import Web3
w3 = Web3(Web3.HTTPProvider('your network endpoints'))
w3.keccak(text='text_you_want_to_hash')

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.