← All posts

ZKPerp 1/4: Perpetual Futures Where Nobody Can See Your Position

Β·7 min read
Web3Zero-KnowledgeAleoDeFi

ZKPerp β€” privacy-preserving trading with on-chain verifiability

Part 1 of a four-part series. A privacy-first perpetuals DEX on Aleo β€” what it is, what's working, and what isn't.

ZKPerp has won a prize in four buildathon rounds and runs on Aleo testnet today. This is the overview; the rest of the series goes deeper.

Every perpetual DEX deployed on a transparent chain publishes your entire trading life. Position opens, closes, liquidations, LP deposits β€” written to public storage and indexed by a dozen data providers within seconds of settlement.

This is usually filed under "transparency." It's more accurate to call it a structural attack surface, because three specific things follow from it:

Front-running. A whale opens a large long. Bots see the pending transaction, buy ahead of it, sell immediately after, and pocket the price impact at the whale's expense.

Liquidation hunting. Every open position's liquidation price is computable from public data β€” entry, collateral, and size are all on-chain. Coordinated traders push price toward known liquidation clusters to trigger cascades.

Strategy copying. Every trade by a skilled trader is visible the moment it settles. Competitors replicate in real time. An institution cannot trade meaningful size without telegraphing its thesis to the entire market.

These aren't edge cases. They're a description of why professional flow largely doesn't go to on-chain perp venues, and no amount of MEV mitigation at the sequencer level addresses the root cause: the positions themselves are readable.

The approach

ZKPerp is built natively on Aleo, a Layer-1 designed around zero-knowledge proofs from the ground up. This matters because Aleo's programming model distinguishes two kinds of state:

  • Public mappings β€” readable by anyone, stored on-chain
  • Private records β€” UTXO-style encrypted objects, readable only by the owner's viewing key

ZKPerp stores all position data in private records. Size, entry price, collateral, leverage, direction, PnL, and liquidation level are encrypted by default β€” not as an opt-in mode, but as the only mode.

The property that makes this more than encrypted storage is this: an Aleo transition can verify that a computation is correct β€” that a position was opened at a valid price with valid collateral, producing a valid PnL β€” entirely via ZK proof, without the contract ever learning the values. The verifier learns that the computation was right, not what it computed over.

This is not a privacy layer over a transparent system. It's written in Leo, Aleo's native language, and the privacy is a property of the execution model rather than a feature layered on top.

What's public, and why

Being specific about this is more useful than claiming everything is hidden.

  • Oracle prices. Required for correct settlement. Unavoidably public.
  • Pool aggregates. Total liquidity, aggregate long and short open interest.
  • Commitment hashes. position_commits[id] is a BHP256 hash. It reveals nothing about the position's parameters, but its existence is visible.
  • Transaction counts. How many positions opened or closed per block β€” not their contents.

Everything else β€” size, entry, collateral, leverage, direction, PnL, liquidation level β€” is encrypted in records only the trader can decrypt.

What's live

Perpetual markets β€” BTC, ETH, SOL. Each is a separate program with its own LP pool and slot records. Up to 20Γ— leverage, 0.10% opening fee, 5% maintenance margin, settled in USDCx (the official Aleo testnet stablecoin) via real private token transfers.

Position commitment scheme. At open, all sensitive parameters are hashed into a single on-chain field element. Every termination path β€” close, take-profit, stop-loss, liquidation β€” recomputes that hash from supplied inputs and asserts equality before paying anything out. No party can terminate a position with parameters different from those committed at open. A trader can't inflate a payout; a keeper can't inflate a reward or liquidate at the wrong size.

Keeper-auth liquidation. Opening a position atomically mints authorization records to a keeper set, so liquidation works without the trader online and without anyone reading the trader's position. Any single keeper can act; they race for a deterministic reward rather than colluding. Correctness is enforced on-chain by five finalize gates regardless of which keeper submits.

