Autonomous trading agents + commit-reveal privacy + zero-knowledge proofs on Uniswap V4
PrivBatch is an Agentic Finance system that enables private, batched token swaps on Uniswap V4. Autonomous trading agents monitor on-chain pools, make strategy-driven trading decisions, and submit their trades through a privacy-preserving commit-reveal mechanism backed by zero-knowledge proofs (ZKPs). Individual trade details (amounts, directions, recipients) are never publicly visible in batch execution calldata — only aggregate net deltas reach the AMM.
- Overview
- Architecture
- Project Structure
- Prerequisites
- Setup & Installation
- Running the Project
- Trading Strategies
- Creating a Custom Strategy
- Testing
- Deployed Contracts (Base Sepolia)
- License
Traditional DEX swaps are fully transparent — anyone can see your trade size, direction, and slippage tolerance before or after execution. This exposes traders to:
- MEV extraction (frontrunning, sandwich attacks)
- Information leakage (competitors see your trading strategy)
- Price impact from publicly visible large orders
PrivBatch solves this by combining three innovations:
| Layer | Technology | Purpose |
|---|---|---|
| Smart Contract | PrivBatchHook (Uniswap V4 Hook) |
Commit-reveal batch execution with on-chain ZK verification |
| Zero-Knowledge Proofs | Circom + Groth16 | Prove trade commitment validity without revealing parameters |
| Autonomous Agents | TypeScript trading agents | Monitor pools, decide trades, submit commitments, coordinate batches |
- Agents monitor Uniswap V4 pools for trading opportunities
- Agents commit hashed trade intents to the hook contract (trade details hidden)
- ZK proofs verify commitment validity without exposing parameters
- Reveals are submitted in separate transactions (not in batch calldata)
- Batch execution swaps only aggregate net deltas — individual trades are invisible
- Output tokens are distributed proportionally to participants
┌──────────────────────────────────────────────────────────────────────────────┐
│ PrivBatch System Architecture │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ OFF-CHAIN (TypeScript Agents) │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │
│ │ │ Momentum │ │Arbitrage │ │Liquidity │ │ Mean Reversion │ │ │
│ │ │ Strategy │ │ Strategy │ │ Strategy │ │ Strategy │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───────┬──────────┘ │ │
│ │ │ │ │ │ │ │
│ │ └──────────────┼──────────────┼────────────────┘ │ │
│ │ ▼ │ │
│ │ ┌──────────────────┐ │ │
│ │ │ PrivBatchAgent │ Concrete agent class │ │
│ │ │ ┌────────────┐ │ │ │
│ │ │ │MarketData │ │ Reads pool state via extsload │ │
│ │ │ │ Fetcher │ │ │ │
│ │ │ └────────────┘ │ │ │
│ │ └────────┬─────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────────┼────────────────────────────────┐ │ │
│ │ │ AgentManager │ Lifecycle │ BatchCoordinator│ │ │
│ │ │ (orchestrator) │ Manager │ (multi-agent) │ │ │
│ │ └──────────────────┼────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌───────────┴───────────┐ │ │
│ │ │ ZK Proof Generation │ Circom + snarkjs │ │
│ │ │ (Poseidon hash) │ Off-chain prover │ │
│ │ └───────────┬───────────┘ │ │
│ └─────────────────────┼───────────────────────────────────────────────┘ │
│ │ │
│ ══════════════════════╪═══════════════════════════════════════════════════ │
│ │ BLOCKCHAIN (Base Sepolia) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ON-CHAIN (Solidity Contracts) │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ PrivBatchHook.sol │ │ │
│ │ │ (Uniswap V4 Hook — beforeSwap + afterSwap) │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────────┐ ┌───────────────────────┐ │ │ │
│ │ │ │ Commit Phase │──▶│ Reveal Phase │ │ │ │
│ │ │ │ - Store hash │ │ - submitReveal() │ │ │ │
│ │ │ │ - ZK verify │ │ - submitRevealForZK() │ │ │ │
│ │ │ └────────────────┘ └──────────┬────────────┘ │ │ │
│ │ │ ▼ │ │ │
│ │ │ ┌──────────────────────────────────────────┐ │ │ │
│ │ │ │ Batch Execution │ │ │ │
│ │ │ │ - Net delta computation │ │ │ │
│ │ │ │ - Single AMM swap (aggregate only) │ │ │ │
│ │ │ │ - Proportional output distribution │ │ │ │
│ │ │ │ - Slippage validation per user │ │ │ │
│ │ │ └──────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────────┼──────────────────┐ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │
│ │ │Groth16 │ │PoolManager │ │ Mock Tokens │ │ │
│ │ │Verifier.sol │ │(Uniswap V4) │ │ USDT / USDC │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────┐
│ run.ts │
│ (Entry Point / Runner) │
└──────────────┬───────────────┘
│
┌──────────────▼───────────────┐
│ AgentManager │
│ - Registers agents │
│ - Starts/stops all agents │
│ - Batch execution check loop │
│ - Error handling & recovery │
└──────────────┬───────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌────────────────────┐
│ AgentLifecycle │ │ BatchCoordinator│ │ AgentMessageBus │
│ Manager │ │ │ │ │
│ - Health checks │ │ - Quorum detect │ │ - Pub/Sub channels │
│ - Auto restart │ │ - Readiness │ │ - Shared state │
│ - Exp. backoff │ │ - Voting │ │ - Message history │
└─────────────────┘ └─────────────────┘ └────────────────────┘
│
┌──────────────▼───────────────┐
│ PrivBatchAgent │
│ (extends TradingAgent) │
│ │
│ ┌─────────────────────────┐ │
│ │ MarketDataFetcher │ │
│ │ - extsload for price │ │
│ │ - extsload for liq. │ │
│ │ - Swap event query │ │
│ │ - Caching layer │ │
│ └─────────────────────────┘ │
│ │ │
│ ┌───────────▼──────────────┐ │
│ │ TradingStrategy │ │
│ │ (pluggable) │ │
│ │ │ │
│ │ shouldTrade(data,config) │ │
│ │ → TradeDecision │ │
│ └──────────────────────────┘ │
│ │ │
│ ┌───────────▼──────────────┐ │
│ │ Commitment Submission │ │
│ │ → PrivBatchHook on-chain │ │
│ └──────────────────────────┘ │
└───────────────────────────────┘
Monitoring Loop (every N ms):
┌──────────────────────────────┐
│ 1. Fetch market data (price, │
│ liquidity, recent swaps) │
│ 2. Evaluate strategy │
│ 3. If signal → submit commit │
│ 4. Coordinate batch when ready│
└──────────────────────────────┘
The PrivBatchHook is a Uniswap V4 hook that intercepts swap operations and implements a commit-reveal-batch pattern:
PrivBatchHook Flow
──────────────────
User A ──┐ ┌── User A gets output
User B ──┤ ① COMMIT │ proportional to input
User C ──┘ (hashed intents — no trade details) │
│ │
▼ │
┌──────────────────────────┐ │
│ Commitment Storage │ │
│ commitmentHash → { │ │
│ hash, timestamp, │ │
│ revealed: false │ │
│ } │ │
└────────────┬─────────────┘ │
│ │
User A ──┐ │ ② REVEAL (separate transactions) │
User B ──┤───┘ submitRevealForZK(hash, intent) │
User C ──┘ (stored in contract, NOT in batch │
│ execution calldata) │
▼ │
┌──────────────────────────┐ │
│ Reveal Storage │ │
│ commitmentHash → │ │
│ SwapIntent { user, │ │
│ tokenIn, tokenOut, │ │
│ amountIn, minOut, │ │
│ recipient, nonce, │ │
│ deadline } │ │
└────────────┬─────────────┘ │
│ │
│ ③ BATCH EXECUTE │
│ revealAndBatchExecuteWithProofs( │
│ poolKey, hashes[], proofs[]) │
│ │
│ Calldata contains ONLY: │
│ • commitment hashes (opaque bytes32) │
│ • ZK proofs (cryptographic data) │
│ • Pool key (public routing info) │
│ │
│ NO individual trade details! │
▼ │
┌──────────────────────────┐ │
│ Batch Processing │ │
│ │ │
│ 1. Verify ZK proofs │ │
│ 2. Load intents from │ │
│ revealStorage │ │
│ 3. Compute net deltas: │ │
│ netΔ₀ = Σ(inputs₀) │ │
│ netΔ₁ = Σ(inputs₁) │ │
│ 4. Validate privacy │ │
│ 5. Single AMM swap │──── Uniswap V4 Pool ───┘
│ (net amount only) │ Only sees aggregate
│ 6. Validate slippage │
│ 7. Distribute outputs │
│ 8. Clean up storage │
└──────────────────────────┘
Key privacy properties:
- Individual trade sizes, directions, and recipients are never visible in batch execution calldata
- On-chain events use hashed recipient addresses
- The AMM only sees a single aggregate swap
- ZK proofs verify validity without revealing parameters
ZK Proof Flow (Groth16 + Poseidon)
──────────────────────────────────
┌─────────────────────────────────────────────────────────────┐
│ OFF-CHAIN (Agent / User) │
│ │
│ Trade Parameters (PRIVATE): │
│ ┌──────────────────────────────────────────────┐ │
│ │ user = 0xABC... │ │
│ │ tokenIn = 0xUSDC... │ │
│ │ tokenOut = 0xUSDT... │ │
│ │ amountIn = 1000000 (1 USDC) │ │
│ │ minAmountOut= 990000 (0.99 USDT) │ │
│ │ recipient = 0xABC... │ │
│ │ nonce = 42 │ │
│ │ deadline = 1700000000 │ │
│ └───────────────────┬──────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ Poseidon Hash (ZK-friendly) │ │
│ │ │ │
│ │ commitmentHash = Poseidon( │ │
│ │ user, tokenIn, tokenOut, amountIn, │ │
│ │ minAmountOut, recipient, nonce, │ │
│ │ deadline │ │
│ │ ) │ │
│ └───────────────────┬───────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ Circom Circuit (commitment- │ │
│ │ proof.circom) │ │
│ │ │ │
│ │ Proves: Poseidon(private_inputs) │ │
│ │ == commitmentHash (public) │ │
│ │ │ │
│ │ Witness generation → Groth16 prover │ │
│ └───────────────────┬───────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ ZK Proof Output │ │
│ │ │ │
│ │ proof = { a, b, c } (PUBLIC) │ ◄── Sent to │
│ │ publicSignals = [commitmentHash] │ blockchain │
│ │ │ │
│ │ Private inputs stay OFF-CHAIN ✓ │ │
│ └───────────────────┬───────────────────┘ │
└──────────────────────┼───────────────────────────────────────┘
│
═══════════════════════╪════════════════════════════════════
│ BLOCKCHAIN
▼
┌─────────────────────────────────────────────────────────────┐
│ ON-CHAIN │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ Groth16Verifier.sol │ │
│ │ (auto-generated from snarkjs) │ │
│ │ │ │
│ │ verifyProof(a, b, c, publicSignals) │ │
│ │ → true / false │ │
│ └───────────────────┬───────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ PrivBatchHook.sol │ │
│ │ │ │
│ │ submitCommitmentWithProof( │ │
│ │ poolKey, commitmentHash, │ │
│ │ a, b, c, publicSignals │ │
│ │ ) │ │
│ │ ✓ Verifies proof on-chain │ │
│ │ ✓ Marks commitment as ZK-verified │ │
│ │ ✓ No trade parameters revealed │ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
What's Visible on the Blockchain?
─────────────────────────────────
┌─────────────────────────────────────┐
│ VISIBLE (Public) │
│ │
│ • Commitment hashes (opaque) │
│ • ZK proofs (cryptographic data) │
│ • Pool key (which pool) │
│ • Net swap delta (aggregate) │
│ • Batch size (# of participants) │
│ • Hashed recipient addresses │
│ • Timestamps │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ HIDDEN (Private) │
│ │
│ • Individual trade amounts ✗ │
│ • Individual trade directions ✗ │
│ • User addresses in batch tx ✗ │
│ • Recipient addresses (hashed) ✗ │
│ • Slippage tolerances ✗ │
│ • Trading strategy signals ✗ │
└─────────────────────────────────────┘
privbatch/
├── agents/ # 🤖 Autonomous Trading Agents (TypeScript)
│ ├── run.ts # Entry point — boots and runs the agent
│ ├── PrivBatchAgent.ts # Concrete agent (MarketDataFetcher + Strategy)
│ ├── TradingAgent.ts # Abstract base agent class
│ ├── AgentManager.ts # Multi-agent orchestrator
│ ├── strategies/ # Pluggable trading strategies
│ │ ├── BaseStrategy.ts # Abstract strategy template
│ │ ├── MomentumAgent.ts # Price momentum strategy
│ │ ├── ArbitrageAgent.ts # Cross-pool arbitrage strategy
│ │ ├── LiquidityAgent.ts # Liquidity-based strategy
│ │ └── MeanReversionAgent.ts # Mean reversion strategy
│ ├── config/
│ │ ├── agentConfig.ts # Config loading (env + JSON + defaults)
│ │ └── AgentLifecycleManager.ts # Health monitoring & auto-restart
│ ├── coordination/
│ │ ├── BatchCoordinator.ts # Multi-agent batch timing coordination
│ │ └── AgentMessageBus.ts # Inter-agent pub/sub messaging
│ ├── hooks/ # PrivBatchHook client wrappers
│ │ ├── PrivBatchHookClient.ts # Contract interaction client
│ │ ├── RevealManager.ts # Reveal collection & validation
│ │ ├── BatchExecutor.ts # Batch execution logic
│ │ └── TokenDistributionHandler.ts # Token distribution event handling
│ ├── utils/
│ │ ├── marketData.ts # Pool data fetcher (extsload + events)
│ │ └── poolMonitor.ts # Continuous pool monitoring
│ ├── types/
│ │ └── interfaces.ts # TypeScript type definitions
│ ├── __tests__/ # Jest unit tests
│ ├── .env # Agent configuration (not committed)
│ ├── .env.example # Example configuration template
│ ├── package.json
│ └── tsconfig.json
│
├── contracts/ # 📜 Solidity Smart Contracts (Foundry)
│ ├── PrivBatchHook.sol # Main hook — commit-reveal-batch logic
│ ├── CommitmentVerifier.sol # Auto-generated Groth16 verifier
│ ├── MockUSDT.sol # Mock USDT token (18 decimals)
│ ├── MockUSDC.sol # Mock USDC token (6 decimals)
│ ├── lib/
│ │ └── SimpleERC20.sol # Minimal ERC20 base
│ ├── script/
│ │ ├── DeployPrivBatchHook.s.sol # Deploy hook + verifier
│ │ ├── DeployMockUSDT.s.sol # Deploy mock USDT
│ │ ├── DeployMockUSDC.s.sol # Deploy mock USDC
│ │ ├── SetupPoolLiquidity.s.sol # Initialize pool + add liquidity
│ │ ├── ExecuteBatch.s.sol # Execute batch swap
│ │ └── MonitorAndExecute.s.sol # Monitor + auto-execute
│ ├── test/
│ │ ├── PrivBatchHookZK.t.sol # ZK integration tests
│ │ └── CommitmentVerifier.t.sol # Verifier tests
│ ├── foundry.toml # Foundry configuration
│ └── remappings.txt # Solidity import remappings
│
├── circuits/ # 🔐 ZK Circuits (Circom)
│ ├── commitment-proof.circom # Poseidon commitment proof circuit
│ └── package.json # Circuit build scripts
│
├── scripts/zk/ # 🛠️ ZK Proof Scripts (Node.js)
│ ├── generate-proof.js # Off-chain proof generation
│ ├── test-proof-generation.js # Proof generation tests
│ ├── test-end-to-end-zk-flow.js # Full E2E ZK flow test
│ └── package.json
│
├── build/zk/ # 🏗️ Compiled ZK Artifacts
│ ├── commitment-proof.wasm # Circuit WASM
│ ├── final.zkey # Proving key
│ ├── vkey.json # Verification key
│ └── ...
│
└── README.md # This file
| Tool | Version | Purpose |
|---|---|---|
| Node.js | ≥ 18 | Agent runtime, ZK scripts |
| npm | ≥ 9 | Package management |
| Foundry | Latest | Solidity compilation, testing, deployment |
| Circom | ≥ 2.1.6 | ZK circuit compilation |
| snarkjs | ≥ 0.7.0 | Trusted setup, proof generation |
| Git | Latest | Dependency management |
curl -L https://foundry.paradigm.xyz | bash
foundryup# Using cargo (Rust package manager)
cargo install --git https://github.com/iden3/circom.gitgit clone <your-repo-url> privbatch
cd privbatchcd contracts
forge install
cd ..cd agents
npm install
cd ..cd scripts/zk
npm install
cd ../..cd circuits
npm install
cd ..First, set up your environment variables. Create a .env file in the contracts/ directory:
# contracts/.env
PRIVATE_KEY=0xYOUR_PRIVATE_KEY
BASE_SEPOLIA_RPC_URL=https://base-sepolia.g.alchemy.com/v2/YOUR_API_KEY
BASESCAN_API_KEY=YOUR_BASESCAN_API_KEYcd contracts
# Deploy Mock USDT (18 decimals)
forge script script/DeployMockUSDT.s.sol:DeployMockUSDT \
--rpc-url $BASE_SEPOLIA_RPC_URL \
--broadcast \
--verify
# Deploy Mock USDC (6 decimals)
forge script script/DeployMockUSDC.s.sol:DeployMockUSDC \
--rpc-url $BASE_SEPOLIA_RPC_URL \
--broadcast \
--verifyforge script script/DeployPrivBatchHook.s.sol:DeployPrivBatchHook \
--rpc-url $BASE_SEPOLIA_RPC_URL \
--broadcast \
--verify# Set deployed addresses in .env first, then:
forge script script/SetupPoolLiquidity.s.sol:SetupPoolLiquidity \
--rpc-url $BASE_SEPOLIA_RPC_URL \
--broadcastIf you need to recompile circuits and regenerate the verifier (pre-built artifacts are included in build/zk/):
cd circuits
# Compile the Circom circuit
npm run compile
# Trusted setup (Powers of Tau ceremony)
npm run setup
npm run contribute
# Finalize
snarkjs powersoftau prepare phase2 ../build/zk/pot12_0001.ptau ../build/zk/pot12_final.ptau -v
# Generate proving/verification keys
npm run setup-groth16
npm run contribute-zkey
# Export verification key and Solidity verifier
npm run export-vkey
npm run export-verifier
cd ..cd scripts/zk
npm test
cd ../..Create an .env file in the agents/ directory. Use the example as a template:
cd agents
cp .env.example .envEdit agents/.env with your deployed contract addresses and RPC credentials:
# ─── Agent Configuration ───────────────────────────────────────
AGENT_ID=agent-1
# Wallet (NEVER commit your private key to version control)
AGENT_WALLET_ADDRESS=0xYOUR_WALLET_ADDRESS
AGENT_WALLET_PRIVATE_KEY=0xYOUR_PRIVATE_KEY
# Strategy: momentum | arbitrage | liquidity | mean-reversion
AGENT_STRATEGY_NAME=momentum
# Contract addresses (Base Sepolia)
AGENT_HOOK_ADDRESS=0xYOUR_HOOK_ADDRESS
AGENT_POOL_MANAGER_ADDRESS=0x05E73354cFDd6745C338b50BcFDfA3Aa6fA03408
# RPC
AGENT_RPC_URL=https://base-sepolia.g.alchemy.com/v2/YOUR_API_KEY
AGENT_CHAIN_ID=84532
# Token addresses
MOCK_USDT_ADDRESS=0xYOUR_USDT_ADDRESS
MOCK_USDC_ADDRESS=0xYOUR_USDC_ADDRESS
# Monitoring (ms)
AGENT_POLL_INTERVAL=3000
# Batch settings
AGENT_BATCH_INTERVAL=4
AGENT_MIN_COMMITMENTS=2
# Trading limits (wei)
AGENT_MAX_AMOUNT_IN=10000000000000000000
AGENT_MIN_AMOUNT_IN=1000000000000000000
AGENT_DEFAULT_SLIPPAGE_BPS=50cd agents
# Start the agent (production)
npm start
# Or with auto-restart on file changes (development)
npm run devYou should see output like:
╔══════════════════════════════════════════════╗
║ 🤖 PrivBatch Trading Agent Runner ║
╚══════════════════════════════════════════════╝
[Runner] Pool: 0x0Ea67A67 / 0x98346718 (fee=3000, tick=60)
╔══════════════════════════════════════╗
║ Agent Configuration Summary ║
╠══════════════════════════════════════╣
║ Agent ID: agent-1
║ Strategy: momentum
║ Chain ID: 84532
║ Pools: 1
╚══════════════════════════════════════╝
[Runner] Strategy: momentum
[Runner] Agent created: agent-1
[Runner] Starting agent system...
[agent-1] Agent started successfully
[Runner] ✅ Agent is live and monitoring pools.
[Runner] Press Ctrl+C to stop.
[agent-1] ⏳ 0x0Ea67A../ 0x983467.. — price=1 liq=0 — No price movement detected (0.00% < 2.00% threshold)
Press Ctrl+C to gracefully shut down.
# Via environment variable
AGENT_STRATEGY_NAME=arbitrage npm start
# Or edit .env and restartnpx ts-node run.ts --config ./my-config.jsonThis test exercises the full privacy flow: proof generation → commitment → reveal → batch execution.
cd scripts/zk
# Make sure .env is configured with contract addresses
npm run test-e2e| Strategy | File | Description | Signal |
|---|---|---|---|
| Momentum | MomentumAgent.ts |
Trades in direction of price momentum | Price change exceeds threshold (default 2%) |
| Arbitrage | ArbitrageAgent.ts |
Exploits cross-pool price discrepancies | Spread exceeds minimum profitable threshold |
| Liquidity | LiquidityAgent.ts |
Trades based on liquidity imbalances | Liquidity ratio exceeds imbalance threshold |
| Mean Reversion | MeanReversionAgent.ts |
Trades against deviations from moving average | Price deviates significantly from historical mean |
All strategies extend BaseStrategy which provides:
- Cooldown management — prevent over-trading on the same pool
- Amount scaling — scale trade size by confidence level
- Slippage calculation — automatically compute
minAmountOutfrom price and BPS tolerance - Market data validation — check data freshness, price sanity, liquidity
- Standardized decisions — consistent
TradeDecisionformat
import { BaseStrategy } from './BaseStrategy';
import { MarketData, TradeDecision, AgentConfig, SwapDirection } from '../types/interfaces';
export class MyCustomAgent extends BaseStrategy {
name = 'my-custom-strategy';
async shouldTrade(marketData: MarketData, config: AgentConfig): Promise<TradeDecision> {
// Validate market data
const validation = this.validateMarketData(marketData);
if (!validation.isValid) {
return this.noTradeDecision(`Invalid data: ${validation.errors.join(', ')}`);
}
// Check cooldown
if (this.isCooldownActive(marketData.poolId, 60000)) {
return this.noTradeDecision('Cooldown active');
}
// Your custom logic
const price = parseFloat(marketData.currentPrice);
if (price > someThreshold) {
this.recordTrade(marketData.poolId);
return this.buildTradeDecision(
SwapDirection.ZERO_FOR_ONE,
this.scaleAmount(0.8, config),
'0',
0.8,
'Custom signal triggered'
);
}
return this.noTradeDecision('No signal');
}
}Register it in run.ts:
case 'my-custom':
return new MyCustomAgent();cd agents
npm testTests cover:
- All 4 trading strategies (signal detection, cooldown, edge cases)
MarketDataFetcher(caching, pool ID computation)PrivBatchHookClient(commitment submission, reveal, batch execution)RevealManager(validation, deduplication)BatchExecutor(pool management, ZK/standard execution)BatchCoordinator(quorum, readiness, countdown)BaseStrategy(cooldown, scaling, market data validation)
cd contracts
forge test -vvTests cover:
- ZK proof verification on-chain
- Commitment submission and reveal
- Batch execution with privacy checks
- Slippage validation
- Token distribution
cd scripts/zk
npm test # Proof generation tests
npm run test-e2e # Full end-to-end ZK flow| Contract | Address |
|---|---|
| PrivBatchHook | 0x2EEeC56B3037EC07cf2024a896C9708Bc94280C4 |
| Groth16Verifier | 0x09F3bCe3546C3b4348E31B6E86A271c42b39672e |
| MockUSDT (18 dec) | 0x0Ea67A670a4182Db6eB18A6aAbC0f75195ef2EfC |
| MockUSDC (6 dec) | 0x98346718c549Ed525201fC583796eCf2eaCC0aD5 |
| PoolManager (Uniswap V4) | 0x05E73354cFDd6745C338b50BcFDfA3Aa6fA03408 |
Network: Base Sepolia (Chain ID: 84532)
| Decision | Rationale |
|---|---|
| Poseidon hash (not Keccak256) in ZK circuits | ~150x fewer constraints than Keccak in ZK proofs |
| Separate reveal transactions | Individual intents are never in batch execution calldata |
extsload for pool state reads |
Uniswap V4 stores state in PoolManager slots; no public getter functions |
10-block eth_getLogs range |
Compatible with Alchemy free tier rate limits |
via_ir = true in Foundry |
Resolves "stack too deep" in complex hook contract |
| Hashed recipient in events | Prevents linking on-chain events to specific user addresses |
| Net delta batching | AMM sees one swap regardless of how many users participate |
MIT