ERC-7964: Cross-Chain Signatures for Account Abstraction

Hi everyone! :wave:

Following up on ERC-7803, I’ve drafted ERC-7964: Universal Cross-Chain Signatures for Account Abstraction - a simple extension that enables cross-chain signatures using chainId: 0.

Concept

One rule: chainId: 0 in signing domains = valid on any chain

This allows users to sign once and authorize operations across multiple networks - perfect for cross-chain intents, multi-chain DAO voting, and unified account management.

ERC

1 Like

Thanks @ernestognw — really cool proposal!

One important consideration I’d like to raise:

While chainId: 0 for universal signatures simplifies UX, things may get tricky with Smart Contract Accounts (SCAs) or custom wallet logic.

For example:

  • Contract code may differ across chains (even if the interface is similar).
  • A signature that passes isValidSignature() on one chain might fail or behave differently on another.
  • If contract state (e.g. owner, nonce, or permissions) has diverged across chains, security assumptions break down.

So I’m wondering:
How do we mitigate risks where same signature = valid on one chain but unsafe on another?

Would love to hear thoughts on whether:

  • A checksum of the deployed bytecode should be embedded in the domain separator?
  • We need chain-specific overrides for contracts with isChainAware() logic?

Really appreciate the simplicity this introduces for users, AA kits, Devs.

1 Like

Hey @codebyMoh! Thanks for the the thoughtful feedback!

On scope: You’re absolutely right about the complexity with SCAs. This ERC intentionally focuses on being a simple building block rather than solving cross-chain authentication holistically. The chainId: 0 pattern gives us universal signature validity, but the verification semantics are left to the implementation layer.

On your specific concerns:

  • Code differences: This feels like wallet/dapp responsibility to me. Wallets should warn users when signing for contracts with different bytecode across chains, and dapps should validate contract compatibility before accepting signatures. The standard can’t enforce this on already-deployed implementations, but we should definitely call it out in Security Considerations.

  • State divergence: Similar reasoning - this is where higher-level coordination mechanisms come into play. Things like keystore rollups or dedicated state sync protocols could address this, but probably warrant their own ERCs.

On “unsafe” signatures: I’d love to hear your definition here. In my view, a signature is “unsafe” when it authorizes unintended actions. But with proper wallet UX (showing exactly what’s being signed on each chain) and dapp validation (checking contract compatibility), the risk becomes manageable.

On your solutions: The bytecode checksum idea is elegant! But I lean toward leaving these patterns to implementations rather than standardizing them here. Different use cases might want different safety mechanisms - some might prefer your checksum approach, others might want state synchronization, etc.

Hope this framing makes sense! Curious to hear your thoughts

1 Like

@ernestognw Your framing makes a lot of sense — especially treating this as a foundational primitive rather than a full authentication framework. I agree that universal signature validity is a powerful enabler, and implementation-level flexibility is key.

On “unsafe” signatures:
Yes, totally agree with your definition — signatures are “unsafe” when they authorize unintended actions. I think the risk amplifies in scenarios where contracts diverge in state or logic but remain address-aligned across chains. So UX + validation are critical — maybe the standard could recommend (non-mandate) checksum practices or at least link to best practices in Security Considerations?

On state divergence:
Right, it’s out of this ERC’s scope, but might be worth noting that coordination layers (e.g., keystore rollups, state pinning, chain-specific guards) become almost essential in high-stakes use cases like governance or treasury control.

On modular safety:
Totally fair to defer specific safety patterns to use case–specific implementations. Maybe we could treat the chainId: 0 concept as an interface layer and publish optional “safety modules” alongside it — like a checksum utility, signer attestations, or bytecode validation hooks?

All in all, loving the direction — this could become a key building block for cross-chain AA architecture. Happy to brainstorm or co-contribute to supporting standards or tooling around it if useful.

Thanks for the feedback, @codebyMoh!

maybe the standard could recommend (non-mandate) checksum practices or at least link to best practices in Security Considerations?

I’m hesitant to recommend unproven patterns, and I’m not sure if I would recommend this approach. I think it’s preferable to see real-world usage to inform safety practices rather than speculating upfront.

but might be worth noting that coordination layers (e.g., keystore rollups, state pinning, chain-specific guards) become almost essential in high-stakes use cases like governance or treasury control.

Absolutely agree these become essential for high-stakes use cases. However, I see this as a natural architectural consequence rather than something this ERC should prescribe. Imo, different use cases will have vastly different coordination requirements.

publish optional “safety modules” alongside it — like a checksum utility, signer attestations, or bytecode validation hooks?

While I appreciate the modular thinking, I’m concerned about scope creep. The strength of chainId: 0 is its simplicity. I’d rather see future ERCs build specialized safety frameworks on this foundation if demand emerges. Also happy to provide feedback if such standards appear

1 Like

@frangio pointed out (accurately) that all domains fields are optional. Citing from EIP-712

Protocol designers only need to include the fields that make sense for their signing domain.

So it may be clever to rework this ERC as just omitting the chainId field.

Hey everyone! Thanks for the feedback so far, especially @frangio’s point about omitting chainId instead of using 0. I’ve substantially reworked ERC-7964 based on this and other considerations.

Key Changes

1. Omit chainId instead of using 0
Following @frangio’s suggestion, the ERC now simply omits chainId from the root EIP712Domain since all fields are optional per EIP-712. Much cleaner semantics!

2. Dropped ERC-7803 dependency
The proposal now uses only standard EIP-712 encoding - no draft standards required. This means existing wallets can support it immediately without implementing custom logic.

3. Array-based encoding over Merkle trees
Cross-chain operations are encoded as standard EIP-712 arrays. While proposals like EIL use Merkle trees, I’ve opted for arrays because:

  • For 2-5 chains (typical case), Merkle trees save only 32-64 bytes
  • Arrays provide full transparency in standard wallet UIs - users see all operations
  • Merkle trees require custom wallet logic to verify leaves aren’t malicious

4. Introduced EIP712ChainDomain pattern
Each chain-specific operation includes a nested domain with chainId and optionally verifyingContract. This handles both:

  • Same address deployments (CREATE2) → root domain has verifyingContract
  • Different address deployments → nested domains have verifyingContract

Updated Examples

All four reference implementations now demonstrate both deployment patterns and include reference on-chain verification code.

Would love feedback on this simplified approach! Does the array encoding trade-off (transparency vs. minimal extra overhead) make sense for the typical 2-5 chain use case?