Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Hashing is inconsistent with respect to ethers js #2633

Open
ethereumdegen opened this issue Oct 10, 2023 · 6 comments
Open

Hashing is inconsistent with respect to ethers js #2633

ethereumdegen opened this issue Oct 10, 2023 · 6 comments
Labels
bug Something isn't working

Comments

@ethereumdegen
Copy link

Version
2.0.10

Platform
Linux Mint 20

Description
Enter your issue details here.

Okay i have narrowed down my hashing problem to a smaller test scenario that proves my woes.

check this out :

this rust code

   
   let encoded_data =  ethers::abi::encode_packed( &vec![Token::Uint(U256::zero())]).unwrap();
         
   
   let hash_bytes = H256( keccak256(encoded_data) );
   
     
   println!("nonce only  hash {:?}", hash_bytes);

outputs this: 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

and this javascript code which i hoped would be the same

 const result_nonce_only = ethers.utils.solidityKeccak256(
        ["uint256"],

        [0]
      );

outputs this : 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563

why might this be ?

@ethereumdegen ethereumdegen added the bug Something isn't working label Oct 10, 2023
@ethereumdegen
Copy link
Author

ethereumdegen commented Oct 10, 2023

What is super bizarre is my tests with Address work fine. It is uint that specifically is giving strange results

even if there is an explanation for this , the documentation is highly insufficient and this is very confusing

@ethereumdegen
Copy link
Author

ethereumdegen commented Oct 10, 2023

Okay i found another clue. It looks like in rust, Uint only matches JS if doing 'encode' and Address only matches if doing 'encodePacked' . The reference on JS is doing ' ethers.utils.solidityKeccak256 '. To my limited knowledge, that JS reference is doing encodePacked so i thought rust would also always be doing that. uh oh.

unfortunately, this means it is impossible for me to match hashes on a struct that has both an address and a uint. This seems like a bug... ?

@ethereumdegen
Copy link
Author

ethereumdegen commented Oct 10, 2023

Okay i forked the code and changed it to this

'''
Uint(n) => {
/*

let mut buf = [0; 32];
n.to_big_endian(&mut buf);
let start = if in_array { 0 } else { 32 - ((n.bits() + 7) / 8) };
out.extend_from_slice(&buf[start..32]);

*/

        let mut buf = [0; 32];
        n.to_big_endian(&mut buf);
        let start = 0;
        out.extend_from_slice(&buf[start..32]);
    
    }

'''

and now it works like a charm for me. Needs some investigation for sure !

@ethereumdegen
Copy link
Author

ethereumdegen commented Oct 11, 2023

Btw im talking abt etherscore/src/abi/encode_packed having an issue here

@DaniPopes
Copy link
Collaborator

This is an unfortunate limitation of ethabi tokens.
https://docs.rs/ethers/latest/ethers/abi/fn.encode_packed.html

Uint and Int tokens will be encoded using the least number of bits, so no padding will be added by default.

@ethereumdegen
Copy link
Author

Uhh so

  1. encodePacked isnt encodePacked? It means something different in rust versus javascript???

And 2 ) so there is absolutely no way to do solidityKeccak256(tokens[]) in rust yet ?

🤔 i feel like these are some serious problems as they relate to applications that want to use ECRecover with rust backend

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants