Hashing that matches Solidity `keccak256(abi.encode(...))`
See original GitHub issueI spent a long time figuring out why I could not get matching hashes between Solidity and Ethers using the solidityKeccak256
function with dynamic types (i.e. string
).
Example Solidity contract:
pragma solidity ^0.5.0;
contract TestingHashes {
function hash() public pure returns (bytes32) {
return keccak256(abi.encode("Hello", "world!"));
}
function hashPacked() public pure returns (bytes32) {
return keccak256(abi.encodePacked("Hello", "world!"));
}
}
In Ethers, if I use the hash function:
eth.utils.solidityKeccak256(["string", "string"], ["Hello", "world!"]);
The above matches the output of the Solidity function hashPacked
. However, as the Solidity docs state, the packed encoding is ambiguous. Is there a way to mimic the behavior of abi.encode
in Ethers?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:17
- Comments:6 (2 by maintainers)
Top Results From Across the Web
Hashing with Keccak256 | Solidity by Example | 0.8.13
keccak256 computes the Keccak-256 hash of the input. Some use cases are: Creating a deterministic unique ID from a input; Commit-Reveal scheme ...
Read more >Solidity's keccak256 hash doesn't match WEB3 keccak hash
The abi.encode function encode its parameters for a contract call using Solidity's ABI specs. For fixed size types like uintXXX, bool, ...
Read more >Hashing Functions In Solidity Using Keccak256 - Medium
This means that dynamic types are encoded in-place without length while static types will not be padded if they are shorter than 32...
Read more >Contract ABI Specification — Solidity 0.8.17 documentation
Indexed event parameters that are not value types, i.e. arrays and structs are not stored directly but instead a Keccak-256 hash of an...
Read more >ethereum/web3.py - Gitter
There are examples for preparing a signature to be verified by a solidity contract, ... encodePacked(recipient , amount); bytes32 message = keccak256(abi.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Right, the packed encoding is ambiguous. For example, imagine the following two cases:
Both will have the same packed representation and hence the same hash. This can allow a malicious actor to trick your contract. So in general you need to use a distinguished encoding. The
abi.encode
in Solidity is mirrored in ethers, so they should both produce the same, non-ambiguous data; however abi encoding is not truly distinguished, as there are multiple ways to encode the same data, it’s just the most popular implementations all behave the same, so this point is moot (ish).To get the result that matches
hash()
, you can use:I am also working on an EIP for a scheme that provides an actual distinguished encoding too, but I’ve been quite busy and haven’t had a chance to follow up on some feedback for it. I’ll bump it up my todo list. 😃
Make sense? Feel free to ask follow-up questions. 😃
I found different behavior. If struct have no array,ethers.utils.defaultAbiCoder.encode
works expected. Otherwise,defaultAbiCoder
adds array length before elements so bytes does not matchabi.encode
’s one .test.sol
Test.test.ts
tuple works 😉