Vault Invariants
Vault invariants keep maker accounting well-defined across time.
The vault is a daily ledger: trades move pricing continuously, while maker-side results are realized at a single batch boundary. These invariants are the rules that make that boundary coherent and reproducible.
Daily accounting invariants
The daily batch produces one accounting update for the day.
Key properties:
- Single update: exactly one batch update realizes maker results for a day.
- Share price definition: share price is derived from vault value and total shares at the batch boundary.
- Deterministic rounding: rounding rules are fixed and applied consistently.
Daily accounting is intentionally coarse. The specification is not "continuous accounting." The specification is "one well-defined boundary per day."
Batch processing also has readiness invariants. A daily batch is only admissible once every market assigned to that batch day has been resolved (settled on the primary or secondary path). Batch processing reverts if the batch is not ready. This makes the accounting boundary depend on explicit settlement finality rather than on an off-chain assumption about which markets "should have" settled.
Batch readiness is therefore part of correctness, not a dashboard convention. A day either resolves on-chain or it does not. The vault does not process "most of the day" and patch the remainder later.
One useful way to state the share accounting invariant is:
where the values are read at the batch boundary. Within a day, trades can move the pricing curve continuously, but vault value is realized discretely at the batch.
The boundary nature of the update also implies a conservation-style check. If is the pre-batch vault value and is the realized net change from the day, then:
subject to the fee-allocation and rounding rules. The key invariant is that the update is single-step and deterministic, not that is smooth.
Request queue invariants
Deposits and withdrawals are represented as requests that become eligible at a future batch boundary.
Key properties:
- Eligibility: requests execute only at eligible batch boundaries.
- Single processing: no request can be processed more than once.
- Conservation: batch totals equal the sum of eligible requests.
Batching is the fairness device. It prevents "react after the outcome" behavior from being expressed as a timing advantage in accounting.
Another invariant framing is that requests are not part of intraday pricing. They are part of day boundaries. A request either executes at a boundary or not at all. This keeps maker accounting from being entangled with intraday trade timing.
The request system also enforces escrow at request time:
- Deposit requests reserve funds as pending deposits.
- Withdrawal requests burn the requester shares immediately and convert the withdrawal into a pending claim on future batch assets.
Burning shares at withdrawal request time prevents double-spend behavior. The same shares cannot be transferred after the request and cannot be withdrawn twice.
Request execution at a boundary can be described as a conversion at a single batch price:
- Deposits convert ctUSD into shares at the batch share price.
- Withdrawals convert shares into ctUSD at the batch share price.
The exact mint and burn amounts depend on rounding rules at token precision, but the invariant is that conversion uses a single boundary price and happens only at eligible boundaries.
Queue integrity also requires "too late" behavior. Once a batch has been processed, requests eligible for that batch cannot be cancelled or re-ordered, because their effects have been reserved in vault accounting. This turns the batch into a true checkpoint rather than a soft suggestion.
Deposit claiming has a related invariant: residual refunds. Deposits are converted into shares using floor division at the batch price. Any remainder is refunded rather than retained by the vault. This keeps conversion conservative without accumulating user dust inside the vault.
Capital accounting invariants
Capital accounting is discrete.
Key properties:
- Boundary updates: vault value and share price update only at the batch.
- Deterministic update rule: the batch update is a pure function of the day inputs and the current vault state.
- Share conservation: total shares change only through batch processing.
The implementation also enforces a non-bricking invariant for shares: total shares must not fall below a small dead-share threshold. This prevents a corner case where a withdrawal would reduce the vault to zero shares and make future share accounting undefined.
The dead-share threshold is implemented by minting a small amount of shares to a dead address at seed time. Those shares are not withdrawable. The intent is not economics. The intent is arithmetic safety: sharePrice requires dividing by totalShares, so totalShares must never reach zero.
Another accounting invariant is escrow separation. The vault tracks pending deposits, pending withdrawals, and payout reserves separately and excludes them from the free balance available for transfers. This is what makes "pending" funds non-spendable for unrelated flows.
This separation can be stated as a free balance identity over token units:
If tokenBalance is smaller than reserved totals, freeBalance is treated as zero. Transfers and claims are gated against freeBalance so escrowed funds cannot be spent twice.
If these invariants hold, ownership and attribution do not depend on timing games or discretionary interpretation. If they fail, maker accounting becomes ambiguous and results stop being comparable across days.
Examples of unacceptable behavior under the invariants:
- Multiple batch updates for the same day.
- A request executing twice or executing mid-day.
- Share price changing without a batch boundary event.
- Fee or PnL amounts being counted twice or dropped between trade accounting and the daily update.
Example invariant check
Suppose a day begins with vault value 1,000 and total shares 1,000. If the daily accounting update realizes +10 net value to the vault, the post-batch share price should become 1.01 and the new vault value should become 1,010, subject to rounding rules. If the share price changes without a corresponding batch update, the accounting boundary is no longer well-defined.
The same check can be extended to queued requests. If, at the same batch boundary, a deposit request of 101 ctUSD is eligible and the post-batch share price is 1.01, then the minted shares should be approximately 100 shares, subject to rounding direction. Any deviation must be explainable by the explicit rounding rules, not by discretionary adjustment.
Relation to depth
The vault invariants are not only accounting hygiene. They are part of what makes liquidity depth credible. Depth is underwritten by maker capital, and maker capital is tracked through vault value and shares. If vault accounting is not deterministic and conserved, depth becomes an arbitrary number rather than a mechanism-level capacity constraint.
Request fairness
Batching turns deposits and withdrawals into boundary events. The invariant goal is that participants who carried the same day risk are treated equivalently. This is the reason request eligibility is defined at boundaries rather than as an intraday stream.
Without this invariant, maker-side accounting becomes gameable. A participant could enter after favorable intraday information and exit before unfavorable realization, extracting value from the capital stack without carrying the day’s exposure.