Skip to content

Conversation

ernestognw
Copy link
Member

@ernestognw ernestognw commented Aug 10, 2025

This PR streamlines the ZKEmailUtils by receiving an EmailProof directly instead of an EmailAuthMsg struct. From the original struct, the templateId was unused and not included in the proof so anyone can construct the expected value, so it was removed.

On the SignerZKEmail and ERC7913ZKEmailVerifier side, their implementation was simplified following changes in ZKEmailUtils.

Key Changes:

  • Remove templateId and skippedCommandPrefix functionality across all ZKEmail contracts
  • Add robust tryDecodeEmailProof function for safe calldata decoding with comprehensive bounds checking
  • Update signature encoding in tests to use direct EmailProof field encoding
  • Maintain security through existing DKIM verification and zero-knowledge proof validation

The simplified implementation reduces complexity while preserving all essential security guarantees.

@ernestognw ernestognw changed the title Chore/zkemail emailproof Refactor ZKEmailUtils toPubSignals to receive an EmailProof Aug 10, 2025
@ernestognw ernestognw changed the title Refactor ZKEmailUtils toPubSignals to receive an EmailProof @ernestognw Remove templateId and simplify EmailProof validation in ZKEmailUtils Aug 10, 2025
@ernestognw ernestognw changed the title @ernestognw Remove templateId and simplify EmailProof validation in ZKEmailUtils Remove templateId and simplify EmailProof validation in ZKEmailUtils Aug 10, 2025
@ernestognw ernestognw changed the title Remove templateId and simplify EmailProof validation in ZKEmailUtils Remove templateId and simplify EmailProof validation in ZKEmailUtils Aug 10, 2025
@ernestognw ernestognw marked this pull request as ready for review August 10, 2025 22:21
@ernestognw ernestognw requested review from zkfriendly, benceharomi and a team as code owners August 10, 2025 22:21
@ernestognw ernestognw mentioned this pull request Aug 10, 2025
zkfriendly
zkfriendly previously approved these changes Aug 12, 2025
Copy link
Collaborator

@zkfriendly zkfriendly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the simplification. Removing templateId and skippedCommandPrefix makes sense to me here. Other changes also look good to me.

* NOTE: The returned `emailProof` object should not be accessed if `success` is false. Trying to access the data may
* cause revert/panic.
*/
function tryDecodeEmailProof(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious to know what the main benefit of these checks is? Looking at the places where this is used, there is always a call to isValidZKEmail, which will reject a malformed EmailProof either by failing to pass the zk-proof checks (including DKIM checks and command matching) or by reverting somewhere. However, it does help to revert early if EmailProof is not a valid struct. So basically would these be redundant checks for valid EmailProofs? or is there some other attack vector if these checks are not in place?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great observation! In summary, yes, the tryDecodeEmailProof is redundand if the bytes buffer correctly decodes to EmailProof. However, we try to avoid reverting in functions that may be part of an ERC-4337 user op validation flow for 2 reasons:

  1. It would affect the reputation of the account if it reverts (anyone can send undecodable EmailProofs).
  2. To force readability into the signature, we recommend ERC-7739. However, it has a detection mechanism that passes an empty buffer to the signer. If the account can't differentiate a valid struct vs an empy bytes buffer it will revert and detection wouldn't be possible

I think using tryDecodeEmailProof is acceptable in both the signer and the verify since it's only performing calldata slices (not memory copies) and simple JUMP/JUMPI operations. The overhead shouldn't be a big deal.

@ernestognw ernestognw merged commit b0c00eb into master Aug 14, 2025
9 of 10 checks passed
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.

2 participants