I am trying to tightly pack some typed data (array of structs or nested JSON) and generate SHA3 hash from it.

In JS, I can use ethereumjs-abi.soliditySHA3() method, ethAbi.soliditySHA3( ['bytes32', 'bytes32'], [ ethAbi.soliditySHA3(new Array(typedData.length).fill('string'), schema), ethAbi.soliditySHA3(types, data) ] );

The above code snippet is how Metamask packed, hashed and eventually signed typed-data. See https://medium.com/metamask/scaling-web3-with-signtypeddata-91d6efc8b290

I want to replicate the logic in smart contract so that I can verify the signature.

In solidity, I tried the following when dealing with an array of 2 elements. Each element has "type", "name" and "value". The schema is a concatenation of "type" and "name".

bytes32 schemaHash = sha3('string', 'string', elem1Schema, elem2Schema); bytes32 dataHash = sha3(type1, type2, elem1Data, elem2Data); bytes32 hash = sha3('bytes32', 'bytes32', schemaHash, dataHash);

The solidity code doesn't generate the same hash as the JS code. I suspect I am not packing the data correctly or using the wrong solidity function.


1 Answer 1


I over-think the problem.

The method ethAbi.soliditySHA3([types], [values]) is using the [types] to determine the destination datatypes and perform the necessary paddings / conversion. The [types] are never added to the buffer for sha3 hashing.

And the [types] is not required in solidity because it is a strong typed language. So to achieve the sha3 hashing in solidity, I just need to call sha3(v1, v2, ...). The function will tightly pack the value and then hash the buffer.

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.