> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/zkp2p/zkp2p-contracts/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> Comprehensive overview of the ZKP2P v2.1 system architecture, core components, and user flow

## 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

<Note>
  The v2.1 architecture introduces a unified verification system that consolidates multiple payment method verifiers into a single, configurable contract, significantly reducing deployment complexity.
</Note>

## Architecture Diagram

```mermaid theme={null}
graph TB
    subgraph Users
        Maker[Maker/Liquidity Provider]
        Taker[Taker/Buyer]
        Relayer[Relayer/Gasless Service]
    end
    
    subgraph Core Contracts
        Escrow[Escrow Contract]
        Orchestrator[Orchestrator Contract]
        Verifier[Unified Payment Verifier]
    end
    
    subgraph Registry System
        PaymentReg[Payment Verifier Registry]
        EscrowReg[Escrow Registry]
        RelayerReg[Relayer Registry]
        HookReg[Post Intent Hook Registry]
        NullifierReg[Nullifier Registry]
    end
    
    subgraph External
        Attestation[Attestation Verifier]
        Hooks[Post Intent Hooks]
    end
    
    Maker -->|createDeposit| Escrow
    Taker -->|signalIntent| Orchestrator
    Relayer -->|signalIntent| Orchestrator
    Orchestrator -->|lockFunds| Escrow
    Orchestrator -->|getVerifier| PaymentReg
    Orchestrator -->|verifyPayment| Verifier
    Verifier -->|verify| Attestation
    Verifier -->|nullify| NullifierReg
    Orchestrator -->|unlockAndTransfer| Escrow
    Orchestrator -->|execute| Hooks
    Orchestrator -.validate.-> EscrowReg
    Orchestrator -.validate.-> RelayerReg
    Orchestrator -.validate.-> HookReg
```

## Core Components

### Escrow Contract

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

<CardGroup cols={2}>
  <Card title="Deposit Management" icon="vault">
    Creates, updates, and closes liquidity deposits with configurable parameters
  </Card>

  <Card title="Payment Method Config" icon="credit-card">
    Supports multiple payment methods per deposit with currency-specific rates
  </Card>

  <Card title="Intent Locking" icon="lock">
    Temporarily locks funds when takers signal intent to trade
  </Card>

  <Card title="Liquidity Reclaim" icon="clock-rotate-left">
    Automatically reclaims liquidity from expired intents
  </Card>
</CardGroup>

#### Key Responsibilities

