DOCS
On this page6 sections

Rewards

Reward Catalog and just-in-time prizes

How FLIP supports many rewards without warehousing every stock token.

JIT Functional Testnet PASS · 7 stock + 1 cash fallback · Formal certification deferred

One versioned Reward Catalog

Coin, Parity, Mystery, capacity checks, and the user interface consume one ordered asset set. Only publish creates a new append-only version and ordered-assets hash; adding, removing, or reordering therefore means publishing a new set. setActiveVersion points admission at an existing eligible version, while deactivateActiveVersion sets the configured pointer to zero. Every accepted Ticket freezes the set identity. Manual freezes its selected reward at acceptance; Mystery freezes only the set and unassigned all-member capacity at acceptance, then freezes the concrete reward in the verified VRF selection callback before RandomReady or AwaitingReport.

Unified USDG Reserve, not one vault per stock

At acceptance, FLIP locks the extra House coverage needed for the Ticket and reserves JIT route capacity. A winner’s principal plus Reserve lock becomes one complete USDG prize liability. The protocol does not have to carry long-lived NVDA, AAPL, TSLA, and every future reward inventory before anyone wins.

Solvency boundary
Reserve USDG balance
≥ active prize liabilities
+ claimable cash fallbacks
+ every other locked Reserve responsibility

Unsettled principal, undelivered stock purchases, unreleased Provider/Reporter Bond, and unrealized FLIP price appreciation are obligations or exposures—not revenue. A single liability key can terminate only once through stock delivery or complete USDG fallback.

Static amount limits are only the first capacity check

Finalized Reserve and global-exposure preview
baseAdditionalRaw = additionalReserveRaw >= bonusRaw
  ? additionalReserveRaw - bonusRaw
  : additionalReserveRaw

generalReserveAvailable =
  availableGeneralRaw >= safetyFloorRaw + baseAdditionalRaw

protectedExposureAvailable =
  totalPendingPrizeNotionalRaw + totalLiabilityRaw + prizeNotionalRaw
    <= maxProtectedExposureRaw

reservationSlotAvailable = activeReservations < maxActiveReservations

mysteryReserveAvailable = manual
  OR (mystery.epochOpen AND mystery.maxStakeRaw >= principalRaw)
Per-asset JIT capacity
inventoryCapacityRaw =
  floor(inventoryRaw × route.reserveDenominator / route.rewardNumerator)

effectiveCapacityRaw = min(routeCapacityRaw, inventoryCapacityRaw)
requiredExposureRaw =
  manualLockedRaw + selectedMysteryLockedRaw + unassignedMysteryLockedRaw

availableCapacityRaw = routeLive
  ? max(effectiveCapacityRaw - requiredExposureRaw, 0)
  : 0

manual JIT check: selected asset availableCapacityRaw >= prizeNotionalRaw
mystery JIT check: every active Catalog asset availableCapacityRaw >= prizeNotionalRaw
Meaning of capacity.admission.ready
ready =
  amountWithinLimits
  AND catalogActive
  AND rewardSupported
  AND !gamePaused
  AND reserveAcceptingGame
  AND jitAcceptingGame
  AND reservationSlotAvailable
  AND protectedExposureAvailable
  AND generalReserveAvailable
  AND mysteryReserveAvailable
  AND jitCapacityAvailable
  AND !reserve.requiresBootstrap

ready == true  ⇔  blockers.length == 0

routeLive also requires an enabled nonzero route whose validity covers the Guard’s minimum TTL. The response exposes the finalized quote, raw Reserve fields, each asset’s route/inventory/effective/locked/available capacity, every admission boolean, and the exact blocker codes. It is advisory only: Bond funding, concurrent state changes, settlement, and the Gateway’s final atomic checks can still reject the transaction.

Winner delivery flow

Observable event path
Bet / Ticket wins
→ LiabilityCreated
→ JitQuoteAttempted
→ StockDelivered

execution failure:
JitPurchaseFailed → liability remains PurchasePending → new quote / retry

SLA expiry:
CashFallbackAvailable → CashFallbackClaimed
  1. 01

    Create liability

    Win settlement fixes player, reward token, notional, rules, Catalog, and cash fallback time.

  2. 02

    Publish signed quote

    An authorized signer binds chain, Guard, Reserve, liability key, recipient, venue, notional, min output, expiry, and nonce.

  3. 03

    Execute against an approved route

    The Executor checks quote and route capacity, spends exactly the liability USDG, and measures actual reward delivery.

  4. 04

    Record StockDelivered

    Delivery succeeds only when the player’s real token balance increases by at least signed min-out and all accounting deltas match.

  5. 05

    Fallback if the SLA expires

    After the frozen SLA, anyone—including a Keeper—may call makeCashClaimable(game, id) to close the JIT window. Only the recorded winner may call claimCash(game, id) and receive the full USDG notional; claimCash can perform both steps when still PurchasePending.

Prize liability state machine

PurchasePending → StockDelivered
PurchasePending → CashClaimable → CashClaimed

StockDelivered and CashClaimed are mutually exclusive terminal states. A failed JIT attempt does not create a third terminal state, reduce the notional, return the Ticket to a loss, or consume the liability; it remains PurchasePending until delivery succeeds or the frozen cash-fallback SLA opens.

Failures cannot erase a win

  • A malformed direct call or a pre-attempt state error can revert. Quote-guard failures and Executor/venue failures reached through attemptJitPurchase are caught, emit JitPurchaseFailed, return false, and do not consume the liability.
  • Expired/wrong-domain/wrong-signer/replayed quotes, route/inventory failure, venue revert, or delivery/min-out mismatch leave PurchasePending; the attempt can be retried with a new valid quote until the frozen SLA closes.
  • Stock delivery and USDG cash claim are mutually exclusive terminal paths.
  • makeCashClaimable is permissionless after the SLA but moves no user funds; claimCash enforces msg.sender == liability.player and always pays that player.
  • The formal Testnet acceptance matrix includes 1/10/50/100/200 USDG notional boundaries, but it must not be labeled accepted until matching finalized evidence is published.

Authority sources

These repository paths were used to derive this page. They link only when an explicitly configured public repository and immutable Source A commit are both available; otherwise they remain plain paths. Release addresses and live status still require an accepted manifest and finalized evidence.

  • src/v3/reserve/UnifiedUsdReserveV3.sol
  • src/v3/jit/JitCapacityGuardV3.sol
  • src/v3/jit/SignedJitQuoteGuard.sol
  • src/v3/jit/TestnetJitPrizeExecutor.sol
  • infra/protocol_v3_acceptance/jit.py