Sitelet https://github.com/NomicFoundation/hardhat/issues/8344
Skip to content

EIP-712 collector throws HHE818 for a same-named struct in a source the user didn't include #8344

Description

@anaPerezGhiglia

Version of Hardhat

3.6.0

What happened?

test.solidity.eip712Types.include in Hardhat defines the include set only controls which struct names are emitted. The collector still walks every compiled source's AST and considers every struct it finds for name-collision detection. A struct in a file the user didn't include — and that nothing in the included scope imports — can therefore abort the test run with HHE818 if its name happens to clash with a selected struct, even though the user has no expectation that the tool would look at that file at all.

Forge's equivalent ([bind_json].include) behaves differently: structs in sources outside the include set never enter the registry.

Minimal reproduction steps

Self-contained dual-toolchain repro (forge test passes, npx hardhat test solidity throws HHE818 against the same source set): https://github.com/anaPerezGhiglia/repro-hh-eip712-include-scope.

Two small files plus a test:

  • contracts/A.sol — listed in eip712Types.include; defines library A { struct Order { address user; uint256 amount; } }.
  • contracts/B.sol — not included, not imported by A.sol or any test; defines a same-named struct Order { bytes32 id; bool active; }.

The repro repo's README has the full versions table, devcontainer setup, and an optional appendix that also validates the name-form path under forge bind-json.

Observed error

Error HHE818: Two different EIP-712 struct definitions named "Order" were found:
- contracts/A.sol
- contracts/B.sol

Thrown at collection time, before any test runs.

Expected behavior

include should bound which sources contribute structs to the registry. Conflict detection should fire only on selected-vs-selected conflicts (and on unselected conflicts reachable from a selected struct — the existing reachableFromSelected deferred-path machinery in canonicalize.ts already covers that). An unselected struct in an unimported file should not throw.

Environment

  • hardhat@3.6.0 (also reproduces on 3.5.1)
  • @nomicfoundation/edr@0.12.0-next.33

Search terms

eip712, EIP-712, HHE818

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

type:bugSomething isn't working

Type

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions