RFC 0x20CCPRIVATE SESSION: The RFCsOctober 2026

6. The RFCs

the contracts, in their own words

Every contract opens with a header written as a Request for Comments. They are set here exactly as the source says them; the build reads them out of the contract files, so this page cannot drift from the code.

  1. 6.1.RFC 1: the TokenPrivateSession.sol
  2. 6.2.RFC 2: the ServerServer.sol
  3. 6.3.RFC 3: the MeterMeter.sol
  4. 6.4.RFC 4: the LauncherLauncher.sol
  5. 6.5.What is private, and what is nothere
  6. 6.6.Limitshere
  7. 6.7.Gas, measuredhere
  8. 6.8.Questionshere

6.1.RFC 1: the Token

PRIVATE SESSION . zkAPI for the pool . Ethereum . sessionevm.xyz . x.com/session_evm

Network Working Group
Request for Comments: 1 (the Token)
Category: Standards Track
PRIVATE SESSION
October 2026

SESSION

1. Supply

1,000,000,000 SESSION are minted once, in the constructor, to whoever deploys this contract (the Launcher, which places them in the pool and hands the rest to its deployer). No mint function exists.

2. Authority

There is none. No owner, no admin, no pause, no blacklist, no trading switch, no proxy, no upgrade.

3. Transfers

Free. A transfer costs gas and nothing else. The toll is charged on swaps by the pool's hook (the Meter), never on a transfer.

4. Burn and permit

burn and burnFrom MAY be called by any holder: supply can only fall. EIP-2612 permit is supported, so approving the Server for a deposit MAY be a signature.

5. Hidden balances

SESSION deposited into the Server becomes a hidden balance: a note only its holder can spend, earning the cover (RFC 2, section 6). The token contract itself knows nothing of this; to it the Server is an ordinary holder.

Not advice. SESSION can go to zero.

The header of privatesession/PrivateSession.sol, its first 30 lines, as built on 2026-10-02.

6.2.RFC 2: the Server

PRIVATE SESSION . zkAPI for the pool . Ethereum . sessionevm.xyz . x.com/session_evm

Network Working Group
Request for Comments: 2 (the Server)
Category: Standards Track
PRIVATE SESSION
October 2026

Private Usage Credits for the Pool

Abstract

zkAPI (the Ethereum Foundation and the Open Anonymity Project, October 2026) lets a person pay for a metered API without being known: deposit once into a vault, then authorize bounded usage with zero-knowledge proofs instead of an identity. This contract applies the idea to the most used API on Ethereum, a Uniswap pool, and puts the server on chain. Value enters in public and leaves in public, to the address it came from. In between, every session of trading is authorized by a proof that names no note, no deposit and no person. PRIVATE SESSION is not affiliated with zkAPI or its authors.

1. Conventions

The key words MUST, MUST NOT and MAY are to be read as in RFC 2119. Amounts are in wei. "SESSION" is the token (RFC 1); "a session" is a private trading session (section 4).

2. Notes

A note is (tag, s, eth, tok, accE): tag the address that deposited, s a secret only its holder knows, eth and tok its hidden balances, accE the cover accumulator when it was made. Its leaf is H(3, H(2, tag, b), eth, tok, accE) with (b, nf) = Perm(1, s, 0, 0, 0), H one Poseidon permutation (width 5, BLS12-381 scalar field) read at state[0]. Leaves live in a four-way Poseidon tree of depth 10 (1,048,576 leaves); a full tree is followed by a fresh one, so the protocol never runs out of room. Every root any tree has ever had stays valid: a proof MAY name any of them. Spending a note publishes its nullifier nf, which MUST NOT have been published before.

3. Deposit

Anyone MAY deposit ETH and SESSION. The note's tag is the depositing address, written by this contract, so the note can only ever be withdrawn to that address. A deposit is public: who, how much, when.

4. Sessions

A spend proof (section 7) moves part of a note into a session: a public, ownerless account holding the reserved ETH and SESSION and a program of up to eight orders, each a swap on the pool with an amount, a minimum output, an optional price limit, an optional price trigger, and a time window. Anyone MAY fire an order whose conditions hold and is paid for it from the session (section 8). An order that would fill below its minimum MUST NOT fire. When every order has fired, or the session expires (at most 30 days after opening), anyone MAY close it: what it holds becomes a fresh note owned by the same tag, as a leaf whose owner commitment was fixed, and proven, when the session opened. A session MAY be topped up from another note of the same tag. Nothing on chain says whose a session is.

