For market makers
How Split's cash-settled markets work from the writer's side: the instrument, collateral, pricing, settlement, pool accounting, and the on-chain surfaces a maker integrates against.
Products
Capped call spreads on BTC and ETH, cash-settled in USDG on Robinhood Chain (chain id 4663).
| Underlyings | BTC, ETH |
| Tenor | Daily. Each round matures at 00:00 UTC. |
| Bands per round | 8, contiguous: each band's cap is the next band's strike |
| Up leg (N) | min(max(S − K, 0), W) per unit of underlying |
| Down leg (P) | W − Up |
Width W | cap − strike, fixed when the round opens |
| Collateral and payout | USDG, 6 decimals |
| Leg tokens | ERC-20, 18 decimals. One vault clone per band. |
| Settlement price | Chainlink BTC/USD and ETH/USD on Robinhood Chain |
| Protocol fee | 0 |
Up is a call spread from K to K + W. Down is the put spread from K + W to K. One Up plus one Down pays exactly W at every settlement price.
Band layout
Each round is opened with startEpoch(strikes, caps, maturity):
- 8 bands centred on spot, narrowest at the centre and wider towards the wings.
- Total ladder width scales with
spot × σ√T, using realized vol times a per-market markup.
Example, BTC round maturing 2026-10-15 00:00 UTC:
| Band | Strike | Cap | W |
|---|---|---|---|
| 0 | 79,360.31 | 81,012.35 | 1,652.04 |
| 3 | 83,035.25 | 83,637.30 | 602.05 |
| 4 | 83,637.30 | 84,239.35 | 602.05 |
| 7 | 86,262.25 | 87,914.29 | 1,652.04 |
All eight are on Contracts.
Counterparty
The counterparty to every trade is the market's CashSettledPool:
- Buy Up. The pool takes the premium, locks
Wper unit by minting an N and P pair, gives the buyer N and keeps P. - Buy Down. The pool hands out P it already holds first, and mints a new pair only for the shortfall, keeping the N.
- Sell back. The pool buys the leg at its bid, recombines it with the opposite leg it holds, and frees the collateral.
The pool is a USDG vault with shares. Its value is free USDG plus the value of the legs it holds.
Collateral
| Locked per unit | ceil(qty × W) USDG, when the pair is minted |
| Payouts | Rounded down |
| Margin, mark-to-market calls, liquidation | None, on either side |
| Allocation cap | At most 80% of pool value (free + committed USDG) committed to open positions (maxAllocBps = 8000) |
| Matched Up and Down | One W covers both |
| Withdrawal of committed collateral | The contract has no function for it |
Reverts to handle:
| Revert | Cause |
|---|---|
alloc cap | The buy would push committed USDG past the allocation cap |
inventory | Free USDG can't cover the collateral |
slippage | Cost above maxCost, or proceeds below minProceeds |
expired quote, bad signer, quote/vault, crossed | Quote expired, wrong signer, wrong band, or ask below bid |
not selling | The round is not trading, or maturity has passed |
pool liquidity | A sell back the pool can't pay |
Pricing
Each band is priced as a Black-Scholes call spread, C(K) − C(K + W), averaged over a jump-diffusion spot distribution.
| Input | Value |
|---|---|
| Spot | The settlement Chainlink feed. If it is more than 15 minutes old, a reference price (Coinbase for BTC and ETH). |
| Vol | Realized vol × per-market markup |
| Jumps | Per market. Default jump size 0.08, intensity 8 per year. |
| Rate | 0 |
| Clamp | Neither leg below 0.5% of W |
| Spread | 150 bps total around mid by default, set per market |
| Divergence halt | No quote if the feed and the reference differ by more than 2% |
The pricer signs one quote per band with an Up ask and an Up bid. The contract derives Down:
Down ask = W − Up bid
Down bid = W − Up askSigned quote
EIP712Domain { name: "CashSettledPool", version: "1", chainId: 4663, verifyingContract: <pool> }
Quote { address vault, uint256 askPerN, uint256 bidPerN, uint256 validUntil, uint256 nonce }askPerN,bidPerN: USDG (6 dp) per 1e18 of the leg, i.e. per one unit of underlying.validUntil: 180 seconds after signing.- On chain:
vaultmust equal the band,block.timestamp ≤ validUntil, the signature (low-s) must recover topricer(), andaskPerN ≥ bidPerN. Nonces are burned only whenrequireUniqueNonceis on. - Cost is
ceil(qty × askPerN / 1e18). Proceeds arefloor(qty × bidPerN / 1e18).
Quote endpoint (the market registry gives quoteApiUrl per market):
GET <quoteApiUrl>/flex2-quote?pool=<pool>&vault=<band>&side=callThe response carries askPerN, bidPerN, validUntil, nonce, signature, the spot and IV used, greeks, and the model inputs needed to reproduce the price.
Worked example
A band with strike 84,000 and cap 84,600, so W = 600 USDG per BTC. Mid 118.50, spread 150 bps:
| Up | Down | |
|---|---|---|
| Ask | 119.39 | 600 − 117.61 = 482.39 |
| Bid | 117.61 | 600 − 119.39 = 480.61 |
| Multiple at ask | 600 ÷ 119.39 = 5.03× | 600 ÷ 482.39 = 1.24× |
A trader buys 0.1 Up. They pay 11.94 USDG. The pool mints 0.1 of the pair, locking 60.00 USDG, and keeps 0.1 P. Free USDG falls by 48.06 and committed rises by 60.00.
| BTC at settlement | Up pays the trader | P pays the pool | Pool P&L |
|---|---|---|---|
| 83,900 | 0 | 60.00 | +11.94 |
| 84,450 | 45.00 | 15.00 | −33.06 |
| 84,800 | 60.00 | 0 | −48.06 |
A second trader then buys 0.1 Down. They pay 48.24. The pool hands over its 0.1 P without locking anything new. It now holds no position in the band and has taken in 11.94 + 48.24 = 60.18 against 60.00 locked. Whatever the settlement price, the vault pays the two traders 60.00 in total and the pool keeps 0.18, the spread.
Settlement
- Trading stops at maturity.
- After
maturity + settleDelay(60 s on BTC and ETH), anyone can callcloseEpoch()on the pool. Split calls it every 5 minutes until it succeeds. - Each band reads Chainlink
latestRoundData()once and recordssettlePriceandintrinsicPerUnit. The read requires a positive answer, a complete round, and an update within the pool'smaxStaleness. If a check fails the call reverts and is retried; no funds move. closeEpoch()claims the pool's own legs into free USDG and returns the pool to Idle. The next round opens withstartEpoch.- Holders claim with
claimNAndWithdraw(amount, to)orclaimPAndWithdraw(amount, to), which settle the band first if needed. No exercise, no deadline.
Pool accounting
| Flow | Effect on the pool |
|---|---|
| Premium on a buy | Free USDG + premium |
| Mint on a buy | Free USDG − W × qty, committed + W × qty |
| Sell back at bid | Free USDG − proceeds, collateral released |
| Settlement | The pool's legs pay out by the same formula as anyone's |
closeEpoch() | All pool legs claimed, committed reset to 0 |
Shares are tracked in the pool (shares(address), totalShares):
deposit(amount, NavQuote, sig)mintsamount × 1e18 / navPerShareshares.redeem(shares, NavQuote, sig)paysshares × navPerShare / 1e18USDG, up to free USDG.NavQuote { uint256 navPerShare, uint256 validUntil, uint256 nonce }is EIP-712 signed by the pricer, same domain as quotes. The first deposit is at 1.00.
Between rounds every position is settled, so NAV per share is free USDG ÷ shares. Example: 10,000 USDG and 10,000 shares at 1.00. Over one round the pool collects 300 USDG of premium and pays 220 USDG net to winning traders. After closeEpoch() free USDG is 10,080 and NAV is 1.008.
Integrating as a maker
Everything below is on chain and permissionless, except quote signing (the pool's pricer()) and opening rounds (the pool's owner()).
| Surface | Function or endpoint |
|---|---|
| Discover markets | GET https://split.markets/api/markets: symbol, pool address (flex2), quoteApiUrl |
| Read a round | Pool: phase(), epoch(), epochMaturity(), callSeriesCount(epoch), callVaultAt(epoch, i), freeUsdg(), usdgCommitted(), allocHeadroom() |
| Read a band | Vault: strike(), cap(), capPayout(), maturity(), N(), P() |
| Down prices | Pool: downPrices(vault, quote) returns the Down ask and bid |
| Quote format | Quote struct and domain above. The pool accepts quotes signed by pricer(), which the owner sets with setPricer. |
| Trade against the pool | buyCall, buyDown, sellCall, sellDown(seriesId, qty, limit, quote, sig) |
| Mint inventory directly | Vault mint(amount): lock W per unit, receive N and P. redeemPair(amount) reverses it before maturity. |
| Fund a pool | deposit / redeem at a signed NAV |
| Settle and claim | Pool closeEpoch(); vault settle(), claimNAndWithdraw, claimPAndWithdraw |
| Index | Pool: EpochStarted, BoughtCall, BoughtDown, SoldCall, SoldDown, EpochClosed, Deposit, Redeem. Vault: Mint, RedeemPair, Settled, ClaimN, ClaimP. |
RFQ on Paradex and Derive
Split also routes the same views to Paradex and Derive spreads, as the taker:
- Derive:
private/send_rfq(legs, no price),private/poll_quotes, thenprivate/execute_quotesigned by the user. - Paradex:
POST /v1/rfqs, quotes over the WebSocketrfqchannel, thenPOST /v1/rfqs/{id}/execute.
For each trade the app compares Split's band with matching venue spreads at the trader's stake and routes to the best payout. Maker quotes are shown as firm; marks are shown as estimates.
To discuss maker integration, contact us on X: @splitmarkets.
