Skip to content

Escrow invariant

fact For every series s and at every point in time after every external call:

quoteEscrow(s) == N_c(s) + prefundRemaining(s) + claimableQuote(s) + refundableQuote(s) + accruedFees(s) stockEscrow(s) == stockMatched(s) + refundableStock(s) + claimableStock(s)

where

TermMeaning
quoteEscrow, stockEscrowUSDG and Stock Token balances the series holds inside NoteCore
N_cMatched COUPON notional not yet redeemed (COUPON principal); 0 once breached, when it becomes SHIELD’s claimableQuote
prefundRemainingSHIELD’s remaining maximum coupon liability
claimableQuoteNet coupons accrued (the couponPool) and terminal payouts booked but not yet pulled
refundableQuoteUnmatched COUPON deposits and unmatched SHIELD prefund
accruedFeesProtocol fees not yet swept, from which keeper rewards are paid
stockMatchedStock backing matched notional; on breached it becomes COUPON’s claimableStock
refundableStockUnmatched SHIELD stock

The implementation states the same identity in its own bucket names (couponSideQuote + prefundRemaining + prefundRefundable + couponPool + accruedFees), where couponSideQuote covers both matched principal and unmatched COUPON deposits.

  1. No path can pay out more than escrowed. Every transfer out of NoteCore debits exactly one bucket on the right-hand side and quoteEscrow/stockEscrow on the left by the same amount. The identity is checked in tests after every handler call.
  2. No liquidations. Because SHIELD’s maximum liability is escrowed at subscription, there is never a moment where a price move creates an unfunded obligation.
  3. No principal risk in NoteCore. The protocol’s only balance is accruedFees. It is never used to fund coupons or redemptions.
  4. Isolation. The invariant is per series. A failure in one series (for example an oracle deferral) cannot draw on another series’ escrow.
quote escrow (USDG) N_cCOUPON principal prefundRemainingSHIELD max coupons claimableQuotecoupon pool + payouts accruedFees→ feeSink, keepers refundableQuote net coupon fee 15% · notional fee 0.25% breached at maturity: principal becomes SHIELD's claim stock escrow (Stock Tokens) stockMatchedN × 1e8 / s0 refundableStock claimableStock (breached)delivered to COUPON on redeem
Every observation moves one gross coupon out of prefundRemaining: the net part into claimableQuote, the fee into accruedFees. Nothing enters or leaves the sum except through deposits and pulls.
EventDebitCredit
depositCouponexternal USDGrefundableQuote (until strike)
depositShieldexternal USDG, stockprefund and stock buckets (until strike)
finalizeStrikedepositsN_c, prefundRemaining, stockMatched; unmatched → refundable; notional fee → accruedFees
Coupon observationprefundRemaining (gross)claimableQuote (net), accruedFees (fee)
Keeper paymentaccruedFees, quoteEscrowexternal (keeper)
Autocall / maturity, barrier holdsshieldUnusedPerUnit fixed from prefundRemaining
Maturity, breachedN_c → SHIELD claimable; stockMatched → COUPON claimable
claim, redeem, redeemShield, refundcorresponding bucket and escrowexternal (holder)
sweepFeesaccruedFees, quoteEscrowexternal (feeSink)
  • Coupon index is WAD, rounded down; dust stays in claimableQuote and is unreachable, which is conservative.
  • Stock matched at strike is rounded up so the physical-settlement quantity units × 1e12 × 1e8 / s0 can always be delivered.
  • Prefund matched is rounded up so prefundRemaining always covers (observations.length − 1) gross coupons at the cap.

The invariant is the primary target of the specified handler-based invariant suite: random sequences of deposits, strikes, observations with fuzzed prices, transfers, claims, redemptions, refunds and sweeps across many actors and series, with the identity asserted after every call. Additional assertions: total USDG paid out never exceeds total deposited plus zero; NoteLegs total supply per id equals matched notional until redemption. status At the time of writing the repository contains unit tests for the core and token modules and stateless fuzz tests (test/fuzz/core/Settlement.fuzz.t.sol checks coupon-index conservation across transfers and the physical-settlement sum bound); the handler-based invariant suite in test/invariant is not yet committed. See Security: Invariants.