5. Withdrawal

A spend proof MAY instead pay out of a note directly, and then only to the note's tag: the address that made the deposit it descends from. Nothing can be withdrawn anywhere else. No value moves between tags except through the pool, as a trade.

6. Cover

The Meter (RFC 3) charges 2% of the ether leg of every swap and sends it here. Tolls stream over one day to hidden SESSION: a note earns floor(tok x (acc - accE) / 2^64), settled into its change when it is next spent. Nothing streams while fewer than 1,000,000 SESSION are hidden; what would have streamed is carried into the next day. A note earns only while its tokens are hidden, never while they sit in a session. Floors all round toward this contract: what is owed never exceeds what came in.

7. The proof

PS-PLONK over BLS12-381: KZG commitments against Ethereum's own powers of tau from the EIP-4844 ceremony (141,416 contributions), checked by the EIP-2537 precompiles. No setup was made for this protocol, and no one holds a secret that could forge a proof unless every ceremony contributor did. Public inputs: root, nullifier, change leaf, ethOut, tokOut, owner out, accUsed, isWithdraw, withdraw tag, noChange, action. The action binds the proof to what it is used for (the program, the session, the relayer and fee cap, a deadline), so a proof MUST NOT be usable for anything else.

8. Relayers and keepers

Whoever submits a proof MAY be paid by it, up to the cap the proof names and never more than the gas it spent times (basefee + 1 gwei). Whoever fires or closes a session is paid the same way from the session, at most 0.003 ETH a call. The calldata repaid is the call's exact canonical length, and a call carrying any byte more MUST be refused, so the submitter cannot pad its way to the cap. Gas is counted as the call spends it, before the refund the chain gives back for a closed session's cleared storage: an open that leaves its session running is repaid within 0.3% of its receipt, a call that closes one 2% to 8% above it (measured on a mainnet fork). Nobody can be paid more than that, so no relayer can be used to move value. A close is repaid on a fixed estimate of the gas its return note's climb burns (760,000), within the same cap. The cap is a ceiling, not a promise: above a base fee of about 2.4 gwei it no longer covers a fire that also closes the session, and such a session waits for anyone willing to close it, its owner included.

9. What is private, and what is not

Private: which note paid for a session, which sessions belong together, and which deposit a withdrawal's value travelled through. Public: every deposit and its depositor, every session (its program, its trades, its balances), every withdrawal and its destination, the total hidden. A session opened from the depositing wallet itself is that wallet's in public; it SHOULD be submitted from another address or through a relayer. Amounts are visible: a session that reserves exactly what was deposited points at the deposit. It hides behaviour, never ownership. It is not a mixer.

10. Limits

No owner, no admin, no pause, no upgrade. Not audited. Proofs are made in the browser: about 3 seconds in a desktop browser (measured), longer on a phone. The anonymity set is the set of unspent notes: small at first.

The header of privatesession/Server.sol, its first 90 lines, as built on 2026-10-02.

6.3.RFC 3: the Meter

PRIVATE SESSION . zkAPI for the pool . Ethereum . sessionevm.xyz . x.com/session_evm

Network Working Group
Request for Comments: 3 (the Meter)
Category: Standards Track
PRIVATE SESSION
October 2026

The Meter: a Toll on Every Swap

Abstract

The Uniswap v4 hook on the one ETH / SESSION pool (flags 0x20CC). Every swap pays 2% of its ether leg. The toll is sent in the same swap to the Server (RFC 2), which streams it over a day to every hidden SESSION balance: the crowd that hides a trader is paid by the trading.

1. Conventions

The key words MUST, MUST NOT and MAY are to be read as in RFC 2119.

2. The toll

Every swap MUST pay 2% of its ether leg, whoever sends it: wallets, routers, bots, and the Server's own private sessions alike. Private and public trading pay the same; privacy is not bought with the toll. The rate on the four shapes of swap: exactly 2.00% on exact-in buys and exact-out sells, where the ether amount is named and the toll is taken from it before the swap; about 2.04% on exact-in sells and 1.96% on exact-out buys, where it is taken from the ether that actually moved, after the swap. A buy that names its ether and is stopped early by its own price limit still pays 2% of the ether it named.

