I have a smart contract with the following function:

function testHash(
    address _sender, 
    uint8 _method, 
    uint256 _number, 
    uint256 _amount) 
    public 
    returns (bytes32) 
{
return keccak256(abi.encodePacked(_sender, _number, _method, _amount));    
}

Which when given the following values 0xa1d9e8788414eA9827f9639c4bd81bA8f3A29758, 0, 0, 0 produces the following hash 0x65a0fc07391cb16f60c589836a72bdeaf2ab8bcb16c819126abba4408e069bcb

I have the following golang code

func GenerateSignedPaymentMessage(ethAddress common.Address, paymentMethod uint8, paymentNumber, chargeAmountInWei *big.Int) []byte {
//keccak256(abi.encodePacked(msg.sender, _paymentNumber, _paymentMethod, _chargeAmountInWei))

addressBytes := ethAddress.Bytes()
// we need to cast to []byte in order to generate a keccak hash
methodBytes := make([]byte, 1)
methodBytes[0] = byte(paymentMethod)
numberBytes := paymentNumber.Bytes()
amountBytes := chargeAmountInWei.Bytes()
// generate the hash
hash := crypto.Keccak256(addressBytes, numberBytes, methodBytes, amountBytes)
return hash

}

Which when I call like so

address := common.HexToAddress("0xa1d9e8788414eA9827f9639c4bd81bA8f3A29758")
method := uint8(0)
number := big.NewInt(0)
amount := big.NewInt(0)
hash := GenerateSignedPaymentMessage(address, method, number, amount)
fmt.Println(hash.String())

which gives the following output 0x7fc96d5f44e3e792633fcc981adf2bd0f644f0c167132eca5659b8a72d95bf07 which does not match the hash given by the solidity code. I'm unsure what to do here so any advice would be great!

EDIT:

As pointed out by smarx, I tried the following function

func TestHash(t *testing.T) {
address := common.HexToAddress("0xa1d9e8788414eA9827f9639c4bd81bA8f3A29758")
bn := make([]byte, 32)
ba := make([]byte, 32)
bm := make([]byte, 32)
bn[31] = 0
ba[31] = 0
bm[31] = 0
hash := crypto.Keccak256Hash(address.Bytes(), bn, ba, bm)
fmt.Println(hash.String())
}

Which produces the following hash 0xfc60222910c18ebcfd5610479223663effa903325f3db1db39a4d5fa37ba33a2

  • What does .Bytes() do? My guess is it's not returning 32 bytes (the size of a uint256), because I don't see where you're providing information as to how many bytes to return. – smarx Jul 11 at 5:13
  • 2
    Skimming the code of big.Int, I would say this is definitely the problem. You're probably only getting back a single byte for each. You'll need to figure out how to left pad the result to make it 32 bytes. – smarx Jul 11 at 5:20
  • Ah okay that would make sense! I'll try and hopefully that fixes it :D – hextet Jul 11 at 5:25

It was definitely what smarx pointed out! I used the https://github.com/miguelmota/go-solidity-sha3 library, which works!

hash := payment.SoliditySHA3(
    payment.Address("0xa1d9e8788414eA9827f9639c4bd81bA8f3A29758"),
    payment.Uint8(big.NewInt(0)),
    payment.Uint256(big.NewInt(0)),
    payment.Uint256(big.NewInt(0)),
)
fmt.Println(hex.EncodeToString(hash))

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.