Confidential prize-linked savings

Save. Never lose. Nobody sees.

Your deposit earns a share of the pooled yield as a prize. Your balance, your odds and whether you won stay encrypted end to end, and the draw itself stays publicly verifiable.

32 stakes per shard. 5 levels. 4,476,000 HCU.

THE DESCENT, ILLUSTRATEDnot live data

A diagram of the walk, over 5 levels. On chain the resolved leaf is encrypted and no client can locate it. The live register is on the draw screen.

02

The constraint

A linear draw dies at thirty depositors.

FHEVM caps the longest chain of dependent operations in a transaction at 5,000,000 HCU. Encrypting balances and scanning them puts every depositor in that one chain, so it stops working almost immediately. Sortis descends a tree instead, which puts one short chain per level in the budget rather than one per person. Both curves describe a complete draw, not a fragment of one. The Sortis curve is swept until the transaction reverts; the linear one is its per-depositor cost multiplied out, because a scan that reverts cannot be measured past the point it stops fitting.

The two failures are not the same failure. A linear scan is one dependent chain, so at thirty depositors it is finished and no amount of splitting helps. A Sortis shard holds 32 and then a second shard opens. The dashed continuation is what one oversized shard would cost, and it is drawn only to show why the ceiling is where it is.

SEQUENTIAL HCU1M2M3M4M5M6M14163264256STAKES IN THE REGISTER5,000,000 HCU. Transaction reverts here.Sortis. 32 per shard, then another opens.Linear scan. Dead at 30, and cannot be split.32 per shard
Linear scan, one dependent add per depositorSortis, one encrypted descent per level. Dashed past the shard ceiling.
Linear drawProjected past 30
Cost per depositor, measured162,000 HCU
At 32 stakes, derived5,184,000 HCU
At 256 stakes, derived41,472,000 HCU
Draws from30 stakes
Sortis, one shard90% of budget
Cost per tree level728,000 HCU
Draw at 32 stakes4,476,000 HCU
Commit and release713,000 HCU, flat
Draws from32 stakes per shard

The Sortis curve is measured by test/Calibration.t.ts against the FHEVM mock coprocessor at commit 3f79c22, sweeping drawLot, the whole settling transaction, until it reverts rather than assuming where it will. test/HCU.t.ts sweeps the walk on its own and reports a higher ceiling; a walk is not a draw, and the number that sets capacity is the cost of the transaction that has to land. The linear curve is derived, not swept: it is 162,000 HCU per depositor multiplied out, because a scan that cannot fit cannot be measured past the point it reverts. Two real draws on Sepolia at the deployed height 5 each reported 4,476,000 HCU against the mock’s 4,476,000, so the two agree exactly. Depth is the budget that binds, not global work, so this ceiling cannot be raised by splitting a draw across transactions. Run npm test to reproduce both tables.

03

The sequence

How a draw works.

Four steps, in this order. The gap between the second and the third is the security argument, not an implementation detail.

  1. 01

    Commit

    Money enters as confidential cUSDT. Weight accrues from how much sat in the pool and for how long, so a deposit made a moment before a draw carries nothing.

    commit() 920,000 HCU
  2. 02

    The root is snapshotted

    Opening a draw publishes the register root and the block. No randomness exists yet, anywhere, so the operator has to commit to the tree before learning anything about who it favours.

    openDraw() no randomness yet
  3. 03

    The lot is drawn

    In a later block, the chain itself produces the lot with FHE.randEuint64. No oracle and no VRF. If the register moved since the snapshot, the root handle changed and the draw is void.

    drawLot() one block later
  4. 04

    One slot resolves

    The walk descends the shard, one encrypted comparison per level, halving what is left each time. It lands on a leaf and the index stays encrypted. Only the drawn address can decrypt what it holds.

    32 stakes, 4,476,000 HCU
04

The threat model

What stays private, and what does not.

The right-hand column is deliberate. Public verifiability is the point of the design, and a draw nobody can check is not worth having.

Privateencrypted
Your depositeuint64, encrypted in your wallet before it is sent
Your balanceeuint64, decryptable by you and nobody else
Your weighteuint64, the time-weighted stake the draw reads
Whether you wonThe resolved leaf is an encrypted index
What you were paidA losing claim transfers an encrypted zero
Publicon chain
The pot sizeHarvested yield, plaintext, so the draw can be checked
The tree rootA handle, published when the draw opens
The blockThe lot must come from a later one
That a draw happenedAnyone can verify the walk ran against that root
That you interactedYour address, the time, and the direction
05

The limitation

The wrap leak, addressed.

Money arrives as public USDT. If wrapping it into confidential cUSDT happened in the same transaction as the deposit, the amount would be readable one call before it became private, and the encryption would buy nothing.

The queue is deployed and the app does not use it yet. Committing goes straight to the pool, which is the legible path for anyone trying this and the less private one: your wrap and your stake are one transaction apart and the amount is readable in between.

What the queue buys, once deposits route through it, is a one-to-many link instead of a one-to-one: an epoch closes, the whole queue is wrapped and credited together, and a public sender maps to any stake settled in that window rather than to one. Four hours on Sepolia, longer on mainnet. The limits below apply to that design and are the reason it is described here rather than claimed as a privacy guarantee.

What batching does not fixhonest limits
Alone in an epochNo anonymity set at all. One deposit in, one stake out.
Distinctive amountsAmounts are not mixed. Sizes can be matched back.
Settlement orderEach credit emits an event naming the stake owner.

Batching raises the cost of linkage. It does not eliminate it. Anything stronger needs equal denominations and a real mixer, which is a different protocol.