3. The pool

Native ETH / SESSION, 0.30% LP fee, tick spacing 60, opened within 50 ticks of OPENING_TICK: the price is pinned, not the caller, so nobody can open the pool anywhere else first. A swap on an empty pool, a swap that would end with no liquidity in range, and a swap ending outside -887220 to 887220 MUST be refused. The liquidity bits are clear: adding and removing liquidity never touches the Meter.

4. Authority

None. No owner, no settings, nothing it can be told to change.

The header of privatesession/Meter.sol, its first 34 lines, as built on 2026-10-02.

6.4.RFC 4: the Launcher

PRIVATE SESSION . zkAPI for the pool . Ethereum . sessionevm.xyz . x.com/session_evm

Network Working Group
Request for Comments: 4 (the Launcher)
Category: Standards Track
PRIVATE SESSION
October 2026

Opening Day, in One Transaction

Abstract

Deploying this contract is the launch. The proof verifier and the Poseidon contract are pure and stateless and are deployed first, by anyone; their addresses are passed in. Then, in this constructor, in order, or not at all:

  1. SESSION is deployed: 1,000,000,000 minted to this contract (its CREATE nonce 1).
  2. The Meter (the pool's hook) is deployed with CREATE2 at a salt that lands it on an address carrying exactly the flags 0x20CC (nonce 2). It is told the Server's address in advance.
  3. The Server is deployed (nonce 3) and MUST be exactly where the Meter was told.
  4. The ETH / SESSION pool is initialized at the opening tick.
  5. Full-range liquidity is added through Uniswap's PositionManager with the attached ether and this contract's SESSION. The position (an ordinary Uniswap LP NFT, removable by its holder), any ether left over, and every SESSION not placed in the pool go to the deployer.

It keeps nothing and has no functions. A launch planned for a different nonce fails a check and reverts whole.

The header of privatesession/Launcher.sol, its first 26 lines, as built on 2026-10-02.

6.5.What Is Private, and What Is Not

The Server hides one thing: the link between a deposit and what its value does afterwards. Everything else is on the chain in public, as it is for any contract. This is RFC 2, section 9, row by row.

whatwho sees itbecause
a deposit: who, how much, wheneveryonea deposit is an ordinary transaction, and its note is tagged with its sender
which note paid for a sessionits holder alonethe proof names a root of the whole tree and a nullifier, never a leaf
which sessions belong togethertheir holder aloneevery spend publishes a fresh nullifier: two sessions of one holder look like two holders
a session: its orders, trades and balanceseveryonea session is a public account; keepers read its orders to fire them
whose a session isits holder alone, unless they send it from their depositing walletits owner is a commitment, H(2, tag, b), and b is secret
a withdrawal: how much, and to whereeveryoneit can only go to the tag, the address that deposited
which deposit a withdrawal came throughits holder aloneit is proven like a session, against the whole tree
the total hiddeneveryoneit is the Server's own balance

How people link themselves anyway, and what to do instead:

  1. The wallet that sends it. A session opened by a transaction from the depositing wallet is that wallet's, in public. Send it from another address, or hand the relay ticket to a relayer (page 4).
  2. Amounts. A session that reserves exactly what was deposited points at the deposit. Reserve part of a note, and leave round numbers alone.
  3. Timing. A session opened a minute after the only deposit of the hour points at it. Let other deposits and sessions go by first.
  4. Few notes. The anonymity set is the set of unspent notes, and in the first days it is small. A patient observer narrows it by elimination.
  5. Your connection. The RPC this page reads through sees your IP address and the logs you ask for. Your own node, or a browser on Tor, removes that.
  6. Your signature. The key to your notes is your wallet's signature of one message. Whoever holds that signature can find your notes and spend them into sessions of their own design, made to lose to a trader on the other side; they still cannot withdraw anywhere but your address. Sign it only here.

It hides behaviour, never ownership. It is not a mixer: value leaves only to the address it came from, so the Server cannot be used to pay anyone else.

6.6.Limits

  1. No owner, no admin, no pause, no upgrade. Nobody can stop it and nobody can fix it: a fault found after launch stays.
  2. Not audited. Tested, not audited: 47 checks on a mainnet fork, 5 dry runs against live mainnet state, 16 tests of the proof system and 19 of the spend circuit, six of those provers that lie. An adversarial review found one serious fault, relayers padding their calldata to be repaid more, and it was fixed and tested again.
  3. A new proof system. PS-PLONK was written for this protocol. Its setup is Ethereum's and its curve is BLS12-381, but its circuit and its verifier are new code, without years of use behind them.
  4. Cost. Privacy costs gas a public swap does not: about 2,120,000 for a one-shot private buy, against 135,000 to 220,000 for a public one (section 6.7). At a base fee of 1 gwei that is about 0.0021 ETH; at 20 gwei, about 0.042 ETH. Small sessions do not pay for themselves.
  5. Keepers. A keeper is repaid at most 0.003 ETH a call. Above a base fee of about 2.4 gwei that no longer covers a fire that also closes a session, and such a session waits until someone closes it, its owner included.
  6. Fills. An order fills against the pool as it stands when fired. Its minimum output and price limit are its protection, and the page sets the minimum from a quote. An order cut short by its price limit pays the toll on the amount it named.
  7. Proving. Proofs are made in the browser: about 3 seconds in a desktop browser, longer on a phone, which may run out of memory.
  8. Tickets. A ticket that names no relayer can be sent by anyone, and whoever sends it first is repaid. It opens the same session either way.
  9. Room. A tree holds 1,048,576 notes. A full tree is followed by a fresh one, and every root any tree has had stays valid.

6.7.Gas, Measured

Receipts from the fork simulation against Ethereum mainnet's PoolManager and PositionManager, read from privatesession/measured.json when this site was built.

transactiongasruns
launch (Launcher constructor)6,155,2171
public buy (rig)134,905 to 220,3097
public sell (rig)150,7881
deposit807,546 to 916,8649
poke41,4581
open + fire + close (one-shot private swap)2,120,7681
open (keeper program, no fire)1,408,4001
whale buy (moves the price)156,6371
fire (keeper) + close883,4201
open + fire order 0 (DCA)1,519,8741
fire (DCA day 2)160,5021
topUp1,296,0821
fire (DCA day 3) + close905,9021
withdraw (all of a note, to its depositor)676,5031

6.8.Questions

Is this a mixer?

No. A mixer lets value leave to an address that did not put it in. Here a withdrawal can only go to the address that made the deposit it descends from, and nothing passes between people except by trading on the pool. What is hidden is behaviour: which trades are whose.

Is this zkAPI?

No, and it is not affiliated with zkAPI, the Ethereum Foundation or the Open Anonymity Project. It takes zkAPI's idea, pay once in public and then use a service under proofs that name no one, and applies it to a Uniswap pool, with the server as a contract.

Who runs the server?

Nobody. The Server is a contract with no owner. Keepers and relayers are whoever shows up, and each is repaid gas and at most a gwei a unit of it: running one is a public service at cost, not a business.

Why is there a token?

The pool needs something to trade, and the crowd needs a reason to stay. Every swap pays a 2% toll on its ether leg, streamed to hidden SESSION: whoever keeps SESSION hidden is paid to be the crowd that private sessions hide in.

What if this site goes away?

Nothing on chain changes. The site is a folder of static files that reads the chain directly; any copy of it works, from any host. Your notes are on chain and their key is one signature, so any copy recovers them.

What if I lose my wallet?

Your notes go with it. They can only ever be withdrawn to that address, so a wallet nobody can sign with holds them for good.

Can someone take my notes?

Not away from your address: every withdrawal goes to it. But the key to your notes is one signature, and whoever holds it can trade them into a loss. Sign it only on this site, and never when a page asks for it some other way.

Why BLS12-381 and not BN254?

Because Ethereum already had a setup for it. The EIP-4844 ceremony made powers of tau on BLS12-381 with 141,416 contributions, and the EIP-2537 precompiles made the curve affordable to verify on chain. On BN254 the protocol would have needed a ceremony of its own, and asked you to trust it.

Can I trade SESSION without a session?

Yes. The pool is an ordinary Uniswap v4 pool with the Meter as its hook: any wallet, router or bot that reaches v4 pools with hooks can swap on it, and pays the same 2% toll. Only private sessions need this site, or any other client of the Server.

Where is the code?

The four contract headers are on this page, read from the source when the site is built. The source is verified on Etherscan once deployed, and page 5 compares the code on chain with it byte for byte. The code this site runs is plain JavaScript, readable in your browser.