Repository navigation
fix: parse an EIP-7702 authorization yParity above 1 and reject it in recovery - #5371
Conversation
…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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 8a4f488 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 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) }) |
There was a problem hiding this comment.
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 👍 / 👎.
Supersedes #5367 and keeps its commit (authored by @erkancamli) unchanged.
Problem
parseTransactionthrewInvalidYParityErrorfor an authorizationyParityabove 1. EIP-7702 permits anyy_paritybelow 2**8 on the wire, and #5304 madeserializeTransactionkeep such values. So a transaction viem serializes could not be parsed back, for example mainnet0xaec84209…cb09withy_parity28.#5367 fixes the parsing, but on its own it lets a protocol-invalid tuple recover a signer.
recoverPublicKeymaps 27 and 28 to recovery bits 0 and 1 as legacyvvalues. EIP-7702 recovers withy_parityas the raw recovery id, so the client skips that tuple and no delegation happens. With #5367 alone,verifyAuthorizationreturnstruefor a real signature whoseyParitywas raised by 27.Changes
parseTransaction(from fix: accept an EIP-7702 authorizationyParityabove 1 inparseTransaction#5367): keeps an authorizationyParityfrom 2 to 255 as is. 256 or more still throws.recoverAuthorizationAddress: throwsInvalidYParityErrorwhen an object signature has ayParityother than 0 or 1. Hex and byte signatures, and signatures that carry onlyv, are unchanged.verifyAuthorization: returnsfalsefor that case instead of throwing.Tests
parseTransaction.test.ts: the mainnet round-trip from fix: accept an EIP-7702 authorizationyParityabove 1 inparseTransaction#5367, plus a round-trip atyParity255.recoverAuthorizationAddress.test.ts:yParity28 throwsInvalidYParityError.verifyAuthorization.test.ts: a real signer verifies only at its ownyParity(0). At 1, 2, 27, 28 and 255 it returnsfalse. Before this fix it returnedtrueat 27.I ran
parseTransaction,serializeTransactionandsrc/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.jsonand Biome are clean.For Reviewers
Parsed authorizations still differ in shape:
yParity0 or 1 includesv(27n or 28n), but 2–255 has nov. I left that as is. TheInvalidYParityErrormessage ("Expected 0 or 1") is also unchanged for the parse error at 256 or more.Generated by Claude Code