Skip to content

Liquidity Provision

Oracle uses a pure Central Limit Order Book (CLOB) — no AMM, no shared liquidity pools, no LP vaults with share tokens. Liquidity comes from resting limit orders, and the protocol incentivizes LPs in two ways:

  1. Maker rebates — paid per fill, funded from the taker fee. Instant.
  2. Liquidity rewards — a daily USDG budget per market, awarded to wallets that held tight two-sided quotes. Extended quadratic scoring: multi-level depth, gold-band bonus, super-linear uptime weighting, anti-spoofing clamp, 40% per-wallet cap.

Both programs run independently. Any resting order is automatically eligible for both — no opt-in, no vault deposits.


1. Maker Rebates

Every fill on Oracle pays a rebate to the resting (maker) side. Rebates settle into the maker's usdc_balance at match time — spendable immediately, no claim step.

Fee split per fill

Party Flow
Taker Pays taker_fee_bps on notional (default 2%)
Maker Receives maker_rebate_bps of notional (default 0.5%)
Treasury Receives the remainder

Calculation

taker_fee    = floor(fill_size × fill_price × taker_fee_bps    / 10_000)
maker_rebate = floor(fill_size × fill_price × maker_rebate_bps / 10_000)

fill_price is in micro-USDG per outcome token (6 decimals). fill_size is outcome tokens.

Example — fill 1,000 YES @ $0.65, default bps:

  • Taker pays: 1,000 × 650,000 × 200 / 10,000 = 13,000,000 µUSDG = $13.00
  • Maker earns: 1,000 × 650,000 × 50 / 10,000 = 3,250,000 µUSDG = $3.25

Who earns it

Only orders that rest on the book and get matched by an incoming taker earn the rebate. A GTC limit order that sits and gets filled: rebate. A market order (IOC) that crosses the spread: no rebate — it's the taker. Partial fills pay pro-rata.

Changing fees

Fees are read live from the fee config on the PartiVault contract (Robinhood Chain). Changes require an admin tx and are announced ≥24h in advance.


2. Liquidity Rewards

A daily per-market USDG budget is distributed to wallets that hold resting orders inside a configured spread band. The Oracle scoring formula extends a quadratic distance base with five mechanics that reward real depth, uptime, and two-sided balance — and punish spoofing and whale capture.

Per-sample scoring

Every 30 seconds the engine snapshots each market's order book. For each wallet with resting orders, compute:

(a) Per-order distance (quadratic base). For every resting order inside max_spread_bps:

order_score = size × ((max_spread − distance_from_mid) / max_spread)² × in_game_multiplier

A quote at mid earns size × multiplier. Halfway to the band → 25% (0.5²). At the boundary → 0.

(b) Multi-level depth. Sum across every resting order on the side, with a per-level decay by rank-from-mid. Rewards real depth, not just a single tight quote:

side_score = Σ order_score(o) × level_decay(rank(o))
level_decay(rank) = 1 / (1 + 0.5 × rank)      // 1.00 / 0.67 / 0.50 / 0.40 / …

(c) Gold-band bonus. Orders within the tightest 25% of max_spread get a 1.5× multiplier on top of the quadratic.

(d) Combined sides (single-sided penalty).

combined = max( min(bid_score, ask_score),  max(bid_score, ask_score) / c )
c = 2         // stricter than the c=3 used elsewhere; single-sided = 50% credit

Symmetry bonus: if |bid − ask| / max ≤ 0.20, multiply combined by 1.10.

Daily aggregate

uptime = active_samples / 2880        // active = non-zero combined score
daily_score = (Σ sample_scores) × uptime^0.8

Super-linear uptime penalty (uptime 95% → ×0.96, 80% → ×0.83, 50% → ×0.57).

Anti-spoofing clamp: a wallet's cancel_ratio over a rolling 5-min window = cancels / (cancels + fills). If > 0.50 with any cancels, every sample in that window is scored ×0.5.

Daily distribution

At 00:00 UTC, pro-rata by daily_score, then cap at 40% per wallet:

raw_payout(w)   = daily_score(w) / Σ daily_scores × daily_budget_usdc
max_share       = daily_budget_usdc × 0.40
final_payout(w) = min(raw_payout(w), max_share)

Any undistributed remainder from cap enforcement rolls into the next day's budget.

