Skip to main content

System Overview

ZKP2P v2.1 implements a modular, intent-based architecture for trustless peer-to-peer fiat-to-crypto exchanges. The system consists of five main components that work together to facilitate secure, verifiable trades:
  1. Escrow Contract - Liquidity management and deposit custody
  2. Orchestrator Contract - Intent lifecycle coordination
  3. Unified Payment Verifier - Multi-platform payment validation
  4. Registry System - Permission and configuration management
  5. Protocol Viewer - Read-only state aggregation
The v2.1 architecture introduces a unified verification system that consolidates multiple payment method verifiers into a single, configurable contract, significantly reducing deployment complexity.

Architecture Diagram

Core Components

Escrow Contract

The Escrow contract manages liquidity deposits from makers (liquidity providers) and handles secure fund custody.

Deposit Management

Creates, updates, and closes liquidity deposits with configurable parameters

Payment Method Config

Supports multiple payment methods per deposit with currency-specific rates

Intent Locking

Temporarily locks funds when takers signal intent to trade

Liquidity Reclaim

Automatically reclaims liquidity from expired intents

Key Responsibilities

Makers can create deposits with specific parameters:
Escrow.sol (line 139)
Each deposit includes:
  • Token type (USDC)
  • Amount range for individual intents (min/max)
  • Supported payment methods and currencies
  • Optional delegate for deposit management
  • Optional intent guardian for expiry extensions
Each deposit can accept multiple payment methods, and each method can support multiple currencies:
This flexibility allows makers to:
  • Accept payments from multiple platforms
  • Support international currencies
  • Set custom conversion rates per currency
  • Update rates dynamically based on market conditions
When a taker signals intent, the Orchestrator calls lockFunds:
Escrow.sol (line 557)
This ensures:
  • Liquidity is reserved for the specific intent
  • Intents expire after a configurable period
  • Expired intents are pruned to reclaim liquidity
To prevent small leftover balances:
Escrow.sol (line 989)
  • Dust threshold prevents tiny balances from remaining
  • retainOnEmpty flag allows makers to keep deposit config
  • Protocol collects dust to avoid locked funds

Orchestrator Contract

The Orchestrator coordinates the entire intent lifecycle from creation to settlement.

Intent Coordination

Manages intent creation, cancellation, and fulfillment

Payment Verification

Routes verification requests to appropriate verifiers

Fee Collection

Distributes protocol fees and referrer commissions

Hook Execution

Executes optional post-intent hooks for custom logic

Intent Lifecycle

1

Signal Intent

Taker signals their intention to trade:
Orchestrator.sol (line 102)
2

Off-Chain Payment

Taker sends fiat payment through the specified payment platform (Venmo, PayPal, etc.) to the maker’s payee details.
This step happens entirely off-chain. The protocol does not control or monitor the payment itself.
3

Fulfill Intent

Anyone can submit payment proof to fulfill the intent:
Orchestrator.sol (line 184)
4

Settlement

Funds are distributed to all parties:
  1. Protocol Fee - Sent to protocol fee recipient
  2. Referrer Fee - Sent to referrer (if specified)
  3. Net Amount - Sent to taker or post-intent hook
Orchestrator.sol (line 475)

Intent Gating

Orchestrator supports optional signature-based gating:
Orchestrator.sol (line 428)
Gating allows makers to restrict who can take their liquidity, enabling compliance, KYC requirements, or whitelist-based access.

Unified Payment Verifier

The Unified Payment Verifier consolidates verification logic for all payment methods into a single contract.

Architecture Benefits

Reduced Complexity

One contract instead of 8+ separate verifiers

Consistent Interface

Standardized verification across all payment methods

Easy Configuration

Per-method settings without deploying new contracts

Lower Gas Costs

Shared logic and optimized verification flow

Verification Flow

UnifiedPaymentVerifier.sol
Critical Security: The nullifier registry prevents payment proofs from being reused. Each payment ID can only be used once across the entire protocol.

Registry System

The registry system provides modular permission management:
Maps payment methods to verifier contracts and supported currencies:
Supported payment methods:
  • Venmo (USD)
  • PayPal (USD, EUR, GBP)
  • Wise (USD, EUR, GBP, SGD, etc.)
  • Zelle (USD)
  • CashApp (USD)
  • Revolut (USD, EUR, GBP)
  • MercadoPago (BRL, ARS)
  • Monzo (GBP)