<AccordionGroup>
  <Accordion title="Deposit Lifecycle Management">
    Makers can create deposits with specific parameters:

    ```solidity Escrow.sol (line 139) theme={null}
    function createDeposit(CreateDepositParams calldata _params) 
        external 
        whenNotPaused 
    {
        // Validates parameters
        if (_params.intentAmountRange.min == 0) revert ZeroMinValue();
        if (_params.amount < _params.intentAmountRange.min) {
            revert AmountBelowMin(_params.amount, _params.intentAmountRange.min);
        }
        
        // Creates deposit with unique ID
        uint256 depositId = depositCounter++;
        deposits[depositId] = Deposit({
            depositor: msg.sender,
            token: _params.token,
            intentAmountRange: _params.intentAmountRange,
            acceptingIntents: true,
            remainingDeposits: _params.amount,
            outstandingIntentAmount: 0,
            // ...
        });
        
        // Transfers tokens to escrow
        _params.token.safeTransferFrom(msg.sender, address(this), _params.amount);
    }
    ```

    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
  </Accordion>

  <Accordion title="Multi-Currency Support">
    Each deposit can accept multiple payment methods, and each method can support multiple currencies:

    ```solidity theme={null}
    // Example: Deposit supports Venmo and Revolut
    // Venmo accepts: USD (1:1 rate)
    // Revolut accepts: USD (1:1), EUR (1.2:1), GBP (1.3:1)

    mapping(uint256 => mapping(bytes32 => mapping(bytes32 => uint256))) 
        internal depositCurrencyMinRate;
    ```

    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
  </Accordion>

  <Accordion title="Intent Fund Locking">
    When a taker signals intent, the Orchestrator calls `lockFunds`:

    ```solidity Escrow.sol (line 557) theme={null}
    function lockFunds(
        uint256 _depositId, 
        bytes32 _intentHash,
        uint256 _amount
    ) 
        external
        onlyOrchestrator 
    {
        // Validates deposit state
        Deposit storage deposit = deposits[_depositId];
        if (!deposit.acceptingIntents) revert DepositNotAcceptingIntents(_depositId);
        
        // Reclaims expired intent liquidity if needed
        bytes32[] memory expiredIntents = _reclaimLiquidityIfNecessary(
            deposit, _depositId, _amount
        );
        
        // Locks liquidity
        deposit.remainingDeposits -= _amount;
        deposit.outstandingIntentAmount += _amount;
        
        // Creates intent with expiry
        uint256 expiryTime = block.timestamp + intentExpirationPeriod;
        depositIntents[_depositId][_intentHash] = Intent({
            intentHash: _intentHash,
            amount: _amount,
            timestamp: block.timestamp,
            expiryTime: expiryTime
        });
    }
    ```

    This ensures:

    * Liquidity is reserved for the specific intent
    * Intents expire after a configurable period
    * Expired intents are pruned to reclaim liquidity
  </Accordion>

  <Accordion title="Dust Collection & Deposit Closure">
    To prevent small leftover balances:

    ```solidity Escrow.sol (line 989) theme={null}
    function _closeDepositIfNecessary(uint256 _depositId, Deposit storage _deposit) 
        internal 
    {
        uint256 totalRemaining = _deposit.remainingDeposits;
        if (_deposit.outstandingIntentAmount == 0 && 
            totalRemaining <= dustThreshold && 
            !_deposit.retainOnEmpty) 
        {
            // Close deposit and sweep dust
            IERC20 token = _deposit.token;
            _closeDeposit(_depositId, _deposit);
            
            if (totalRemaining > 0) {
                token.safeTransfer(dustRecipient, totalRemaining);
                emit DustCollected(_depositId, totalRemaining, dustRecipient);
            }
        }
    }
    ```

    * Dust threshold prevents tiny balances from remaining
    * `retainOnEmpty` flag allows makers to keep deposit config
    * Protocol collects dust to avoid locked funds
  </Accordion>
</AccordionGroup>

### Orchestrator Contract

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

<CardGroup cols={2}>
  <Card title="Intent Coordination" icon="diagram-project">
    Manages intent creation, cancellation, and fulfillment
  </Card>

  <Card title="Payment Verification" icon="check-circle">
    Routes verification requests to appropriate verifiers
  </Card>

  <Card title="Fee Collection" icon="coins">
    Distributes protocol fees and referrer commissions
  </Card>

  <Card title="Hook Execution" icon="webhook">
    Executes optional post-intent hooks for custom logic
  </Card>
</CardGroup>

#### Intent Lifecycle

