# zkVerify, Horizen & Base Integration

## Overview

PolyPay uses multiple blockchain layers for privacy-preserving multisig operations:

* [**zkVerify**](https://docs.zkverify.io/): Verifies zero-knowledge proofs off-chain (UltraHonk for new accounts, UltraPlonk for legacy accounts), providing proof verification and aggregation as a service
* [**Horizen**](https://www.horizen.io/): EVM-compatible L3 blockchain where multisig accounts (`MetaMultiSigWallet` contracts) are deployed and transactions are executed
* [**Base**](https://base.org/): EVM-compatible L2 blockchain, also supported as a destination chain for account deployment and transaction execution

> **"Destination Chain"** refers to the EVM chain where the multisig account is deployed — either **Horizen** (L3, chain ID 26514) or **Base** (L2, chain ID 8453). The user selects the destination chain when creating an account, and all subsequent operations for that account happen on the same chain.

## Blockchain Classification

| Action          | Blockchain              | Description                                                                                                                                                      |
| --------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| LOGIN           | zkVerify                | ZK auth proof verified on zkVerify                                                                                                                               |
| CREATE\_ACCOUNT | Horizen or Base         | `MetaMultiSigWallet` contract deployed on the chosen destination chain                                                                                           |
| PROPOSE         | zkVerify                | Creates a new transaction (TRANSFER, BATCH\_TRANSFER, ADD\_SIGNER, REMOVE\_SIGNER, or UPDATE\_THRESHOLD) and submits the creator's ZK approval proof to zkVerify |
| APPROVE         | zkVerify                | Signer's approval proof submitted to zkVerify                                                                                                                    |
| DENY            | None                    | Off-chain vote, no proof or on-chain interaction                                                                                                                 |
| EXECUTE         | zkVerify + Horizen/Base | Proofs aggregated on zkVerify, then executed on the destination chain                                                                                            |

## Architecture

![Architecture Flow](/files/pScbkiymyuE71Kjoa2st)

## Flows

### 1. Authentication (LOGIN)

User proves ownership of their membership ID without revealing the secret.

![Authentication Flow](/files/oP1dlrioGATCS4hXxKyw)

* **zkVerify**: Verify proof (UltraHonk or UltraPlonk based on account version), return `jobId` and `zkVerifyTxHash`
* **Destination chain**: No interaction

### 2. Account Creation (CREATE\_ACCOUNT)

Deploy a new multisig account on the chosen destination chain (Horizen or Base).

![Account Creation Flow](/files/5R3JJMC6tljgKFDmsvpb)

* **zkVerify**: No interaction
* **Destination chain (Horizen or Base)**: Deploy `MetaMultiSigWallet` contract

### 3. Transaction Lifecycle

#### Propose & Approve

When a user proposes a transaction, they automatically approve it. Other signers can then approve.

![Approve Flow](/files/oLqo5RiD8enMR8Hf6RDj)

* **zkVerify**: Verify proof, return `jobId`
* **Destination chain**: No interaction

#### Deny

Deny is simply a "disagree" vote — no proof required, no on-chain interaction.

![Deny Flow](/files/J17bpM3YcesSaN7isn7m)

* **zkVerify**: No interaction (no proof needed)
* **Destination chain**: No interaction (no gas cost)

#### Execute

When threshold is met, execute the transaction on the destination chain (Horizen or Base) using aggregated proofs.

![Execute Flow](/files/D64YEiic0N2X4ef5JJ8J)

* **zkVerify**: Provide aggregation data (merkle proofs) from job-ids
* **Destination chain (Horizen or Base)**: Verify aggregated proofs + execute transaction

### 4. Transaction Types

All transaction types follow the same Propose → Approve → Execute flow:

| Type              | Description                                             |
| ----------------- | ------------------------------------------------------- |
| TRANSFER          | Transfer ETH or ERC20 tokens to a recipient             |
| BATCH\_TRANSFER   | Transfer tokens to multiple recipients in one execution |
| ADD\_SIGNER       | Add new signer(s) to the multisig                       |
| REMOVE\_SIGNER    | Remove signer(s) from the multisig                      |
| UPDATE\_THRESHOLD | Change the M-of-N approval threshold                    |

## Proof Lifecycle

Each ZK proof goes through the following states on zkVerify:

```
PENDING → IncludedInBlock → AggregationPending → Aggregated
                                                      ↓
                                              Ready for execute()
```

## Kurier API

[Kurier](https://docs.zkverify.io/overview/getting-started/kurier) is a REST API service built by Horizen Labs that simplifies proof verification on zkVerify. Instead of interacting directly with the zkVerify blockchain, PolyPay uses Kurier to submit and track proofs.

### How PolyPay Uses Kurier

| Step            | Kurier Endpoint           | Description                                  |
| --------------- | ------------------------- | -------------------------------------------- |
| 1. Register VK  | `POST /register-vk`       | Register verification key once, get `vkHash` |
| 2. Submit Proof | `POST /submit-proof`      | Submit proof with `vkHash`, get `jobId`      |
| 3. Poll Status  | `GET /job-status/{jobId}` | Wait for `Finalized` or `Aggregated` status  |

### Kurier Job Status

| Status                 | Description                                |
| ---------------------- | ------------------------------------------ |
| `Queued`               | Proof accepted, waiting for processing     |
| `Valid`                | Proof passed optimistic verification       |
| `Submitted`            | Proof submitted to blockchain/mempool      |
| `IncludedInBlock`      | Proof transaction included in a block      |
| `Finalized`            | Proof transaction finalized on-chain       |
| `AggregationPending`   | Proof ready for aggregation                |
| `Aggregated`           | Proof successfully aggregated              |
| `AggregationPublished` | Aggregation published to destination chain |
| `Failed`               | Proof processing failed                    |

### Kurier Endpoints

| Environment | API URL                          | Swagger Docs                          |
| ----------- | -------------------------------- | ------------------------------------- |
| Mainnet     | <https://api.kurier.xyz>         | <https://api.kurier.xyz/docs>         |
| Testnet     | <https://api-testnet.kurier.xyz> | <https://api-testnet.kurier.xyz/docs> |

## Explorer Links

### zkVerify

* **Mainnet**: [zkverify.subscan.io](https://zkverify.subscan.io/)
* **Testnet**: [zkverify-testnet.subscan.io](https://zkverify-testnet.subscan.io/)

### Horizen

* **Mainnet**: [horizen.calderaexplorer.xyz](https://horizen.calderaexplorer.xyz/)
* **Testnet**: [horizen-testnet.explorer.caldera.xyz](https://horizen-testnet.explorer.caldera.xyz/)

### Base

* **Mainnet**: [basescan.org](https://basescan.org/)
* **Testnet (Sepolia)**: [sepolia.basescan.org](https://sepolia.basescan.org/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://q3labs.gitbook.io/polypay-docs/zkverify-horizen-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
