# EIP-712 type hashing in Solidity tests

Description: How to use EIP-712 type hashing cheatcodes in Solidity tests

Note: This document was authored using MDX

  Source: https://github.com/NomicFoundation/hardhat-website/tree/main/src/content/docs/docs/guides/testing/eip712-types.mdx

Hardhat provides three cheatcodes for EIP-712 hashing in Solidity tests:
- [`eip712HashType`](/docs/reference/cheatcodes/utilities/eip712-hash-type)
- [`eip712HashStruct`](/docs/reference/cheatcodes/utilities/eip712-hash-struct)
- [`eip712HashTypedData`](/docs/reference/cheatcodes/utilities/eip712-hash-typed-data)

The first two look up your project's struct definitions by name, avoiding hand-written canonical type strings. `eip712HashTypedData` computes a digest from a self-describing JSON payload and works without any configuration.

## Configuration

`eip712HashType` and `eip712HashStruct` need a registry of struct types to resolve names. Enable this by adding an `eip712Types` block to your `hardhat.config.ts`:

```ts
// hardhat.config.ts
import { defineConfig } from "hardhat/config";

export default defineConfig({
  test: {
    solidity: {
      eip712Types: {
        include: ["contracts/**", "test/contracts/**"],
        // exclude: ["contracts/legacy/**"], // Optional
      },
    },
  },
});
```

> **Note:** To include structs from npm packages, match against the input source name used by solc (e.g., `"npm/@uniswap/permit2@*/src/interfaces/ISignatureTransfer.sol"`). For the full reference, see [Solidity tests configuration](/docs/reference/configuration#solidity-tests-configuration).

## Example

If your bundled `forge-std` doesn't expose these cheatcodes on its `vm` interface yet, declare a local interface and call them through the cheatcode address.

Given these struct definitions in `contracts/Eip712Types.sol`:

```solidity
struct Person {
    address wallet;
    string name;
}

struct Mail {
    Person from;
    Person to;
    string contents;
}
```

You can hash types and structs in your tests:

```solidity
import "forge-std/Test.sol";
import "../../contracts/Eip712Types.sol";

interface IEip712Cheats {
    function eip712HashType(string calldata) external pure returns (bytes32);
    function eip712HashStruct(string calldata, bytes calldata) external pure returns (bytes32);
    function eip712HashTypedData(string calldata) external pure returns (bytes32);
}

contract Eip712Test is Test {
    IEip712Cheats cheats = IEip712Cheats(address(vm));

    function testMailTypeHash() public view {
        bytes32 expected = keccak256(bytes(
            "Mail(Person from,Person to,string contents)"
            "Person(address wallet,string name)"
        ));
        assertEq(cheats.eip712HashType("Mail"), expected);
    }

    function testMailStructHash() public view {
        Mail memory m = Mail({
            from: Person({ wallet: address(0xA), name: "Alice" }),
            to:   Person({ wallet: address(0xB), name: "Bob"   }),
            contents: "hello"
        });

        bytes32 hash = cheats.eip712HashStruct("Mail", abi.encode(m));
        // hash now equals the standard EIP-712 struct hash for `m`.
    }
}
```

## Duplicate struct names

Each struct name must map to exactly one definition across the collected set. If two different structs share a name, the test run fails with error `HHE817`. To fix this, rename one of the structs or narrow your `include`/`exclude` globs. Identical definitions across multiple build infos are deduplicated silently.
