Skip to content

fix: parse an EIP-7702 authorization yParity above 1 and reject it in recovery - #5371

Merged
jxom merged 2 commits into
mainfrom
claude/authorization-y-parity
Nov 1, 2026
Merged

jxom merged 2 commits into
mainfrom
claude/authorization-y-parity

Conversation

@jxom

@jxom jxom commented Nov 1, 2026

Copy link
Copy Markdown
Member

Supersedes #5367 and keeps its commit (authored by @erkancamli) unchanged.

Problem

parseTransaction threw InvalidYParityError for an authorization yParity above 1. EIP-7702 permits any y_parity below 2**8 on the wire, and #5304 made serializeTransaction keep such values. So a transaction viem serializes could not be parsed back, for example mainnet 0xaec84209…cb09 with y_parity 28.

#5367 fixes the parsing, but on its own it lets a protocol-invalid tuple recover a signer. recoverPublicKey maps 27 and 28 to recovery bits 0 and 1 as legacy v values. EIP-7702 recovers with y_parity as the raw recovery id, so the client skips that tuple and no delegation happens. With #5367 alone, verifyAuthorization returns true for a real signature whose yParity was raised by 27.

Changes

  • parseTransaction (from fix: accept an EIP-7702 authorization yParity above 1 in parseTransaction #5367): keeps an authorization yParity from 2 to 255 as is. 256 or more still throws.
  • recoverAuthorizationAddress: throws InvalidYParityError when an object signature has a yParity other than 0 or 1. Hex and byte signatures, and signatures that carry only v, are unchanged.
  • verifyAuthorization: returns false for that case instead of throwing.

Tests

  • parseTransaction.test.ts: the mainnet round-trip from fix: accept an EIP-7702 authorization yParity above 1 in parseTransaction #5367, plus a round-trip at yParity 255.
  • recoverAuthorizationAddress.test.ts: yParity 28 throws InvalidYParityError.
  • verifyAuthorization.test.ts: a real signer verifies only at its own yParity (0). At 1, 2, 27, 28 and 255 it returns false. Before this fix it returned true at 27.

I ran parseTransaction, serializeTransaction and src/utils/authorization/ tests: 135 of 135 passed. pnpm test's Anvil global setup could not start in my environment, so I used a Vitest config without it. These tests don't use Anvil. tsc --noEmit -p src/tsconfig.json and Biome are clean.

For Reviewers

Parsed authorizations still differ in shape: yParity 0 or 1 includes v (27n or 28n), but 2–255 has no v. I left that as is. The InvalidYParityError message ("Expected 0 or 1") is also unchanged for the parse error at 256 or more.


Generated by Claude Code

erkancamli and others added 2 commits November 1, 2026 21:46
…saction`

`parseAuthorizationList` parsed each authorization signature with
`parseEIP155Signature`, which throws `InvalidYParityError` for any
`yParity` other than 0 or 1. EIP-7702 permits any `y_parity` below 2**8
in an authorization tuple, and #5304 made `serializeTransaction` keep
such a value, so a transaction viem serializes, for example mainnet
0xaec84209...cb09 whose authorization has a `y_parity` of 28, could not
be parsed back, and `recoverTransactionAddress` threw on it.

An authorization `yParity` from 2 to 255 is now kept as is, with `r`
and `s` padded as before. 0 and 1 parse as before, and 256 or more
still throws.
…recovery

With `parseTransaction` now keeping an authorization `yParity` from 2 to
255, a parsed `yParity` of 27 or 28 reached `recoverPublicKey`, which
maps them to recovery bits 0 and 1 as legacy `v` values. A tuple the
protocol skips therefore recovered a signer, and `verifyAuthorization`
returned `true` for it.

EIP-7702 recovers the authority with `y_parity` as the raw recovery id,
so `recoverAuthorizationAddress` now throws `InvalidYParityError` for a
`yParity` other than 0 or 1, and `verifyAuthorization` returns `false`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D3nmWhB4o7Zekbowt3QdXf
@vercel

vercel Bot commented Nov 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
viem Building Building Preview Nov 1, 2026 9:51pm UTC

Request Review

@changeset-bot

changeset-bot Bot commented Nov 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8a4f488

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
viem Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-01T21:55:25.874208Z 8a4f488 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@jxom
jxom merged commit 035c519 into main Nov 1, 2026
37 of 40 checks passed
@jxom
jxom deleted the claude/authorization-y-parity branch November 1, 2026 21:52

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a4f488408

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

signature.yParity !== 0 &&
signature.yParity !== 1
)
throw new InvalidYParityError({ yParity: BigInt(signature.yParity) })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject non-integer yParity values without calling BigInt

When an object signature contains NaN, either infinity, or a fractional yParity such as 1.5—all representable by the public Signature<number> type—BigInt(signature.yParity) throws a native RangeError before InvalidYParityError can be constructed. Consequently, recoverAuthorizationAddress does not provide its declared error and verifyAuthorization cannot catch it to return false, contrary to the new handling for every parity other than 0 or 1; validate these numeric cases before conversion or construct the domain error without converting them first.

Useful? React with 👍 / 👎.

This branch was successfully deployed

1 active deployment
Preview — 8a4f4884 Deployed Nov 1, 2026 by vercel[bot]
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.

3 participants