Skip to content

fix(eip712): harden typed-data signing correctness (odd-length hex + primaryType inference)#2

Open
Nexory wants to merge 1 commit into
ProjectOpenSea:mainfrom
Nexory:fix/eip712-signing-correctness
Open

fix(eip712): harden typed-data signing correctness (odd-length hex + primaryType inference)#2
Nexory wants to merge 1 commit into
ProjectOpenSea:mainfrom
Nexory:fix/eip712-signing-correctness

Conversation

@Nexory

@Nexory Nexory commented Jun 11, 2026

Copy link
Copy Markdown

What

Two correctness fixes in the EIP-712 typed-data signing path.

Why

1. util/eip712.ts - an odd-length hex value is silently truncated

hexToBytes allocates new Uint8Array(clean.length / 2), which floors a fractional length. An odd-length hex string therefore drops its last nibble, and encodeValue for a bytes value then hashes the truncated data - the adapter signs the wrong content with no error.

2. bridges/ethers.ts - wrong primaryType when it is omitted

When signTypedData is called without an explicit primaryType, the bridge used Object.keys(types).find(t => t !== "EIP712Domain"), i.e. the first key. EIP-712's primary type is the struct that is not referenced as a field type by any other struct (the root of the type graph), which is what ethers.js infers. When the root is not declared first (for example a dependency struct is listed above it), the bridge signs the wrong struct.

Change

  • hexToBytes rejects an odd-length hex string instead of truncating it.
  • The ethers bridge infers the root type (the struct not referenced by any other) when primaryType is omitted.

Tests

Adds one regression test per fix. Against the current code both fail:

hashTypedData > rejects an odd-length hex bytes value instead of silently truncating
  AssertionError: expected [Function] to throw an error

EthersAdapterSigner > infers the root primaryType when omitted, not the first types key
  expected "spy" to be called with { primaryType: "Mail" }, received "Person"

With the fixes both pass and the full suite stays green:

Test Files  4 passed (4)
      Tests  72 passed (72)

Two correctness fixes in the EIP-712 signing path:

- util/eip712.ts: hexToBytes silently truncated an odd-length hex string
  (dropping the last nibble), producing a wrong hash for `bytes` values. It
  now throws so signing fails loudly instead of signing the wrong data.

- bridges/ethers.ts: when signTypedData is called without an explicit
  primaryType, the ethers bridge picked the first key in `types`. That signs
  the wrong struct when the root type is not declared first (a dependency
  listed above it). It now infers the root type (the struct not referenced by
  any other), matching ethers.js.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant