Skip to content

Cell Seal: Flows ​

Read overview.md first. This document describes each business flow at the level of "who does what, what goes on chain, what the market sees". Contract signatures: contracts.md. Data flow through the SDK and its host services: architecture.md section 8.

1. Order model ​

Every subscription, redemption and secondary transfer is an order with two legs.

LegWhat it isWhere it can live
Share legFund shares change handsAlways on-chain, inside the share wrapper, sealed
Cash legMoney changes handsOff-chain (fiat through a ramp, issuer attests) or on-chain inside the cash wrapper, sealed

Each leg has its own status: pending, then delivered, then confirmed. The status changes only when the chain has confirmed (on-chain leg) or when the issuer attests (off-chain leg). The order is done when both legs are confirmed.

ModeHow the two legs are tiedCash leg
DoPSeparate. The second leg is triggered only when the first is confirmedFiat or sealed stablecoin
DvPOne transaction, all-or-nothing. Each side checks the other side's amount before signingSealed stablecoin

Two moments are kept apart: strike is when the NAV is published and orders are priced. settlement is when the settlement window closes, when the net is wrapped or unwrapped and the shares of new subscriptions are actually delivered. Before settlement, the net shares of the period are not yet inside the wrapper. Minting and burning the fund token is the issuer's job on the platform's rail, not the job of settlement (integration.md section 4).

Every sealed transfer goes through the settlement contract with an order_id. Its events are what the order store (the platform's, or the sandbox backend's) uses to change leg status.

Mode is a property of the order, not of the fund: the same fund can take subscriptions in fiat (DoP) and let holders transfer on the secondary market in stablecoin (DvP).

2. Onboarding a fund ​

Case 1: create a new token. Case 2: token exists / authorize wrapper if AUTH_REQUIREDDeploy the wrapper for the tokenk-of-n viewing key ceremonyRegister the auditor keyConfigure policy (whitelist + KYC) and settlement windowCase 2: existing holders wrap their own balance.Those numbers were already public, nothing is lost.Platform / IssuerFund tokenShare wrapperKey holders (issuer, TA, regulator)

Case 1, a new fund: the platform issues the token and deploys the wrapper in the same pass, so no holder has to wrap and no balance was ever public. Case 2, an existing token: holders who have not wrapped stay on the platform's public rail, and the fund runs two rails side by side, integration.md section 5. The sandbox apps implement Case 1, screens design/ 01 to 03. Step-by-step procedures for both cases: onboarding.md.

From this point the public register shows only the wrapper as holder (Case 1), or the wrapper plus the holders who have not wrapped (Case 2). The real register is rebuilt from data decrypted with the viewing key.

3. Subscription ​

3.1 DoP, fiat (default) ​

Place subscription order (amount stays off-chain, never on chain)Fiat transferMoney arrivedCash leg = confirmed (issuer attests)Strike: shares = cash / NAV - feeFund the public NET into the settlement account (mint in Case 1, transfer in Case 2)close_window: deposit the NET of the whole periodsubmit_leg(order_id): sealed shares to InvestorEvent LegSettled(order_id), share leg = confirmedWait for NAV strikeSettlement, window closesInvestorFund platformRamp / bankIssuerShare wrapper

The market sees: the issuer deposits one total into the wrapper per period, and one sealed transfer to the investor's address. It does not see how much the investor bought.

3.2 DvP, stablecoin ​

The investor wraps stablecoin into the cash wrapper first (the wrap amount is public, but tied to no order). At settlement, one settle_dvp call pulls sealed cash from the investor to the issuer and delivers sealed shares from the issuer to the investor. The investor delegates (spender) the cash part when placing the order, so the order still executes even if their balance changes while waiting.

4. Redemption ​

4.1 DoP ​

submit_leg(order_id): sealed shares to the issuer's settlement accountEvent LegSettled(order_id): a transfer, no numberThe issuer is the recipient, so it decrypts the amount itself. Share leg = confirmedcash = shares x NAV - feePay fiat through the ramp, or confidential_transfer stablecoin to HolderCash leg = confirmedWait for NAV strikeEnd of settlement window:close_window unwraps the NET of the period,issuer burns or retires it on the platform's railHolderShare wrapperFund platformIssuerRamp / cash wrapper

The key point: the holder does not unwrap, and the redemption order carries no plaintext amount. The market sees that the holder sent something to the issuer. It does not see how much. The only number that comes out is the net of the whole period.

4.2 DvP ​

The holder delegates the shares to redeem to the fund's settlement account when placing the order. At settlement, settle_dvp moves sealed shares from holder to issuer and sealed cash from issuer to holder in one call. If one leg fails, neither happens.

5. Secondary transfer between two holders: DvP ​

Both holders have passed policy. Seller and buyer agree on a price off-chain, then one transaction swaps sealed shares for sealed cash. This is the only flow where DvP is mandatory: the two sides have no reason to trust each other.

The issuer is not part of the transaction. The side receiving shares sends the opening of its leg to the fund so the register updates immediately. The k-of-n viewing key is used for periodic reconciliation. Policy still blocks transfers to addresses that are not whitelisted.

6. Settlement window ​

During the periodAt the end
Every subscription and redemption is a sealed transfer inside the wrapperThe issuer computes the net: subscriptions minus redemptions
The wrapper balance does not changeNet positive: the issuer funds the public amount into the settlement account, close_window wraps it. Net negative: close_window unwraps, the issuer burns or retires. Net zero: no token moves, the window still closes and emits WindowClosed. settlement neither mints nor burns
The market sees no numberThe market sees one number: the net of the period

The window runs on schedule even when there are no orders, so that "this period had an unwrap" is not by itself a signal.

7. Disclosure ​

Request to open the books for period XContribute key share (k-of-n)Key shareFetch the ciphertext of period XCiphertext, which Cell Seal cannot decryptRebuilt register + proof that it matches the on-chain commitmentsAuditor / regulatorIssuerTransfer agentEvent archive (the platform's indexer)

Every unlock leaves a trace: who requested, who contributed a share, which scope.

8. Where amounts can leak ​

The business view. The master list with ids L1 to L18 and the technical mitigation of each is security.md section 3.

WhereWhy it leaksHandling
The platform's order event has an amount fieldSize is exposed at request timeOrders carry only the order reference
Payout in public stablecoinpayout / NAV = number of sharesThe on-chain cash leg is always sealed
The holder unwraps to redeemUnwrap is publicRedeem by a transfer inside the wrapper
Unwrap right after a large orderTiming matches the orderUnwrap on a fixed window
Fee paid separately by a public transferfee / fee rate = sizeFee is computed inside the same sealed transfer
Too few orders in one periodNet is roughly one orderLonger window, configured per fund
The issuer wraps straight to the investor's addressWrap has a public amount with the recipient addressAlways wrap into the issuer's settlement account, then transfer sealed
An investor registers with an auditor_id outside the fundThe fund cannot read that investor's amountsEnforce the fund's auditor_id at registration
Case 2: the platform mints public shares straight to an investor who then wrapsPublic amount, tied to an addressNew shares for a sealed investor always go from the settlement account inside the wrapper. Self-wrap is only for a balance already held, integration.md section 5

Cell Private technical documentation.