Credits accumulate in a wallet-level claimable_micro_usdc — a single balance across every market.

Per-market configuration

Each market has its own max_spread_bps, min_size, daily_budget_usdc, in_game_multiplier. See GET /v1/rewards/config. Markets without a config earn nothing.


3. Claim Flow

Reward credits are distinct from wallet balance. Claiming moves USDG from the fee treasury to the user via the PartiVault contract on Robinhood Chain.

On-chain plumbing

  • Vault call: claimRewards on PartiVault (Robinhood Chain)
  • Authority: operator only (relayed — user doesn't pay gas)
  • Source: the vault's feeTreasury USDG balance
  • Destination: the user's 0x EVM address

API

POST /admin/rewards/claim
X-Admin-Key: <admin key>

{
  "wallet": "<0x EVM address>",
  "amount_micro_usdc": 5000000         // optional; defaults to full claimable
}

Response (200):

{
  "claimed_micro_usdc": 5000000,
  "remaining": 400000,
  "signature": "0x5e8c..."
}

The signature is the Robinhood Chain tx hash. remaining reflects claimable_micro_usdc after the decrement; the decrement is atomic and clamps at zero (never negative, even on over-claim).

Failure mode: tx succeeds, Redis decrement fails

If the on-chain tx lands but the Redis decrement errors, the response is still 200 with remaining: null and a warning field flagging manual reconciliation. The funds are delivered on-chain; only the accounting counter is out of sync. Operator must reconcile manually.

Public self-service endpoint

Not yet shipped. Today all claims are operator-relayed and admin-key-gated. Market makers running continuous strategies should arrange scheduled sweeps with the Parti team.


4. Running a Market Maker

The reference market-making bot is oracle-lp (Rust). It:

  • Subscribes to the order-book WebSocket
  • Maintains symmetric two-sided quotes around mid, scaled by spread_bps and size
  • Cancels and re-posts when mid moves > requote_bps
  • Tracks inventory per market, skews the constrained side on drift

Typical loop (pseudocode)

while True:
    book = GET /v1/markets/{id}/book
    mid  = book["yes_price"]                   # basis points (1..9999)

    # Cancel existing resting orders
    POST /v1/orders/cancel-all  { market_id, user, signature, nonce }

    # Re-post inside the rewards band
    for offset_bps in [spread_bps, spread_bps*2, spread_bps*3]:
        POST /v1/orders  {
            side: "buy",  outcome: "yes",
            price: max(1, mid - offset_bps),
            size: N,  order_type: "gtc",
            signature, nonce
        }
        POST /v1/orders  {
            side: "sell", outcome: "yes",
            price: min(9999, mid + offset_bps),
            size: N,  order_type: "gtc",
            signature, nonce
        }

    sleep(5)

Order type is gtc (not post_only) because cancel-all runs before each rebalance, so there are no stale LP orders to cross with.

Picking spread_bps

Quote inside the market's max_spread_bps — quotes outside earn rebates on fills but score 0 for rewards. Rule of thumb: spread_bps ≈ max_spread_bps / 4 for the tightest level, widening geometrically.

Key endpoints for market makers

Endpoint Use
GET /v1/markets/{id}/book Current order book state
POST /v1/orders Place orders (gtc or post_only)
POST /v1/orders/cancel-all Bulk cancel before requoting
WS book:{market_id} Real-time book updates
GET /v1/rewards/config Per-market max_spread_bps, min_size, daily_budget
GET /v1/rewards/leaderboard?market_id= Current-day scoreboard
GET /v1/rewards/wallet/{wallet} Cumulative claimable balance

5. Funding

Fund your trading balance by sending USDG on Robinhood Chain to your per-account CREATE2 deposit address (minimum 1 USDG). The watcher sweeps it into the vault and credits your off-chain engine balance, usually within a minute — see Deposits & Withdrawals for the full flow, addresses, and the withdraw path (EIP-712, sequential vault nonce).


6. Why CLOB, not AMM

  1. Correct price discovery — prediction markets have binary terminal values, so LP-against-AMM strategies bleed to informed traders. A CLOB lets makers step back when they're out-gunned.
  2. Risk isolation — one market's volatility doesn't affect another's liquidity.
  3. LP control — makers choose exactly which markets to provide on, at what spread, with what size.
  4. Capital efficiency — no idle depth in deep out-of-the-money bands; capital quotes where the flow is.