How Zerk works.
Zerk is a confidential crossing network for tokenized real-world assets. Desks submit encrypted orders, matching runs inside a TEE, and crossed trades settle atomically through unmodified Seaport on Ethereum Sepolia.
What is hidden, and what is not.
This table is the honest version of the privacy claim. Regulated dark pools are pre-trade opaque and post-trade transparent by design; Zerk reproduces that regime rather than claiming more than it delivers.
| Field | Confidential forever | Revealed at settlement |
|---|---|---|
| Limit prices | ✓ | never |
| Orders that never cross | ✓ | never |
| Resting size before a fill | ✓ | never |
| Which desk is shopping | ✓ | never |
| The matching process itself | ✓ | never |
| Executed fill size | — | ✓ |
| Executed fill price | — | ✓ |
| The settlement transfer | — | ✓ |
From intent to settlement.
Nox compute is asynchronous, so the order lifecycle is deliberately three transactions: submit, propose, finalize. There is real latency between a proposal and its result — that is the enclave working, not the UI hanging.
| # | Actor | Action | What the chain sees |
|---|---|---|---|
| 01 | Desk A | Encrypts buy 500k @ 99.20 in the browser | nothing — no transaction yet |
| 02 | Desk A | submitOrder(handles, proofs) | OrderSubmitted(1, deskA) — three opaque handles |
| 03 | Desk B | Encrypts sell 400k @ 99.10, submits | OrderSubmitted(2, deskB) |
| 04 | Matcher | proposeMatch(1, 2) — blind | MatchProposed(matchId) |
| 05 | Nox | Ingestor → Runner → TEE evaluates the cross | nothing readable |
| 06 | Matcher | finalizeMatch(matchId, proofs) | MatchApproved(matchId, 400000, 99.15) |
| 07 | Desk B | Signs a FULL_RESTRICTED Seaport order, zoneHash = matchId | nothing — signed off-chain |
| 08 | Desk A | fulfillAdvancedOrder on Seaport 1.6 | authorizeOrder → transfers → validateOrder |
Steps 1–6 reveal nothing except that some order existed and some match crossed at a size and a price. Had the pair failed to cross, nothing at all would have been revealed — the orders would simply still be resting.
One field does the whole binding.
Seaport supports restricted orders. When one is fulfilled, Seaport calls the order’s designated zone twice — authorizeOrder before any token transfers and validateOrder after them. Reverting in either aborts the entire fulfilment.
zoneHash is an arbitrary 32 bytes baked into the order at signing and handed to the zone at fulfilment. Zerk puts the match id there. The consequence: a Seaport order is unfillable unless ZerkBook approved that exact match, at that exact size and price. Nobody can front-run the settlement, replay it, or fulfil an order the enclave never authorised — and Seaport itself is untouched, running at its canonical address.
Why a rejection tells you nothing.
Solidity cannot branch on an encrypted value, and Nox exposes no encrypted boolean AND. The crossing predicate is therefore folded into a 0/1 selector and multiplied through, so every proposal executes the identical sequence of operations regardless of outcome:
flag = select(bid.limit >= ask.limit, 1, 0) flag = select(bid.side == BID, flag, 0) flag = select(ask.side == ASK, flag, 0) minSize = select(bid.size <= ask.size, bid.size, ask.size) fillSize = flag * minSize fillPrice = flag * midpoint(bid.limit, ask.limit)
A non-crossing pair produces a fill of zero rather than a revert, and the failure discloses nothing about which of the three conditions failed. Only three handles are ever opened to public decryption — crossed, fillSize and fillPrice. The limits are not among them.
The obvious objections.
Settlement is public. What is actually private?
Limits, unfilled orders and resting sizes — permanently. Executed fills are reported, exactly as a regulated dark pool does. Zerk hides intent, not outcome. Even on a filled order, a desk's limit price is never published; only the executed price is.
Is the matcher a trusted party?
No. It pairs order ids blind. It holds no viewer grant on any handle, so it cannot read a side, a size or a limit, and the enclave decides whether a pair crosses. Anyone can run one; running a second changes only how fast pairs get tried.
Why Seaport instead of your own escrow?
Because a hackathon settlement contract will never be audited the way Seaport has been, and because building a new rail is exactly what the venue does not need. Zerk uses Seaport's official zone extension point at its canonical address. Zero forks.
Isn't this a batch auction like CoW?
CoW batches publicly for MEV protection and price improvement. Zerk's orders are never published at all, and it targets permissioned assets that cannot touch an AMM in the first place.
Your anonymity set is two desks.
True in a demo, and worth saying plainly. The claim is pre-trade non-display, which holds at n=2. Position-level anonymity needs volume — that is a liquidity problem, not a protocol one.
Why are settlement amounts visible at all?
Because both legs settle as standard ERC-20s. Nox ships a documented ERC-20 → ERC-7984 wrapper; wrapping both legs as confidential tokens would hide amounts too. That is the next milestone, not part of this build.
Terms & privacy
Zerk is unaudited research software deployed on a public testnet. It handles no real funds, makes no warranty of any kind, and is not an offer to trade securities. Order terms are encrypted in your browser and never transmitted to a Zerk-operated server — there is no Zerk-operated server. On-chain activity is public by construction; see the privacy boundary for exactly what that means.