Skip to content

fix: viem adapter must treat raw byte messages as raw in verifyMessage - #993

Open
gomesalexandre wants to merge 1 commit into
cowprotocol:mainfrom
gomesalexandre:fix_viem_verify_message_raw_bytes
Open

fix: viem adapter must treat raw byte messages as raw in verifyMessage#993
gomesalexandre wants to merge 1 commit into
cowprotocol:mainfrom
gomesalexandre:fix_viem_verify_message_raw_bytes

Conversation

@gomesalexandre

Copy link
Copy Markdown

ViemUtils.verifyMessage decoded a Uint8Array message as UTF-8 text via TextDecoder before recovering the signer, instead of passing it through to viem as raw bytes.

Any binary message that isn't valid UTF-8 - notably an order digest hashed for the ETHSIGN signing scheme and passed via decodeSignatureOwner (packages/contracts-ts/src/settlement.ts) - gets silently mangled by the UTF-8 decode (replacement characters on invalid byte sequences) before being re-hashed with the personal_sign prefix, so the recovered address never matches the real signer.

ViemSignerAdapter.signMessage already handles the identical Uint8Array case correctly, using viem's { raw: bytes } message form (packages/providers/viem-adapter/src/ViemSignerAdapter.ts:37-48) - so signing an ETHSIGN order with the viem adapter works fine, but verifying/recovering its owner does not. ethers-v5/ethers-v6's verifyMessage handle a Uint8Array as raw bytes natively, so this drift was viem-only.

Fix

Use { raw: message } for the Uint8Array branch in ViemUtils.verifyMessage, matching the convention ViemSignerAdapter.signMessage already uses.

Test

Added packages/contracts-ts/tests/decodeSignatureOwner.test.ts: signs a test order with the ETHSIGN scheme across all three adapters (ethers-v5, ethers-v6, viem) using the real per-adapter signer, then recovers the owner via decodeSignatureOwner and asserts it matches the signer's address.

  • Before this fix: fails only for the viem adapter (recovers an unrelated address instead of the real signer).
  • After this fix: passes for all three adapters.

No existing test exercised decodeSignatureOwner for the ETHSIGN scheme, or the viem adapter's raw-byte message path, at all - this was a real, silent, untested correctness gap in owner/signature verification specific to the viem adapter.

Risk

Low - verifyMessage's string branch is untouched; only the Uint8Array branch changes, from an incorrect UTF-8 decode to the raw-bytes form viem itself documents and that the adapter's own signer already uses.

ViemUtils.verifyMessage decoded a Uint8Array message as UTF-8 text via
TextDecoder before recovering the signer, instead of passing it through
as raw bytes. Any binary message that isn't valid UTF-8 - notably an
order digest hashed for ETHSIGN and passed via decodeSignatureOwner -
gets silently mangled, so the recovered address never matches the real
signer. ViemSignerAdapter.signMessage already handles the identical
Uint8Array case correctly via viem's `{ raw }` form; verifyMessage just
never got the same treatment, and ethers-v5/v6 verifyMessage handle
Uint8Array as raw bytes natively, so the drift was viem-only.

Adds a regression test that signs an order with ETHSIGN across all
three adapters and recovers the owner via decodeSignatureOwner - it
only fails for viem on the old code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 14 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 0c7e3d85-3ffc-470e-b5ea-5e25ca845fde

📥 Commits

Reviewing files that changed from the base of the PR and between 9057b6d and 23a44df.

📒 Files selected for processing (2)
  • packages/contracts-ts/tests/decodeSignatureOwner.test.ts
  • packages/providers/viem-adapter/src/ViemUtils.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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