<Steps>
  <Step title="Signal Intent">
    Taker signals their intention to trade:

    ```solidity Orchestrator.sol (line 102) theme={null}
    function signalIntent(SignalIntentParams calldata _params)
        external
        whenNotPaused
    {
        // Validates intent parameters
        _validateSignalIntent(_params);
        
        // Calculates unique intent hash
        bytes32 intentHash = _calculateIntentHash();
        
        // Stores intent with all parameters
        intents[intentHash] = Intent({
            owner: msg.sender,
            to: _params.to,
            escrow: _params.escrow,
            depositId: _params.depositId,
            amount: _params.amount,
            paymentMethod: _params.paymentMethod,
            fiatCurrency: _params.fiatCurrency,
            conversionRate: _params.conversionRate,
            payeeId: depData.payeeDetails,
            timestamp: block.timestamp,
            referrer: _params.referrer,
            referrerFee: _params.referrerFee,
            postIntentHook: _params.postIntentHook
        });
        
        // Locks funds on escrow
        IEscrow(_params.escrow).lockFunds(_params.depositId, intentHash, _params.amount);
    }
    ```
  </Step>

  <Step title="Off-Chain Payment">
    Taker sends fiat payment through the specified payment platform (Venmo, PayPal, etc.) to the maker's payee details.

    <Note>
      This step happens entirely off-chain. The protocol does not control or monitor the payment itself.
    </Note>
  </Step>

  <Step title="Fulfill Intent">
    Anyone can submit payment proof to fulfill the intent:

    ```solidity Orchestrator.sol (line 184) theme={null}
    function fulfillIntent(FulfillIntentParams calldata _params) 
        external 
        nonReentrant 
        whenNotPaused 
    {
        Intent memory intent = intents[_params.intentHash];
        
        // Gets verifier from registry
        address verifier = paymentVerifierRegistry.getVerifier(intent.paymentMethod);
        
        // Verifies payment proof
        IPaymentVerifier.PaymentVerificationResult memory result = 
            IPaymentVerifier(verifier).verifyPayment(
                IPaymentVerifier.VerifyPaymentData({
                    intentHash: _params.intentHash,
                    paymentProof: _params.paymentProof,
                    data: _params.verificationData
                })
            );
        
        if (!result.success) revert PaymentVerificationFailed();
        
        // Unlocks and transfers funds
        IEscrow(intent.escrow).unlockAndTransferFunds(
            intent.depositId, 
            _params.intentHash, 
            result.releaseAmount, 
            address(this)
        );
        
        // Distributes fees and transfers to recipient
        _collectFeesTransferFundsAndExecuteAction(
            deposit.token,
            _params.intentHash,
            intent,
            result.releaseAmount,
            _params.postIntentHookData
        );
    }
    ```
  </Step>

  <Step title="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

    ```solidity Orchestrator.sol (line 475) theme={null}
    function _calculateAndTransferFees(
        IERC20 _token,
        Intent memory _intent, 
        uint256 _releaseAmount
    ) internal returns (uint256 netFees) {
        // Protocol fee (1% default)
        if (protocolFeeRecipient != address(0) && protocolFee > 0) {
            protocolFeeAmount = (_releaseAmount * protocolFee) / PRECISE_UNIT;
            _token.safeTransfer(protocolFeeRecipient, protocolFeeAmount);
        }
        
        // Referrer fee (up to 50%)
        if (_intent.referrer != address(0) && _intent.referrerFee > 0) {
            referrerFeeAmount = (_releaseAmount * _intent.referrerFee) / PRECISE_UNIT;
            _token.safeTransfer(_intent.referrer, referrerFeeAmount);
        }
        
        netFees = protocolFeeAmount + referrerFeeAmount;
    }
    ```
  </Step>
</Steps>

#### Intent Gating

Orchestrator supports optional signature-based gating:

```solidity Orchestrator.sol (line 428) theme={null}
address intentGatingService = IEscrow(_intent.escrow).getDepositGatingService(
    _intent.depositId, _intent.paymentMethod
);

if (intentGatingService != address(0)) {
    if (block.timestamp > _intent.signatureExpiration) {
        revert SignatureExpired(_intent.signatureExpiration, block.timestamp);
    }
    
    if (!_isValidIntentGatingSignature(_intent, intentGatingService)) {
        revert InvalidSignature();
    }
}
```

<Info>
  Gating allows makers to restrict who can take their liquidity, enabling compliance, KYC requirements, or whitelist-based access.
</Info>

### Unified Payment Verifier

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

#### Architecture Benefits

<CardGroup cols={2}>
  <Card title="Reduced Complexity" icon="compress">
    One contract instead of 8+ separate verifiers
  </Card>

  <Card title="Consistent Interface" icon="equals">
    Standardized verification across all payment methods
  </Card>

  <Card title="Easy Configuration" icon="sliders">
    Per-method settings without deploying new contracts
  </Card>

  <Card title="Lower Gas Costs" icon="gas-pump">
    Shared logic and optimized verification flow
  </Card>
