Signing Ethereum messages on Elixir

Thiago Belem
Nov 2, 2018 Β· 1 min read

Using ExW3 you can interact with any Ethereum network, deploy Smart Contracts and call/send any kind of functions & transactions.

When it comes to signing messages, you might have a few surprises along the line:

If you're like me, you would expect that doing ExW3.keccat256(1) on Elixir would give you the same result as keccat256(abi.encodePacked(1)) on Solidity, but it doesn't! :(

What happens is that uint(1) on Solidity has a different bytes representation (0x0000000000000000000000000000000000000000000000000000000000000001) than 1 in Elixir (0x31).. You need to convert it to 256 bits before hashing it, and you do it like this:

message = <<1::size(256)>>
hash = ExW3.keccat256(message)
{:ok, signature} = ExW3.eth_sign(account, hash)

If you have a more complex message, you need to join all the bits:

# On Elixir
account = 0xD8d9DB707461ab3F6FA032BF0e45942B15669d78
amount = 25
message = << <<account::size(160)>>, <<amount::size(256)>> >>
hashedMessage = ExW3.keccat256(message)
{:ok, signature} = ExW3.eth_sign(account, hash)# On Solidity
address _account = 0xD8d9DB707461ab3F6FA032BF0e45942B15669d78;
uint _amount = 25;
bytes32 message = keccak256(abi.encodePacked(_account, _amount));
bytes32 hashedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message));

And boom! πŸš€

Your hashedMessage (on Elixir) and your hashedMessage (on Solidity) will have the same value!