Skip to content

3.3: migrate signBalanceRead to the EIP-712 chainId domain#18

Open
ameya-deshmukh wants to merge 2 commits into
zellic-audit-may-2026from
ameya/zellic-audit-may-2026-3.3
Open

3.3: migrate signBalanceRead to the EIP-712 chainId domain#18
ameya-deshmukh wants to merge 2 commits into
zellic-audit-may-2026from
ameya/zellic-audit-may-2026-3.3

Conversation

@ameya-deshmukh

Copy link
Copy Markdown
Contributor

Downstream of seismic monorepo #209 (Zellic finding 3.3). Contract PR #209 changed SRC20.balanceOfSigned's signature scheme from a personal-sign message to an EIP-712 typed-data digest bound to chainId. This repo's TS signer still built the old scheme, so signed reads would recover the wrong address and revert on require(signer == owner). This PR migrates the signer.

Scheme change (must match contract #209 byte-for-byte)

  • Old: personal-sign over keccak256(abi.encodePacked("SRC20_BALANCE_READ", owner, expiry)).
  • New: EIP-712, token-agnostic domain (no verifyingContract, no salt):
    domainSeparator = keccak256(abi.encode(
        keccak256("EIP712Domain(string name,string version,uint256 chainId)"),
        keccak256("SRC20BalanceRead"), keccak256("1"), chainId))
    structHash      = keccak256(abi.encode(
        keccak256("BalanceRead(address owner,uint256 expiry)"), owner, expiry))
    digest          = keccak256(0x1901 ‖ domainSeparator ‖ structHash)
    

Changes

  • packages/batch-read-ts/src/util/signature.tssignBalanceRead rewritten to use viem signTypedData producing the EIP-712 digest above.
  • Signature change: signBalanceRead now takes a required chainId argument (the domain is chain-bound). Breaking for any external caller.
  • packages/batch-read-ts/src/index.ts — the sole in-repo caller now passes chain.id.

Test plan (test-first)

  • test: commit adds signature.test.ts reconstructing the EIP-712 digest by formula for a fixed (owner, expiry, chainId), signing a known key, and asserting recoverAddress(digest, sig) == owner. Fails on the old personal-sign scheme (recovers a different address), passes on the new one.
  • bun test green; prettier --check clean.

Note — stale vendored contract (not fixed here)

packages/contracts/dependencies/seismic-std-lib-0.1.3/SRC20.sol:253 still implements the old personal-sign scheme. That belongs to the upstream seismic-std-lib version bump (the std-lib tracker's 3.3 propagation), not this TS-signer migration. Flagging so it isn't missed — deploying this signer against the stale vendored contract would revert until the dependency is bumped to the #209 release.

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