# Same function different Hash

**URL:** <https://forum.openzeppelin.com/t/same-function-different-hash/14685>\
**Category:** Smart Contracts\
**Tags:** etherscan-verify\
**Created:** [August 28, 2021, 4:51pm UTC](https://forum.openzeppelin.com/t/same-function-different-hash/14685 "2021-08-28T16:51:45Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Cainuriel](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/cainuriel/32/5410_2.png) [@Cainuriel](https://forum.openzeppelin.com/u/Cainuriel)\
**Post date:** [August 28, 2021, 4:51pm UTC](https://forum.openzeppelin.com/t/same-function-different-hash/14685/1 "2021-08-28T16:51:45Z")

</div>

I am trying to generate a hash with four elements connecting to a contract in solidity. I have not been able to get it to work offline.

The contract is this:

```auto
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;

/* Signature Verification

How to Sign and Verify
# Signing
1. Create message to sign
2. Hash the message
3. Sign the hash (off chain, keep your private key secret)

# Verify
1. Recreate hash from the original message
2. Recover signer from signature and hash
3. Compare recovered signer to claimed signer
*/

contract Signature {
    /* Get message hash to sign
    getMessageHash(
        beneficiary address,
        amount,
        nonce,
        payment contract 
    ) take the hash

    */
    function getMessageHash(
        address _to, uint _amount, uint _nonce, address _contract
    )
        public pure returns (bytes32)
    {
        return keccak256(abi.encodePacked(_to, _amount, _nonce, _contract));
    }

    /* 2. Sign message hash
    # using browser console
    account = "copy paste account of signer here"
    hash = the hash created
    ethereum.request({ method: "personal_sign", params: [account, hash]}).then(console.log)

    # using web3
    web3.personal.sign(hash, web3.eth.defaultAccount, console.log)
    */
    function getEthSignedMessageHash(bytes32 _messageHash) public pure returns (bytes32) {
        /*
        Signature is produced by signing a keccak256 hash with the following format:
        "\x19Ethereum Signed Message\n" + len(msg) + msg
        */
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash));
    }

    /* 4. Verify signature
    signer = sender address
    to = beneficiary address
    amount = weis
    nonce 
    payment address
    signature = the sign hash created before
    */
    function verify(
        address _signer,
        address _to, uint _amount, uint _nonce, address _contract,
        bytes memory signature
    )
        public pure returns (bool)
    {
        bytes32 messageHash = getMessageHash(_to, _amount, _nonce, _contract);
        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);

        return recoverSigner(ethSignedMessageHash, signature) == _signer;
    }

    function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature)
        public pure returns (address)
    {
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);

        return ecrecover(_ethSignedMessageHash, v, r, s);
    }

    function splitSignature(bytes memory sig)
        public pure returns (bytes32 r, bytes32 s, uint8 v)
    {
        require(sig.length == 65, "invalid signature length");

        assembly {
            /*
            First 32 bytes stores the length of the signature

            add(sig, 32) = pointer of sig + 32
            effectively, skips first 32 bytes of signature

            mload(p) loads next 32 bytes starting at the memory address p into memory
            */

            // first 32 bytes, after the length prefix
            r := mload(add(sig, 32))
            // second 32 bytes
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes)
            v := byte(0, mload(add(sig, 96)))
        }

        // implicitly return (r, s, v)
    }
}

```

Well, I have created a mini DAPP with hardhat to connect with the contract deployed on the testnet. is the following code:

```auto
         async function signPayment() {
  
              if (typeof window.ethereum !== 'undefined') {

                  const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
                  console.log('cuenta conectada: ', account);
                  const provider = new ethers.providers.Web3Provider(window.ethereum);
                  const signer = provider.getSigner();
                  const contract = new ethers.Contract(signatureAddress, Signature.abi, signer);

                  try {

                    const hash = await contract.getMessageHash(recipient, ethers.utils.parseEther(amount), nonce, contractAddress);
                    //const hash = await transation.wait();
                    console.log('el primer hash', hash);

                      Swal.fire({
                        title: "Datos hasheados antes de ser firmados",
                        text: `Cantidad: ${amount}, Serie del cheque: ${nonce}, Hash: ${hash}`,
                        icon: 'success',
                        confirmButtonText: "Cerrar",
                        confirmButtonClass: "",
                        buttonsStyling: true,
                        showCloseButton: true,
                      }).then((result) => {

                        if (result.isConfirmed) {

                          console.log('hash',hash);
                          console.log('cantidad ',amount);
                          console.log('serie del cheque',nonce);
                        
                        } 
                      });

                      await window.ethereum.request({method:"personal_sign", params: [account, hash]}).then(console.log)
                    
      
          
                  } catch (err) {
                    let mensajeError = err.message;
                     
                    if (err.data) {
          
                      if (err.data.message === '') {
                        mensajeError = 'para otra cosa';
                      } else {
                        console.log('error: ',mensajeError);
                      }
                    }
                
                    Swal.fire({
                      title: 'Ooops!',
                      text: `${mensajeError}`,
                      icon: 'error',
                      confirmButtonText: 'Cerrar'
                    })
                    console.log("Error: ", err)
                  }
              }
            }

```

As I am in tests, I enter the data by default. The only thing that changes is the Nonce for capturing the timestamp now.

```auto
  const [recipient, setRecipient] = useState('0x1D918aD261752d71FFD63EF9Fb217001C5875005');
  const [nonce, setNonce] = useState(Math.floor(new Date().getTime()/1000.0));
  const [amount, setAmount] = useState('100000000000000000');
 // const [account, setAccount] = useState('');
  const [contractAddress, setContractAddress] = useState("0xc972f1e1a446966AA51B1a13A4Acf703C05A9d4f"); // contrato de cobro.

```

I connect with the same contract in BSC testnet.  
It is verified so you can review it.:

> **[Contract Address 0x854F2CBa80dAe7989Dd5729Ed2a71A1923d43243 | BscScan](https://testnet.bscscan.com/address/0x854F2CBa80dAe7989Dd5729Ed2a71A1923d43243)**
>
> The Contract Address 0x854F2CBa80dAe7989Dd5729Ed2a71A1923d43243 page allows users to view the source code, transactions, balances, and analytics for the contract address. Users can also interact and make transactions to the contract directly on...

Now, the problem is that with the same data and obviously the same order I get different hashes as a result

For example, with the following data:  
Contract: 0xc972f1e1a446966AA51B1a13A4Acf703C05A9d4f  
Recipient: 0x1D918aD261752d71FFD63EF9Fb217001C5875005  
Amount: 100000000000000000  
Nonce: 1630169254

Connecting by remix I get the hash:  
0x94674213c7a2efc0ff486f699ea61064bd68d75857afa2883cc312e0da5cb556  
And connecting by my Dapp i get other hash:  
0x0edd5b8bf737a53fb39f823708dab5f427077ab2e6ab84beb691c6b3e28667da

Why that???? Is the same function...

---

<div class="post-metadata">

**Author:** ![STYJ](https://avatars.discourse-cdn.com/v4/letter/s/df788c/32.png) [@STYJ](https://forum.openzeppelin.com/u/STYJ)\
**Post date:** [August 29, 2021, 6:48am UTC](https://forum.openzeppelin.com/t/same-function-different-hash/14685/2 "2021-08-29T06:48:19Z")

</div>

Your error is in `ethers.utils.parseEther(amount)`. When you call this function in your dapp, the value being used is `ethers.utils.parseEther(100000000000000000)` which is why it gives you `0x0edd5b8bf737a53fb39f823708dab5f427077ab2e6ab84beb691c6b3e28667da`.

Try calling `getMessageHash` with amount = 100000000000000000000000000000000000 on remix.

![image](https://us1.discourse-cdn.com/flex022/uploads/zeppelin/original/2X/a/a939d0c97262a3d2f64afacb895e48489f65b134.png)

---

<div class="post-metadata">

**Author:** ![Cainuriel](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/cainuriel/32/5410_2.png) [@Cainuriel](https://forum.openzeppelin.com/u/Cainuriel)\
**Post date:** [August 31, 2021, 9:21am UTC](https://forum.openzeppelin.com/t/same-function-different-hash/14685/3 "2021-08-31T09:21:53Z")

</div>

First of all, thank you for answering me @STYJ

Everything works fine infinite thanks !!
