"Compliance is not a gate — it is a dynamic routing parameter."
YieldRouter is an enterprise-grade, compliance-native yield routing protocol deployed on Arc Testnet (Chain ID 5042002). It routes stablecoins (USDC/EURC) into risk-adjusted yield strategies with embedded zero-knowledge compliance verification, institutional audit trails, and programmable waterfall distributions. By leveraging Circle Developer-Controlled Wallets, User-Controlled Wallets, and CCTP via App Kit, YieldRouter enables frictionless, gas-abstracted stablecoin commerce with institutional compliance.
- Live Demo: https://yield-router.vercel.app
- Video Presentation & Demo Walkthrough: YieldRouter Video Pitch
- Technical Docs: https://yield-router.vercel.app/docs
- Vision
- Problem Statement
- Solution
- Core Features
- Product Tour
- Architecture & Flows
- Folder Structure
- Technology Stack
- Installation & Setup
- Prerequisites
- Environment Variables
- Script Index
- Configuration
- API Reference
- Database Schema
- Security & Threat Model
- Performance & Scaling
- ZK Compliance Circuit
- Autonomous Agent Architecture
- Deployment & CI/CD
- Monitoring & Observability
- Troubleshooting & FAQ
- Roadmap
- Contributing
- License
YieldRouter reimagines decentralized finance for institutional players. Currently, compliance is treated as a binary gate at the entrance of a protocol. YieldRouter treats compliance as a multi-tiered routing variable.
Our long-term impact is to bridge traditional capital markets with public blockchain ledger efficiency. By embedding zero-knowledge KYC attestations directly into EVM smart contracts, we protect sensitive investor PII while providing verification to protocol allocation engines.
Traditional financial institutions want to capture decentralized yields, but face three core blockers:
- Compliance Risks: Pooling assets with unverified, anonymous counter-parties violates anti-money laundering (AML) laws.
- On-chain PII Leakage: Publicly uploading passports or KYC certificates violates data privacy laws (e.g. GDPR, CCPA).
- Execution Friction: Managing native gas assets (ETH, AVAX) introduces accounting complexity, security risks, and pricing volatility.
YieldRouter solves these friction points through a modular compliance stack:
- Embedded ZK-Compliance: Proves user compliance tiers (1 = Basic, 2 = Accredited, 3 = Institutional) without exposing identity or country codes on-chain.
- USDC-as-Gas on Arc: Eliminates native gas tokens; users pay gas natively using USDC, which is swapped/handled under the hood, simplifying the developer and client balance requirements.
- Programmable Yield Waterfall: Automated smart contract distribution splitting returns across Risk/Return tranches: Senior (Fixed APY), Mezzanine (Target APY), and Junior (Variable APY).
- On-chain registry mapping addresses to KYC verification tiers.
- Strict smart contract-level assertions ensuring only Accredited/Institutional users deposit into matching risk-yielding pools.
- Verification is computed off-chain as a ZK-SNARK proof and submitted to an on-chain
Verifiermodule.
- Auto-allocator calculates yield optimization across vaults (e.g., Arc Treasury Bonds, USDC Lending, RWA Pools).
- Dynamic portfolio weight allocation based on risk parameters.
- Standardized, auditable log files containing
AllocationDecision,ComplianceVerified, andYieldHarvestedevents. - Ledger reports can be exported as CSV directly from the user dashboard.
- Integrates Circle App Kit to allow seamless bridging of USDC from Ethereum Sepolia directly into the YieldRouter on Arc.
- Real-time yield accrual with sub-cent precision.
- Users can establish streaming sessions validated via cryptographically signed HMAC SHA-256 tokens and claim payouts instantly.
graph TD
A[Onboard Wallet via email or MetaMask] --> B[Perform KYC / Self-Verify]
B --> C[Generate ZK Proof Client-side]
C --> D[Submit Proof to register compliance tier]
D --> E[Deposit USDC / Bridge via App Kit CCTP]
E --> F[Automated Allocation Engine triggers routing]
F --> G[Start real-time x402 Yield Stream payouts]
G --> H[Export institutional-ready audit ledger]
┌────────────────────────────────────────────────────────┐
│ YieldRouter dApp │
│ Next.js + TypeScript + Viem + RainbowKit │
├───────────────────────────┬────────────────────────────┤
│ ZK-SNARK Proof Client │ x402 Yield Streamer │
└─────────────┬─────────────┴─────────────┬──────────────┘
│ │ (HTTP/SSE)
│ (Contract Write) ▼
┌─────────────▼─────────────┐ ┌────────────────────────┐
│ YieldRouter Smart │ │ Next.js API Server │
│ Contracts │ │ Token JWT / Gateway │
├───────────────────────────┤ ├────────────────────────┤
│ - Compliance Registry │ │ - Circle Wallet API │
│ - Strategy Vault Engine │ │ - Prisma ORM / SQLite │
│ - Verifier.sol (Groth16) │ └──────────┬─────────────┘
│ - Governance & Waterfall │ │
└─────────────▲─────────────┘ │ (Developer-Controlled Wallets API)
│ ▼
│ ┌──────────────┐
└─────────────────────┤ Agent Daemon │
(Compound / Sweep) └──────────────┘
sequenceDiagram
autonumber
actor User as Investor Wallet
participant Frontend as dApp Frontend
participant SnarkJS as SnarkJS Client
participant VC as Verifier Contract
participant YR as YieldRouter Contract
User->>Frontend: Select Verification Tier (e.g. Accredited)
Frontend->>Frontend: Gather KYC Attestation Attributes
Frontend->>SnarkJS: Run groth16.fullProve(inputs, wasm, zkey)
SnarkJS-->>Frontend: Generate Proof (piA, piB, piC, publicSignals)
Frontend->>YR: call deposit(amount, tolerance, trancheId, proof, inputs)
YR->>VC: call verifyProof(a, b, c, input)
VC-->>YR: Return bool (Proof Valid)
YR->>YR: Verify Address Commitment == msg.sender
YR->>YR: Record verified ComplianceTier
YR->>User: Confirm deposit on-chain
sequenceDiagram
autonumber
actor User as Investor Wallet
participant Frontend as dApp Frontend
participant Server as Next.js API Gateway
participant DB as SQLite / database
participant Client as Public Client (Arc)
participant Circle as Circle API (DCW / Gasless)
User->>Frontend: Open Real-time Yield Stream View
Frontend->>Server: Request Session Stream Token
Server-->>Frontend: HMAC SHA-256 Signed Session Token
Frontend->>Server: Poll accrued yield with session token
Server->>Client: Read user deposit position on-chain
Server->>DB: Fetch last settlement timestamp
Server-->>Frontend: Return real-time accrued micro-cents
User->>Frontend: Request Stream Payout
Frontend->>Server: POST /api/circle/user-wallet/execute
Server->>Circle: Call contractExecution (Transfer ERC-20 USDC)
Circle-->>User: Execute gasless USDC transfer on Arc
.
├── app/ # Next.js App Router Pages & API Routes
│ ├── api/ # Backend Serverless Endpoints
│ │ ├── agent/chat/ # Agent Chat Endpoint
│ │ ├── circle/ # Circle Wallet & Webhook Handlers
│ │ │ ├── agent-harvest/ # Yield sweeps keeper triggers
│ │ │ ├── user-wallet/ # UCW creation and execution routes
│ │ │ └── webhook/ # Secure Circle webhook receiver
│ │ ├── compliance/aggregate/ # Compliance nonce queries
│ │ └── faucet/yrt/ # Faucet for Yield Router Tokens
│ ├── blog/ # Technical updates and announcements
│ ├── dashboard/ # Institutional Investor Dashboard
│ ├── docs/ # Static developer guides
│ ├── faq/ # Frequently Asked Questions
│ ├── layout.tsx # Core layout container
│ └── page.tsx # Interactive landing page and calculator
├── blockchain/ # Blockchain configuration and compilation scripts
│ ├── contracts/ # Solidity Smart Contracts
│ │ ├── mocks/ # Test Mock contracts (e.g. MockStableFX)
│ │ ├── AgentRegistry.sol # Map keeper addresses to IDs
│ │ ├── Verifier.sol # ZK-SNARK Groth16 Verifier (compiled by Circom)
│ │ ├── YieldHarvestJob.sol # Harvest job logic for keep agents
│ │ ├── YieldRouter.sol # Main strategy router contract
│ │ ├── YieldRouterGovernance.sol# Governance proposal system
│ │ └── YieldRouterToken.sol # Governance Token (YRT)
│ ├── scripts/ # Automation, Deployment & Tests
│ │ ├── agent-daemon.ts # Keeper harvest worker process
│ │ ├── deploy.ts # Compile & deploy smart contracts to Arc
│ │ ├── setup-agent-wallet.ts # Setup Circle Developer-Controlled Wallets
│ │ ├── test-stream.ts # Test real-time stream math
│ │ └── test-zk.ts # Test verification of ZK proofs
│ ├── WalletContext.tsx # Unified App Kit & UCW state provider
│ ├── abis.ts # Deployed addresses and ABI definitions
│ └── zk-service.ts # Client-side SnarkJS generator helper
├── circuits/ # ZK-SNARK Compliance circuit definitions
│ └── KYCProof.circom # Circom Poseidon-hashed KYC verification template
├── components/ # Shared React UI Components
│ ├── AuditReportGenerator.tsx # Institutional PDF audit report generator
│ ├── VisualAnalytics.tsx # Recharts visualization modules
│ └── WalletDetailsModal.tsx # Live status modal & balances
├── prisma/ # Database configuration
│ ├── dev.db # Local development database (SQLite)
│ ├── prisma.ts # Global prisma client export
│ └── schema.prisma # Prisma Database Schema definitions
├── public/ # Static assets and compiled ZK parameters
│ └── circuits/ # Compiled KYCProof.wasm & KYCProof.zkey
├── styles/ # Vanilla CSS layout files
├── package.json # Project manifest and package dependencies
└── tsconfig.json # TypeScript compiler options
| Category | Tools / Technologies |
|---|---|
| Frontend | Next.js 15.5, React 18, TypeScript, Recharts, Lucide Icons, jsPDF |
| Styling | Vanilla CSS (Glassmorphism design tokens) |
| Blockchain | Viem (v2), SnarkJS, Solidity 0.8.24, Arc Testnet (Chain ID 5042002) |
| Circle Services | Developer-Controlled Wallets, User-Controlled Web SDK, App Kit (Bridge/CCTP) |
| Database | SQLite + Prisma Client v5.18.0 |
| ZK Toolkit | Circom 2.1.6, SnarkJS (Groth16 proving system) |
Follow these steps to configure, compile, and run YieldRouter locally.
# Clone the repository
git clone https://github.com/lisajacksiuro/YieldRouter.git
cd YieldRouter
# Install dependency tree
npm install# Run Prisma schema migrations locally
npx prisma db push
npx prisma generateThe pre-compiled circuits are already located inside /public/circuits/. If you modify circuits/KYCProof.circom, you will need to re-run the ceremony using snarkjs.
Before running the application, make sure you have:
- Node.js:
v18.xorv20.xinstalled. - Circle Developer Account: Create one at Circle Console to obtain API Keys and register an App ID.
- Testnet USDC: Request faucet USDC on Arc Testnet via Circle Faucet.
Copy the template from .env.example into a new .env file in the root directory:
cp .env.example .envEnsure the following variables are configured:
| Variable Name | Purpose | Source / URL | Required | Security Recommendation |
|---|---|---|---|---|
PRIVATE_KEY |
Deploy contracts and execute admin seeds | MetaMask Account | Yes | Use a dedicated development key. |
NEXT_PUBLIC_ARC_RPC_URL |
RPC Gateway for Arc Chain queries | Arc Console | Yes | Use the stable RPC link. |
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID |
Project ID for AppKit Wallet modal | Reown Cloud | Yes | Keep public but restrict domains. |
CIRCLE_API_KEY |
Authorize Developer & User wallet APIs | Circle Console | Yes | Server-side only. Do not leak. |
CIRCLE_ENTITY_SECRET |
Secret to register entity encryption keys | Circle CLI | Yes | Server-side only. Encrypt in production. |
NEXT_PUBLIC_CIRCLE_APP_ID |
Circle Web App configuration binding | Circle Console | Yes | Public identifier. |
JWT_SECRET |
Sign user session keys for x402 stream | Arbitrary high entropy string | Yes | Change to unique secret in prod. |
Run these scripts from the repository root:
| Command | Purpose | Execution context | Internal Action |
|---|---|---|---|
npm run dev |
Run Dev Server | Local development | Boots local server at http://localhost:3000 |
npm run build |
Build Production App | CI/CD or Vercel build | Generates Prisma client, compiles TS, Next.js optimization |
npm run deploy |
Deploy Contracts | Setup on Arc Testnet | Compiles Solidity, deploys contracts, seeds mock strategies |
npm run register-agent |
Register Keeper Agent | Setup agent registry | Links Developer wallet address to Keeper contracts on-chain |
npm run agent-daemon |
Active keeper daemon | Running process | Background worker checking and sweeping compound rewards |
npm run test-stream |
Test x402 Streams | Debugging command | Simulates mathematical yield streams and triggers settlements |
The bundler configures polyfills for cryptographic libraries required by SnarkJS:
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = {
...config.resolve.fallback,
fs: false,
readline: false,
child_process: false,
};
}
return config;
},
};
export default nextConfig;- Endpoint:
POST /api/circle/user-wallet - Request Payload:
{
"email": "investor@institution.com"
}- Response Output:
{
"success": true,
"userId": "usr_9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"userToken": "eyJhbGciOi...",
"encryptionKey": "zPqR...",
"challengeId": "c8d76d49-410a-5b12-9c1a-7b3bde6511a2",
"appId": "..."
}- Endpoint:
POST /api/circle/user-wallet/execute - Request Payload:
{
"userToken": "eyJhbGciOi...",
"walletId": "wlt_7a3d1b22-421d-4bcd-8841-325ba4098de7",
"contractAddress": "0x3ed68ff88f31f806a5898f4d9c3dee4fe22a8978",
"abiFunctionSignature": "deposit(uint256,uint8,uint256,uint256[2],uint256[2][2],uint256[2],uint256[3])",
"abiParameters": ["1000000", "1", "0", [...]]
}- Response Output:
{
"success": true,
"challengeId": "challenge_uuid_here",
"txId": "transaction_uuid_here"
}erDiagram
USER ||--o{ WALLET : has
USER ||--o{ TRANSACTION : executes
USER ||--o{ ATTESTATION : verified_by
STRATEGY ||--o{ TRANSACTION : accepts
USER {
string id PK
string address UNIQUE
string circleUserId UNIQUE
int complianceTier
DateTime createdAt
}
WALLET {
string id PK
string walletId UNIQUE
string address UNIQUE
string userId FK
string status
}
TRANSACTION {
string id PK
string txHash UNIQUE
string amount
string type
string status
string userId FK
int strategyId FK
int blockNumber
DateTime createdAt
}
ATTESTATION {
string id PK
string hash UNIQUE
string verifier
string jurisdiction
int expiry
string userId FK
}
STRATEGY {
string id PK
int strategyId UNIQUE
string name
float apy
int riskScore
string maxCapacity
string currentTVL
boolean active
}
- Front-running & Replay Protection: Client ZK proofs bind inputs directly to
msg.sender(enforced on-chain:addressCommitment === userAddress). A malicious actor cannot copy an investor's ZK-proof and submit it from a different wallet. - SSRF Shielding: Circle webhook signing cert URLs are strictly validated to ensure they use
https:and belong explicitly to.circle.comdomains before fetch executions. - Cryptographic Session Tokens: x402 streams are verified with a 30-minute transient HMAC SHA-256 token containing expiration dates, protecting payout endpoints from malicious over-withdrawal attempts.
- Batching and RPC Optimization: Public clients explicitly declare
{ batch: false }and connect using isolated transport pipelines to prevent head-of-line blocking on Arc node infrastructure. - Self-Healing Session Tokens: Backend endpoints automatically detect expired User-Controlled Wallet tokens and silently request fresh credentials from the Circle REST API before completing transactions, maintaining seamless UX.
The compliance validation is implemented in Circom (circuits/KYCProof.circom). It maps private inputs to Poseidon cryptographic hashes acting as verified signatures:
pragma circom 2.1.6;
include "../node_modules/circomlib/circuits/poseidon.circom";
template KYCProof() {
signal input userAddress;
signal input jurisdiction;
signal input passportHash;
signal input verifierSignature;
signal input addressCommitment;
signal input expirationDate;
signal input tier;
signal output valid;
addressCommitment === userAddress;
component hasher = Poseidon(5);
hasher.inputs[0] <== userAddress;
hasher.inputs[1] <== jurisdiction;
hasher.inputs[2] <== passportHash;
hasher.inputs[3] <== expirationDate;
hasher.inputs[4] <== tier;
verifierSignature === hasher.out;
valid <== 1;
}
component main {public [addressCommitment, expirationDate, tier]} = KYCProof();The Autonomous Agent Harvester sweeps strategy vaults to compound rewards using a Developer-Controlled Wallet:
┌──────────────────────────────┐
│ Agent Registry │
│ (Smart Contract on Arc) │
└──────────────┬───────────────┘
│
[Reads Authorized Keepers]
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Keeper Daemon loop (CLI) │
├──────────────────────────────────────────────────────────────┤
│ 1. Check yields on-chain │
│ 2. Compute optimal strategy rebalancing triggers │
│ 3. Call contract execution on YieldHarvestJob │
└──────────────────────────────┬───────────────────────────────┘
│
[Triggers Contract Execution API]
▼
┌──────────────────────────────────────────────────────────────┐
│ Circle Developer Controlled Wallet (Gasless) │
├──────────────────────────────────────────────────────────────┤
│ Submits on-chain harvest() tx utilizing USDC native gas │
└──────────────────────────────────────────────────────────────┘
- Framework Preset: Next.js
- Build Command:
prisma generate && next build - Output Directory:
.next - Node.js Version:
20.xor18.x
Prisma Client auto-generation is automatically triggered during build time to prevent outdated cached dependencies in the Vercel container.
- Circle Webhook Events: The
/api/circle/webhooklogs notifications to database records and emits realtime updates to client sessions using a Server-Sent Events (SSE) stream. - Audit ledger export: Institutional users can download transaction lists directly from the UI panel compiled into standardized spreadsheets.
- Errors Log files: Failure payloads from Circle API or on-chain execution are logged locally under the
scratch/circle_error.jsondirectory for post-mortem analysis.
A: This is usually due to node process files locking dependencies in node_modules (e.g. query_engine-windows.dll.node). Ensure that any running Next.js dev server or active shell instances are terminated before executing compilation scripts.
A: Ensure CIRCLE_API_KEY and CIRCLE_ENTITY_SECRET are correctly declared inside .env. Check the logged responses inside scratch/circle_error.json to inspect the detailed failure payload returned by Circle.
A: SnarkJS needs compiled .wasm and .zkey binary files in the /public/circuits/ folder. In development environments missing these assets, the frontend reverts to a deterministic mock proof that satisfies the validation rules of the Solidity verifier.
📌 Milestones Timeline
├── Q3 2026: ZK-Identity verification integration with decentralized KYC providers
├── Q4 2026: Multi-Vault Auto-rebalancing Strategy launch
└── Q1 2027: Multi-Chain Cross-border Yield Routing v2 (Solana bridging support)
We welcome contributions to YieldRouter. Please read our guidelines:
- Commit Conventions: Follow Conventional Commits (e.g.
feat:,fix:,chore:). - Security Reporting: Do NOT post security vulnerabilities in GitHub issues. Please report issues privately to
security@yieldrouter.com.
This project is licensed under the MIT License - see the LICENSE file for details.
