How to work with _hashTypedDataV4 correctly

This is what the function looks like in the contract:

function extractSigner712(bytes memory signature,
                          address mailTo,
                          string memory mailContents)
                          public view returns (address) {
    bytes32 digest = _hashTypedDataV4(
        keccak256(
            abi.encode(
                keccak256("Mail(address mailTo,string mailContents)"),
                mailTo,
                keccak256(bytes(mailContents))
            )
        )
    );
    address signer = ECDSA.recover(digest, signature);
    return signer;
}

and the test looks like this:

it.only("_hashTypedDataV4 test", async () => {
  const { dao, owner } = await loadFixture(deploy);

  const domain = {
    name: "TestCall",
    version: "1",
    chainId: hre.network.config.chainId,
    verifyingContract: dao.address,
  };
  const types = {
    Mail: [
      { name: "mailTo", type: "address" },
      { name: "mailContents", type: "string" },
    ],
  };

  const value = {
    mailTo: owner.address,
    mailContents: "test message",
  };
  const signature = await owner._signTypedData(domain, types, value);

  const res = await dao.extractSigner712(
    signature,
    value.mailTo,
    value.mailContents
  );
  console.log("res", res);
  expect(res).to.eq(owner.address); // do not match here, why ????
});

Issue resolved, found a working example here:

2 Likes

No, I hurried with the conclusion, the example is not working.

I created a repository with a simple example:

Please help me understand what is the problem? Thanks.

Sorry for the late reply.

The domain as defined in the contract is different from that in the test!

According to the contract you should be specifying name: "test" and version: "1.0".

1 Like

Thank you! it works!