</CardGroup>

#### Verification Flow

```solidity UnifiedPaymentVerifier.sol theme={null}
function verifyPayment(VerifyPaymentData calldata _data) 
    external 
    returns (PaymentVerificationResult memory) 
{
    // 1. Decode payment attestation (EIP-712 signed)
    PaymentAttestation memory attestation = abi.decode(
        _data.paymentProof, (PaymentAttestation)
    );
    
    // 2. Verify attestation signatures
    bool isValid = attestationVerifier.verifyAttestation(
        attestation.dataHash,
        attestation.signatures
    );
    if (!isValid) revert InvalidAttestation();
    
    // 3. Decode and validate payment details
    PaymentDetails memory payment = abi.decode(
        attestation.data, (PaymentDetails)
    );
    
    // 4. Verify payment matches intent
    IntentSnapshot memory intentSnap = _getIntentSnapshot(
        attestation.intentHash
    );
    
    if (payment.method != intentSnap.paymentMethod) revert MethodMismatch();
    if (payment.payeeId != intentSnap.payeeDetails) revert PayeeMismatch();
    if (payment.currency != intentSnap.fiatCurrency) revert CurrencyMismatch();
    
    // 5. Verify timestamp within buffer
    uint256 timeDiff = payment.timestamp - intentSnap.signalTimestamp;
    if (timeDiff > intentSnap.timestampBuffer) revert TimestampOutOfRange();
    
    // 6. Nullify payment to prevent double-spend
    nullifierRegistry.addNullifier(payment.paymentId);
    
    return PaymentVerificationResult({
        success: true,
        intentHash: attestation.intentHash,
        releaseAmount: attestation.releaseAmount
    });
}
```

<Warning>
  **Critical Security**: The nullifier registry prevents payment proofs from being reused. Each payment ID can only be used once across the entire protocol.
</Warning>

### Registry System

The registry system provides modular permission management:

<AccordionGroup>
  <Accordion title="Payment Verifier Registry">
    Maps payment methods to verifier contracts and supported currencies:

    ```solidity theme={null}
    // Payment method => Verifier address
    mapping(bytes32 => address) public verifiers;

    // Payment method => Currency => Supported
    mapping(bytes32 => mapping(bytes32 => bool)) public supportedCurrencies;

    function addPaymentMethod(
        bytes32 _method,
        address _verifier,
        bytes32[] calldata _currencies
    ) external onlyOwner {
        verifiers[_method] = _verifier;
        for (uint256 i = 0; i < _currencies.length; i++) {
            supportedCurrencies[_method][_currencies[i]] = true;
        }
    }
    ```

    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)
  </Accordion>

  <Accordion title="Escrow Registry">
    Whitelists valid escrow implementations:

    ```solidity theme={null}
    mapping(address => bool) public whitelistedEscrows;
    bool public acceptAllEscrows;  // Emergency flag

    function addEscrow(address _escrow) external onlyOwner {
        whitelistedEscrows[_escrow] = true;
    }
    ```

    This allows protocol upgrades without migrating all deposits.
  </Accordion>

  <Accordion title="Nullifier Registry">
    Globally tracks used payment proofs:

    ```solidity theme={null}
    mapping(bytes32 => bool) public usedNullifiers;

    function addNullifier(bytes32 _nullifier) external onlyVerifier {
        if (usedNullifiers[_nullifier]) revert AlreadyNullified();
        usedNullifiers[_nullifier] = true;
    }
    ```

    Prevents double-spending across all deposits and orchestrators.
  </Accordion>

  <Accordion title="Post Intent Hook Registry">
    Manages approved post-fulfillment hooks:

    ```solidity theme={null}
    mapping(address => bool) public whitelistedHooks;

    function addHook(address _hook) external onlyOwner {
        whitelistedHooks[_hook] = true;
    }
    ```

    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
  </Accordion>

  <Accordion title="Relayer Registry">
    Authorizes relayers for gasless transactions:

    ```solidity theme={null}
    mapping(address => bool) public whitelistedRelayers;

    function isWhitelistedRelayer(address _relayer) external view returns (bool) {
        return whitelistedRelayers[_relayer];
    }
    ```

    Relayers can signal multiple intents simultaneously for better UX.
  </Accordion>
