エラーメッセージ
invalid signature length
別の表記
- Error: invalid signature length
viem (TypeScript) — recoverMessageAddress / recoverAddress / recoverTypedDataAddress / recoverPublicKey
このエラーの意味
viem の復元関数は、ちょうど 65 バイト(r‖s‖v)の 16 進またはバイト列の署名を受け付け、それ以外の長さではこの素の `Error` で停止します。64 バイトの EIP-2098 コンパクト形式も例外ではなく、viem はこの形式を明示的な変換ヘルパーを通じてのみサポートしています。何も復元されていません。署名の形式が異なるか、そもそも EOA の署名ではありません。
発生する理由
64 バイトのコンパクト形式(EIP-2098)の署名
よくある一部のウォレット、リレイヤー、コントラクトは、署名をコンパクト形式(yParity を s に折り込んだ形式)で保存します。ethers はこれをそのまま受け付けますが、viem の `recover*` 関数は受け付けません。
スマートアカウントの署名
よくあるSafe、Coinbase Smart Wallet、その他のスマートアカウントによる ERC-1271 や ERC-6492 の署名は 65 バイトより長く、アドレスを復元できません。アカウントのコントラクトに照会して確認しなければなりません。
Base64 または二重の 16 進エンコーディング
ときどきbase64 で受け渡された署名や、16 進文字列をさらに 16 進でエンコードしたものは、viem が読み込んだ時点で長さが正しくありません。
修正方法
- 1.
復元の前にコンパクト署名を変換する
`parseCompactSignature` と `compactSignatureToSignature` を組み合わせると、64 バイトの形式を 65 バイトの形式に変換できます。
ts import { compactSignatureToSignature, parseCompactSignature, recoverMessageAddress, serializeSignature, size } from "viem"; const sig = size(signature) === 64 ? serializeSignature(compactSignatureToSignature(parseCompactSignature(signature))) : signature; const signer = await recoverMessageAddress({ message, signature: sig }); - 2.
ウォレット全般には publicClient.verifyMessage を使う
パブリッククライアントは、EOA の署名をローカルで、スマートアカウントの署名を ERC-1271/ERC-6492 経由で検証するため、どの種類のウォレットにも同じコードで対応できます。
ts import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; // Handles EOAs, ERC-1271 smart accounts and ERC-6492 (undeployed) accounts. const client = createPublicClient({ chain: mainnet, transport: http(process.env.RPC_URL) }); const valid = await client.verifyMessage({ address, message, signature });