x402 supports Permit2-based payments alongside EIP-3009, via permitWitnessTransferFrom on the canonical Permit2 contract and the x402 Permit2 proxy. Permit2 is a different signing scheme, not a variant of the existing partition: its EIP-712 domain uses the canonical Permit2 contract as verifying contract rather than the token, it signs a PermitTransferFrom struct instead of TransferWithAuthorization, it uses unordered nonce bitmaps instead of 32-byte random nonces, and it carries a single deadline instead of a validAfter/validBefore window. It therefore enters the corpus as a new scheme partition with its own vector namespace, reason-code mapping, and generator path. kanon-gen and kanon-core must not share the new EIP-712 plumbing, per the independent-implementations rule.
Candidate failure modes, each needing cited provenance before a vector exists:
- wrong Permit2 domain (chainId or verifying contract), resolving to
SIGNER_MISMATCH.
- nonce bitmap replay, the Permit2 analogue of
NONCE_REPLAY.
- expired
deadline, mapping to EXPIRED.
- signed amount below required amount,
AMOUNT_INSUFFICIENT.
Notes on codes that do not carry over cleanly:
SIG_MALLEABLE does not apply as-is. Permit2's SignatureVerification does not enforce the EIP-2 low-s rule and accepts high-s signatures that recover correctly. If covered at all, it is as a documented divergence from the EIP-3009 lane, not a shared rejection rule.
- Base Permit2 has no start time, so there is no
NOT_YET_VALID analogue at the Permit2 layer. The x402 proxy's witness struct does carry a validAfter, so the code may reappear at the proxy layer. To be settled in the spec work.
Open questions to settle in the spec work:
- whether verification targets the bare Permit2 signature or the proxy witness structure, which determines the reason-code surface.
- how the vector
id and encodes conventions extend to the new partition.
x402 supports Permit2-based payments alongside EIP-3009, via permitWitnessTransferFrom on the canonical Permit2 contract and the x402 Permit2 proxy. Permit2 is a different signing scheme, not a variant of the existing partition: its EIP-712 domain uses the canonical Permit2 contract as verifying contract rather than the token, it signs a
PermitTransferFromstruct instead ofTransferWithAuthorization, it uses unordered nonce bitmaps instead of 32-byte random nonces, and it carries a singledeadlineinstead of avalidAfter/validBeforewindow. It therefore enters the corpus as a new scheme partition with its own vector namespace, reason-code mapping, and generator path. kanon-gen and kanon-core must not share the new EIP-712 plumbing, per the independent-implementations rule.Candidate failure modes, each needing cited provenance before a vector exists:
SIGNER_MISMATCH.NONCE_REPLAY.deadline, mapping toEXPIRED.AMOUNT_INSUFFICIENT.Notes on codes that do not carry over cleanly:
SIG_MALLEABLEdoes not apply as-is. Permit2's SignatureVerification does not enforce the EIP-2 low-s rule and accepts high-s signatures that recover correctly. If covered at all, it is as a documented divergence from the EIP-3009 lane, not a shared rejection rule.NOT_YET_VALIDanalogue at the Permit2 layer. The x402 proxy's witness struct does carry avalidAfter, so the code may reappear at the proxy layer. To be settled in the spec work.Open questions to settle in the spec work:
idandencodesconventions extend to the new partition.