エラーメッセージ
Invalid yParityOrV value
別の表記
- Error: Invalid yParityOrV value
動作はライブラリによって異なります。ethers 6 は EIP-155 形式の値(35 以上)を正規化し、同じ署名をエラーなしで復元します(再現例を参照)。5 のようなその他の想定外の値に対しては「invalid v」をスローします。そのため、ethers から viem に移行したコードでは、以前は検証できていた署名で失敗し始めることがあります。
viem (TypeScript) — recoverAddress / recoverMessageAddress / recoverPublicKey
このエラーの意味
署名の最後のバイト(リカバリ ID)が、viem が受け付ける値、つまり 0 か 1(`yParity`)、または 27 か 28(従来の `v`)のいずれでもありません。メッセージや型付きデータの署名では、常にこれらのいずれかが使われます。それ以外の値は、トランザクション署名の慣習やバイト順の誤りに由来します。viem は復元の前に停止します。
発生する理由
EIP-155 のトランザクションの v をメッセージに使っている
よくあるレガシートランザクションは、v にチェーンをエンコードします(`chainId * 2 + 35 + yParity`、たとえばメインネットでは 37/38)。トランザクション署名用のヘルパーをメッセージに流用するコードや、トランザクションから v を読み取るコードは、viem が拒否する値を生成します。
ハードウェアウォレットやライブラリが別の形式で v を返す
ときどき署名者との連携実装の中には、リカバリビットを 0/1 として別のフィールドで返すものや、27 を 2 回加算するものがあります。その場合、連結した署名の末尾が想定外のバイトになります。
要素を間違った順序で連結している
ときどき署名を r‖s‖v ではなく v‖r‖s の順(一部の API が返す順序)で組み立てると、v の位置に s のランダムなバイトが入ります。
修正方法
- 1.
復元の前に v を正規化する
EIP-155 の値と 0/1 を 27/28(または yParity の 0/1)に変換し、署名が r‖s‖v の順で組み立てられていることを確認してください。
ts import { hexToNumber, numberToHex, type Hex } from "viem"; // Message signatures carry v = 27/28 (or 0/1); map EIP-155 style values back. function normaliseV(signature: Hex): Hex { let v = hexToNumber(`0x${signature.slice(130)}`); if (v >= 35) v = ((v - 35) % 2) + 27; // EIP-155: chainId * 2 + 35 + yParity if (v === 0 || v === 1) v += 27; return `${signature.slice(0, 130)}${numberToHex(v).slice(2)}` as Hex; }