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.

REGISTER, SHARD 00132 / 32

The lot descends 5 levels. Every slot stays encrypted.

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 are a complete draw, not a fragment of one.

SEQUENTIAL HCU1M2M3M4M5M6M14163264256STAKES IN THE REGISTER5,000,000 HCU. Transaction reverts here.Linear scan. Reverts at 30.Sortis. Reverts at 64.one shard
Linear scan, one dependent add per depositorSortis, one encrypted descent per tree level
Linear drawReverts past 30
Cost per depositor162,000 HCU
At 32 stakes5,184,000 HCU
At 256 stakes41,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

Measured by test/HCU.t.ts against the FHEVM mock coprocessor at commit c234b6a, sweeping register sizes until a draw reverts rather than assuming where it will. A real draw on Sepolia at height 2 reported 2,199,000 HCU against the mock’s 2,199,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 every number here.

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.

Deposits queue instead. At the end of each epoch the whole queue is wrapped and credited together, so the on-chain link between a public sender and a confidential stake is one-to-many across everyone who queued in that window. Four hours on Sepolia, longer on mainnet.

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.