Skip to main content

Attestation Service

The Attestation Service validates payment evidence off-chain and returns a standardized, signed EIP-712 PaymentAttestation that the on-chain UnifiedPaymentVerifierV3 can verify.

Base URLs

  • Production: https://attestation-service.zkp2p.xyz (Base mainnet, runs inside an AWS Nitro Enclave)
  • Local dev: http://localhost:8080

Main Surfaces​

  • Enclave attestation: clients verify the running Nitro Enclave before trusting signatures or encrypting session material.
  • Identity registration: clients prove a live payment-platform identity before curator registration.
  • Buyer TEE verification: the current buyer flow for supported payment methods.
  • Buyer proof verification: generic buyer-generated provider proof verification.
  • Dispute verification: DKIM-authenticated Venmo or PayPal dispute emails produce a separate DisputeAttestation.
  • Seller Autopilot: seller-side credential bundle upload and payment resolution.

Trust model​

The identity (/identity), buyer proof (/verify/*), buyer TEE (/buyer/verify/*), and seller-side (/seller/*) flows run inside an AWS Nitro Enclave. The code that validates evidence, checks payment or identity invariants, and signs EIP-712 outputs executes inside the enclave.

  • The EIP-712 signing key is wrapped by an AWS KMS Customer Managed Key whose decrypt policy is gated on the enclave's PCR8 measurement. The key is unwrapped in enclave memory at first use and never leaves the enclave; no operator, AWS, or attacker outside the enclave can extract it.
  • Build artifacts (PCR0/PCR1/PCR2/PCR8) are reproducible from the published source tree. The expected signer address and PCR8 are baked into the enclave image and returned by /attestation alongside the NSM document.
  • Clients can verify the attestation document and PCR8 match the published values before encrypting session material or trusting any signed PaymentAttestation. Reference verifier: @zkp2p/zkp2p-attestation.
  • On-chain, the enclave's signer is registered as a witness on MultiAttestationVerifier. Signatures from any other key are rejected at fulfillIntent.

The previous (legacy) deployment ran the same code on commodity infrastructure with the signing key held in plaintext environment variables; that deployment is sunsetted and the canonical hostname now points at the enclave.

Verification Paths​

Buyer TEE​

Buyer TEE is the current buyer verification flow for supported platforms. The buyer client verifies the Nitro enclave, encrypts payment-platform session material to the attested upload key, and sends that encrypted material with public provider params and the intent snapshot. The enclave decrypts in memory, contacts the payment platform over HTTPS, validates and normalizes the response, runs UnifiedPaymentVerifier, and signs the result with source tag buyer-tee.

Buyer TEE supports Venmo, Cash App, Monzo, Wise, Revolut, Chime, Chase Zelle, Bank of America Zelle, Citi Zelle, PayPal Personal, and PayPal Business. See Buyer TEE Verification for the high-level flow and security model.

Buyer Proof Verification​

This generic path accepts buyer-generated provider proofs, transforms extracted proof context into normalized payment details, runs UnifiedPaymentVerifier, and signs the result. It remains part of the Attestation Service surface, but supported buyer payment methods should use Buyer TEE.

Identity Registration​

Identity registration proves a live platform identity and returns a signed EIP-712 IdentityAttestation. The request shape is:

POST {attestationServiceUrl}/identity
{
platform: 'venmo',
actionType: 'register_venmo',
callerAddress: '0x0000000000000000000000000000000000000002',
encryptedSessionMaterial: '<compact-jwe>',
params: { SENDER_ID: '123456789' },
}

Supported identity actions:

PlatformAction typeEncrypted session materialPublic params
venmoregister_venmoCookieSENDER_ID
paypalregister_paypalCookienone
wiseregister_wiseCookie, X-Access-TokenPROFILE_ID
cashappregister_cashappsessionCookie, requestPayload, optional requestHeadersnone
alipayregister_alipayCookienone

callerAddress is required and remains part of the signed IdentityAttestation, but public maker registration does not authenticate or compare it to a linked wallet. Verification still checks platform, action type, payee hash, canonical identity dataHash, signature, and validUntil.

For Venmo, the current service derives the stories replay URL from public params.SENDER_ID; clients should not encrypt or send a captured sessionMaterial.url. The encrypted Venmo identity session material only needs a replayable Cookie header. The enclave verifies the authenticated account id before replaying https://account.venmo.com/api/stories?feedType=me&externalId={SENDER_ID} and requires a valid response with a stories array.

Cash App identity uses the canonical MY_ACTIVITY_WEB_V2 request body in encrypted sessionMaterial.requestPayload and the replayable cookie in sessionMaterial.sessionCookie. Public params is {}. The service, SDK, and app each have their own platform capabilities; an identity endpoint alone does not establish availability in the web buy flow.

Dispute Verification​

GET /dispute/supported lists the service's dispute verifiers. POST /dispute/verify/venmo/dispute_venmo and POST /dispute/verify/paypal/dispute_paypal accept { encryptedSessionMaterial, params: {}, chainId, intentHash }. Encrypt the complete RFC 5322 email as sessionMaterial: { rawEmail }; the enclave verifies its DKIM signature and extracts the original payment and dispute identifiers.

Use createNitroAttestationClient().verifyDispute() from @zkp2p/zkp2p-attestation@3.1.0 with the appropriate client options. Verify the returned signature and typed data with verifyDisputeAttestation(), including the expected intent and DisputeVerifier domain. The service resolves DisputeVerifier from its deployment configuration. This output is a DisputeAttestation, not a payment proof for fulfillIntent.

Seller Autopilot​

Seller Autopilot uses encrypted seller credential bundles to resolve matching payments from the seller side. It shares the same verifier and attestation output shape. See Seller Autopilot.

Shared Output​

Payment verification paths return a signed EIP-712 PaymentAttestation. The response includes the signer, signature, typed attestation values, encoded payment details, and metadata identifying the source path. The client packages that attestation as paymentProof and calls OrchestratorV3.fulfillIntent for current intents.

Identity registration returns a signed EIP-712 IdentityAttestation plus normalized identity details:

{
identity: {
platform,
actionType,
method,
payeeId,
payeeIdHash,
username,
metadata,
},
typedDataValue: {
method,
actionType,
callerAddress,
payeeIdHash,
dataHash,
issuedAt,
validUntil,
},
signature,
signer,
}

Identity attestations are used by registration APIs and are not submitted to OrchestratorV3.fulfillIntent.

Choosing chainId and verifyingContract​

  • chainId must match the destination chain where UnifiedPaymentVerifierV3 lives.
  • verifyingContract is deprecated in API requests. The service resolves the on-chain UnifiedPaymentVerifierV3 address from chainId (0xC6F4a193576C60892a47e111Bb5706c30162502B on Base). If callers still include verifyingContract, it must match the service-resolved address.