</AccordionGroup>

### Protocol Viewer

A read-only contract for efficient state aggregation:

```solidity theme={null}
contract ProtocolViewer {
    function getDepositWithIntents(uint256 _depositId) 
        external 
        view 
        returns (
            IEscrow.Deposit memory deposit,
            bytes32[] memory intentHashes,
            IEscrow.Intent[] memory intents
        ) 
    {
        deposit = escrow.getDeposit(_depositId);
        intentHashes = escrow.getDepositIntentHashes(_depositId);
        
        intents = new IEscrow.Intent[](intentHashes.length);
        for (uint256 i = 0; i < intentHashes.length; i++) {
            intents[i] = escrow.getDepositIntent(_depositId, intentHashes[i]);
        }
    }
}
```

<Tip>
  Use Protocol Viewer for frontend queries to reduce RPC calls and improve performance.
</Tip>

## Complete User Flow

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

```mermaid theme={null}
sequenceDiagram
    participant Maker
    participant Taker
    participant Escrow
    participant Orchestrator
    participant Verifier
    participant Registry
    participant PaymentPlatform
    
    Maker->>Escrow: createDeposit(1000 USDC)
    Escrow-->>Maker: depositId
    
    Taker->>Orchestrator: signalIntent(100 USDC)
    Orchestrator->>Registry: validate escrow/method
    Orchestrator->>Escrow: lockFunds(100 USDC)
    Escrow-->>Orchestrator: locked
    
    Taker->>PaymentPlatform: Send $100 to Maker
    PaymentPlatform-->>Taker: Payment receipt
    
    Taker->>Attestation Service: Generate proof
    Attestation Service-->>Taker: EIP-712 signed attestation
    
    Taker->>Orchestrator: fulfillIntent(attestation)
    Orchestrator->>Verifier: verifyPayment(attestation)
    Verifier->>Registry: nullify paymentId
    Verifier-->>Orchestrator: valid (100 USDC)
    
    Orchestrator->>Escrow: unlockAndTransfer(100 USDC)
    Escrow-->>Orchestrator: 100 USDC
    
    Orchestrator->>Protocol: 1 USDC fee
    Orchestrator->>Taker: 99 USDC
```

### Step-by-Step Breakdown

<Steps>
  <Step title="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`.
  </Step>

  <Step title="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
  </Step>

  <Step title="Taker Sends Fiat Payment">
    Taker sends \$100 via Venmo to maker's payee details.

    <Note>
      This is a standard Venmo payment - no special protocol interaction required.
    </Note>
  </Step>

  <Step title="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
  </Step>

  <Step title="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
  </Step>

  <Step title="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.)
  </Step>
</Steps>

## Security Considerations

<CardGroup cols={2}>
  <Card title="Reentrancy Protection" icon="shield">
    All state-changing functions use OpenZeppelin's `ReentrancyGuard`
  </Card>

  <Card title="Pausable Contracts" icon="pause">
    Emergency pause functionality preserves fund recovery options
  </Card>

  <Card title="Access Control" icon="user-lock">
    Role-based permissions via Ownable and custom modifiers
  </Card>

  <Card title="Signature Validation" icon="signature">
    EIP-712 typed data and EIP-1271 contract signatures
  </Card>

  <Card title="Nullifier System" icon="ban">
    Global prevention of double-spending payment proofs
  </Card>

  <Card title="Intent Expiration" icon="clock">
    Time-bounded locks prevent indefinite liquidity freezing
  </Card>
</CardGroup>

### Pausable Functionality

Both Escrow and Orchestrator implement careful pause logic:

