Skip to content

Instantly share code, notes, and snippets.

@glihm
Last active July 4, 2023 16:09
Show Gist options
  • Save glihm/25fbff5bfbdab32c57d6b8187f4f041a to your computer and use it in GitHub Desktop.
Save glihm/25fbff5bfbdab32c57d6b8187f4f041a to your computer and use it in GitHub Desktop.
Keccak rust / ethereum

I am trying to pre-compute a keccak hash in a rust library, to then send it to Ethereum where it must match the re-computed hash in solidity.

However, I have a strange behavior.

The data to hash:

function testConsumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload)
    external
    payable
    returns (bytes32)
{
    bytes memory b = abi.encodePacked(fromAddress, uint256(uint160(msg.sender)), payload.length, payload);
    bytes32 msgHash = keccak256(b);                                                                                                                                                                            
    emit TestEvent(fromAddress, uint256(uint160(msg.sender)), msgHash, payload.length, payload, b);
    return msgHash;
}

which results in hash 0x52654d122bf06d08b03ee7c6fc4331bb78c93521369b3f8c10f2725316ba59c9 with arguments:

uint256 fromAddress = 03ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0;
uint256[] payload = [0x1, 0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266];

On the EVM this is the buffer I have in TestEvent data, for b:

03ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0
000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000001
000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266

Which is weird.. because based on solidity abi for dynamic sized types it's supposed to have the offset of the array.

Looks like because the array is the last element, the offset is not required? But cast gives a different result.

Doing it with cast command from foundry and from my rust library (using sha3), I have the following:

cast abi-encode "e(uint256,uint256,uint256,uint256[])" 0x03ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 2 '[1,1390849295786071768276380950238675083608645509734]'

03ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0
000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000080
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000001
000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266

Which generates a hash 0x4728187e41c5f53fb48d5461998c025681e57546967776d74147995716300719.

So.. I don't know what I am missing, but library and cast tool are giving the same result, but solidity a different one.

If is because the argument is a calldata?

I am compiling the code with forge and version solidity pragma solidity ^0.8.0;.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment