Document the signing change for EIP-7702 senders - #62
Merged
ernestognw merged 2 commits intoAug 19, 2026
Conversation
The signed `initCode` field is no longer `userOp.initCode` for EIP-7702 senders: the paymaster substitutes the delegate installed at the sender, so a signer passing the raw marker produces a digest the paymaster rejects. Add an `effectiveInitCode` helper to the paymasters guide and point the signing example at it. Raise the changeset to minor and state that signing services must be updated in lockstep, since nothing about this surfaces at compile time.
|
| Name | Type |
|---|---|
| openzeppelin-solidity | Minor |
Click here to learn what changesets are, and how to add one.
Click here if you're a maintainer who wants to add a changeset to this PR
ernestognw
approved these changes
Aug 19, 2026
ernestognw
merged commit Aug 19, 2026
e5c4f1b
into
ernestognw:docs/paymaster-signer-eip7702-note
10 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on top of
docs/paymaster-signer-eip7702-note(OpenZeppelin#6673). Docs + changeset only — no contract or test changes.Why
PaymasterSigner._signableUserOpHashnow substitutes the effective EIP-7702 delegate for theinitCodecomponent of the digest. The typed-data struct still declaresbytes initCode, so nothing about this surfaces at compile time — but the value a signer must put in that field changed.docs/modules/ROOT/pages/paymasters.adocstill told integrators to signinitCode: userOp.initCode, which for an EIP-7702 sender now yields a digest the paymaster rejects. Every existing signing service that sponsors EIP-7702 senders breaks at runtime, silently.Changes
docs/modules/ROOT/pages/paymasters.adoc— new=== Signing for EIP-7702 senderssubsection with aneffectiveInitCodehelper, and the signing example now calls it instead of passinguserOp.initCode. Includes a warning that a sponsorship signature stops being valid once the delegate is replaced (deliberate), so signing services must readsender.codeat signing time rather than caching a digest..changeset/paymaster-signer-eip7702-delegate-binding.md—patch→minor, plus an explicit note that signing services must be updated in lockstep.The
GuaranteedUserOperationexample further down the same page is deliberately left alone: it is a separate custom paymaster with its own typehash that hasheskeccak256(userOp.initCode)in Solidity and signs the rawinitCodein TS. It is internally consistent and not obliged to mirrorPaymasterSigner.Verification
The helper was checked against the contract rather than written from reading it. The same logic was ported to ethers and
keccak256(effectiveInitCode(...))compared againstPaymasterSigner._effectiveInitCodeHashfor six inputs —0x,0x77,0x7702,0x770200, marker +deadbeef, and a nonzero-tail factory address (0x7702aabb…). All six match, including the empty and 1-byte edges where the marker comparison relies on zero-padding.Caveat: the snippet in the docs is viem, matching the rest of the file, and is not executed by CI. The viem and ethers forms are structurally identical (
size/slice/padHexvsdataLength/dataSlice/zeroPadBytes), so the translation is mechanical, but it is worth a careful read.Open question for the maintainer
The
minorbump is a judgement call and yours to make. There is no Solidity signature or storage-layout change, so it is not amajorby the usual test, but it does break working offchain integrations with no compile-time signal. Revert topatchif the project treats digest changes differently.