```solidity theme={null}
// PAUSED functions (for safety):
- createDeposit
- addFunds
- removeFunds
- signalIntent
- fulfillIntent

// ALWAYS AVAILABLE (for recovery):
- withdrawDeposit
- cancelIntent
- releaseFundsToPayer
- pruneExpiredIntents
```

<Warning>
  Pausing does NOT prevent users from recovering their funds. Withdrawal and cancellation remain available.
</Warning>

## Gas Optimization

The architecture includes several gas optimizations:

<AccordionGroup>
  <Accordion title="Compiler Settings">
    ```typescript theme={null}
    solidity: {
      version: "0.8.18",
      settings: {
        optimizer: { enabled: true, runs: 200 },
        viaIR: true  // Enables IR-based optimizer
      }
    }
    ```
  </Accordion>

  <Accordion title="Storage Packing">
    ```solidity theme={null}
    struct Deposit {
        address depositor;        // 20 bytes
        address delegate;         // 20 bytes
        IERC20 token;            // 20 bytes
        Range intentAmountRange; // 64 bytes
        bool acceptingIntents;   // 1 byte  
        // Packed into same slots where possible
    }
    ```
  </Accordion>

  <Accordion title="Batch Operations">
    Functions support array parameters to batch operations:

    ```solidity theme={null}
    function addPaymentMethods(
        bytes32[] calldata _paymentMethods,
        DepositPaymentMethodData[] calldata _paymentMethodData,
        Currency[][] calldata _currencies
    )
    ```
  </Accordion>

  <Accordion title="View Functions for State Aggregation">
    Protocol Viewer aggregates multiple reads:

    ```solidity theme={null}
    function getDepositWithIntents(uint256 _depositId)
        external view
        returns (
            Deposit memory deposit,
            bytes32[] memory intentHashes,
            Intent[] memory intents
        )
    ```
  </Accordion>
</AccordionGroup>

## Upgrade Path

The modular architecture supports upgrades without full migration:

<Steps>
  <Step title="Deploy New Components">
    Deploy updated contracts (e.g., OrchestratorV2, EscrowV2)
  </Step>

  <Step title="Register in System">
    Add new contracts to respective registries
  </Step>

  <Step title="Gradual Migration">
    * Old deposits remain on old Escrow
    * New deposits use new Escrow
    * Both can coexist using registry pattern
  </Step>

  <Step title="Update References">
    Point Orchestrator to new Escrow via `setEscrowRegistry()`
  </Step>
</Steps>

<Info>
  The registry pattern allows multiple versions to coexist, enabling gradual migration without disrupting active trades.
</Info>

## Extension Points

The architecture provides several extension points:

### Post Intent Hooks

Custom logic executed after intent fulfillment:

```solidity theme={null}
interface IPostIntentHook {
    function execute(
        IOrchestrator.Intent memory intent,
        uint256 amount,
        bytes memory data
    ) external;
}
```

Example: Across Bridge Hook automatically bridges USDC to another chain after fulfillment.

### Custom Verifiers

New payment methods via `IPaymentVerifier` interface:

```solidity theme={null}
interface IPaymentVerifier {
    function verifyPayment(VerifyPaymentData calldata data)
        external
        returns (PaymentVerificationResult memory);
}
```

### Delegate Management

Deposits can have delegates for automated management:

```solidity theme={null}
function setDelegate(uint256 _depositId, address _delegate) external;
```

Delegates can update rates, add currencies, and manage deposit config.

## Next Steps

<CardGroup cols={2}>
  <Card title="Contract API Reference" icon="book" href="/contracts/escrow">
    Detailed documentation for all contract interfaces
  </Card>

  <Card title="Integration Guide" icon="plug" href="/guides/creating-deposits">
    Learn how to integrate ZKP2P into your application
  </Card>

  <Card title="Smart Contracts" icon="file-contract" href="/contracts/escrow">
    Review core contract documentation and implementation details
  </Card>

  <Card title="Testing Guide" icon="flask" href="/guides/testing">
    Code examples and testing patterns for integration
  </Card>
</CardGroup>