On-chain 2-of-3 oracle quorum. Three independent relayers read Chainlink feeds and submit under their own Aleo keys. Quorum is enforced by the Leo contract itself β€” there is no off-chain coordinator. Prices older than 150 blocks (about five minutes) are rejected by every price-reading path.

Circuit-level KYC. A depth-10 BHP256 Merkle allowlist. Only the root is published on-chain; addresses never are. Users prove membership once and hold a private compliance record valid for up to 180 days. Revocation is instant via an on-chain boolean, with no tree rebuild. The off-chain allowlist maps wallet to identity under legal order β€” enabling audit and sanctions screening without publishing anyone's identity.

ZK dark pool. Sealed-bid batch auctions settling at a uniform clearing price. No order is public before or after settlement, which is the property front-running actually needs. Live on testnet with confirmed on-chain settlements.

Advanced order types. Limit orders, take-profit, and stop-loss β€” keeper-executed, with trigger conditions verified against the live on-chain oracle rather than a keeper-supplied price. The only on-chain trace of a pending order is a boolean keyed by a commitment hash.

Cross-chain collateral. USDCx bridged from Ethereum via Circle's bridge. Live test: ~81 USDC in under 15 minutes.

What's not

I'd rather you get this from me than from an audit. Each of these gets a full post later in the series; here's the short version.

The concentrated liquidity AMM is a prototype. A Uniswap v3-style USDCx/ALEO spot venue, maintained as a standalone subproject β€” not the perps liquidity engine. It verifies every swap against the curve, but amount math runs in inline u128, which bounds the provably-safe envelope. It has not been validated on-chain or audited. Research prototype, not a usable venue.

Pool-state aggregation is trusted. Because position sizes are private witnesses, open interest cannot be derived on-chain without publishing the sizes. An off-chain orchestrator computes and writes the aggregates, and its current write surface is broader than it needs to be. What it cannot do is inflate any trader's payout or move more than the pool's real token balance β€” but the full boundary deserves more than a bullet point, and it gets one in part 3.

The liquidator set is permissioned. Non-custodial and rule-bound β€” keepers cannot set prices, invent positions, or touch a solvent position β€” but it is not decentralized. Permissionless liquidation under privacy is an open research problem, not a roadmap item, for reasons I'll lay out next week.

No funding rate, no partial close. Flat borrow model for now; positions close in full.

Not audited. Testnet only. Not for real funds.

Where it goes

Near term: multi-orchestrator rotation, pool-state write hardening, a shared core library so per-market contracts become thin wrappers, and AMM hardening toward devnet validation.

Further out: dynamic funding rates, partial close, verifiable performance proofs enabling copy trading without revealing trades, and a ZK orderbook built on the dark pool's primitives.

Before any mainnet deployment: formal verification of circuit soundness and the in-circuit/finalize boundaries, a third-party ZK audit, and a bug bounty. Mainnet itself is gated on audit sign-off and, realistically, on a licensed operator partner β€” perpetual futures are MiFID II instruments in the EU, which is a permission an individual developer does not hold and cannot acquire on a project timeline.

That constraint shaped the architecture rather than being discovered after it. The compliance layer exists because a system like this only reaches real users through a regulated venue, and it should be built for that from the start. Part 4 is about what that actually means in practice.

This series

Four posts, one a week. The overview is the easy one; the rest are about the parts that resisted.

  1. What ZKPerp is β€” this post
  2. How do you liquidate a position you can't see? β€” the hardest problem in private perps, and the pattern that solved it
  3. What zero-knowledge can't do β€” every trust assumption in the system, named and bounded
  4. Four buildathons and a regulatory wall β€” what broke, what I got wrong, and why I can't run this myself

Technical whitepaper: ZKPerp whitepaper (PDF). Contracts and source: github.com/hwdeboer1977/ZKPerp. Network: Aleo testnet. MIT licensed.

If you're working on privacy-preserving markets, ZK execution models, or you operate a licensed venue and the phrase "settlement layer where order flow isn't visible to the market" sounds like a product rather than a slogan β€” I'd like to hear from you.