Whitelists valid escrow implementations:
This allows protocol upgrades without migrating all deposits.
Globally tracks used payment proofs:
Prevents double-spending across all deposits and orchestrators.
Manages approved post-fulfillment hooks:
Example hooks:
  • Across Bridge Hook - Automatically bridge USDC to another chain
  • Swap Hook - Convert USDC to another token
  • Multi-recipient Hook - Split payment among multiple addresses
Authorizes relayers for gasless transactions:
Relayers can signal multiple intents simultaneously for better UX.

Protocol Viewer

A read-only contract for efficient state aggregation:
Use Protocol Viewer for frontend queries to reduce RPC calls and improve performance.

Complete User Flow

Here’s the end-to-end flow with all components:

Step-by-Step Breakdown

1

Maker Deposits Liquidity

Maker calls Escrow.createDeposit() with:
  • 1000 USDC
  • Accepted payment methods (Venmo, PayPal)
  • Min/max intent amounts (10-500 USDC)
  • Supported currencies and rates
Escrow locks funds and assigns a unique depositId.
2

Taker Signals Intent

Taker calls Orchestrator.signalIntent() with:
  • Target deposit and amount (100 USDC)
  • Payment method (Venmo)
  • Currency (USD) and rate (1:1)
  • Recipient address
Orchestrator:
  1. Validates all parameters
  2. Generates unique intent hash
  3. Calls Escrow.lockFunds() to reserve liquidity
  4. Stores intent parameters for verification
3

Taker Sends Fiat Payment

Taker sends $100 via Venmo to maker’s payee details.
This is a standard Venmo payment - no special protocol interaction required.
4

Payment Proof Generation

Taker obtains payment receipt and sends to attestation service:
  1. Attestation service verifies payment via zkTLS
  2. Extracts payment details (amount, currency, payee, timestamp)
  3. Creates EIP-712 typed data structure
  4. Signs with trusted witness keys
  5. Returns attestation to taker
5

Taker Fulfills Intent

Taker (or relayer) calls Orchestrator.fulfillIntent() with attestation.Orchestrator:
  1. Retrieves intent parameters
  2. Gets verifier from payment registry
  3. Calls UnifiedPaymentVerifier.verifyPayment()
Verifier:
  1. Validates EIP-712 signatures
  2. Checks payment details match intent
  3. Verifies timestamp within buffer
  4. Nullifies payment ID
  5. Returns verification result
6

Settlement & Distribution

If verification succeeds:
  1. Orchestrator calls Escrow.unlockAndTransfer()
  2. Escrow transfers 100 USDC to Orchestrator
  3. Orchestrator deducts 1% protocol fee (1 USDC)
  4. Orchestrator transfers 99 USDC to taker
  5. Intent is pruned from both contracts
If post-intent hook specified:
  • Funds go to hook contract instead
  • Hook executes custom logic (bridge, swap, etc.)

Security Considerations

Reentrancy Protection

All state-changing functions use OpenZeppelin’s ReentrancyGuard

Pausable Contracts

Emergency pause functionality preserves fund recovery options

Access Control

Role-based permissions via Ownable and custom modifiers

Signature Validation

EIP-712 typed data and EIP-1271 contract signatures

Nullifier System

Global prevention of double-spending payment proofs

Intent Expiration

Time-bounded locks prevent indefinite liquidity freezing

Pausable Functionality

Both Escrow and Orchestrator implement careful pause logic:
Pausing does NOT prevent users from recovering their funds. Withdrawal and cancellation remain available.

Gas Optimization

The architecture includes several gas optimizations:
Functions support array parameters to batch operations:
Protocol Viewer aggregates multiple reads:

Upgrade Path

The modular architecture supports upgrades without full migration:
1

Deploy New Components

Deploy updated contracts (e.g., OrchestratorV2, EscrowV2)
2

Register in System

Add new contracts to respective registries
3

Gradual Migration

  • Old deposits remain on old Escrow
  • New deposits use new Escrow
  • Both can coexist using registry pattern
4

Update References

Point Orchestrator to new Escrow via setEscrowRegistry()
The registry pattern allows multiple versions to coexist, enabling gradual migration without disrupting active trades.

Extension Points

The architecture provides several extension points:

Post Intent Hooks

Custom logic executed after intent fulfillment:
Example: Across Bridge Hook automatically bridges USDC to another chain after fulfillment.

Custom Verifiers

New payment methods via IPaymentVerifier interface:

Delegate Management

Deposits can have delegates for automated management:
Delegates can update rates, add currencies, and manage deposit config.

Next Steps

Contract API Reference

Detailed documentation for all contract interfaces

Integration Guide

Learn how to integrate ZKP2P into your application

Smart Contracts

Review core contract documentation and implementation details

Testing Guide

Code examples and testing patterns for integration