Skip to main content

Settlement and Onboarding

Status: Specification (LP Protocol v1, draft 2026-09-23).

On-ledger model​

RFQ swaps settle with the Canton Token Standard allocation workflow (CIP-0056), the same primitives Rocky's spot settler uses for its allocate-and-execute path. Each party locks its own leg in an Allocation naming Rocky's operator party as executor. Executing a registry allocation needs the authority of executor, sender and receiver, so the single settlement transaction is wrapped in the two parties' MemberAuth contracts (rocky-clob-v8 ≥ 0.7.0, Auth_OpenAllocations → Auth_RunAllocationsWith): both the trader's wallet and the LP grant MemberAuth once, at enrollment / onboarding, exactly as for order-book settlement. There is no Rocky-specific escrow contract.

ChoiceSignerWhenEffect
AllocationFactory_AllocateTrader (wallet)After POST /v1/swaps/rfqLocks the input amount (receiver: LP party) and the taker fee (receiver: Rocky fee collector)
AllocationFactory_AllocateLPIn accept-and-allocateLocks the output amount (receiver: trader party) and the maker fee when non-zero
MemberAuth Auth_OpenAllocations → Allocation_ExecuteTransfer × every legRocky operator, with both MemberAuthsOnce both sides are verifiedAtomic transfer of all legs in one Canton transaction
MemberAuth Auth_CancelAllocations → Allocation_CancelRocky operator, with the sender's MemberAuthOn any terminal failureReleases that member's locked allocations before settleBefore
Allocation_WithdrawSender (trader or LP)After settleBefore, if still lockedSender releases its own allocation without Rocky

Every allocation of a swap shares one SettlementInfo:

executor = Rocky operator party
settlementRef = { id: <swapId>, cid: None }
requestedAt = swap creation time
allocateBefore = requestedAt + 60 s
settleBefore = requestedAt + 120 s
meta.values = { "rocky.swapId": <swapId>, "rocky.symbol": <symbol> }

settlementRef.id = swapId is what binds the on-chain transaction to the trade you were shown, exactly as settlementRef.id = tradeId does for order-book fills. Rocky verifies each allocation on ledger before proceeding: instrument, amount, sender, receiver, executor and the full SettlementInfo must equal the frozen swap. Rocky never edits amounts to make a swap fit.

Instruments must support Token Standard allocations through their registry (Canton Coin and the CC-wrapped assets Rocky lists do). Receiver preapprovals are not required on this path.

Failure handling​

FailureDetected byTrader inputLP output
Trader never allocatesallocateBefore passesfree—
Trader allocation mismatchRocky verificationexecutor Allocation_Cancel; wallet may Allocation_Withdraw after settleBefore—
LP rejects / times outaccept-and-allocateexecutor cancels—
LP allocation mismatch or lateRocky verification / allocateBeforeexecutor cancelsexecutor cancels; LP may withdraw after settleBefore
Settlement transient errorexecutorstays locked while retrying inside settleBeforesame
Settlement terminal errorexecutorexecutor cancels; withdrawable after settleBeforesame
Rocky unavailable mid-swap—withdrawable after settleBeforewithdrawable after settleBefore

The windows are deliberately short so that a stuck swap never locks funds for more than two minutes. Because execution is one transaction, there is no state in which one side has paid and the other has not.

Verifying a swap on Canton​

  1. Take swapId and cantonUpdateId from GET /v1/lp/trades/{swapId} (LP) or GET /v1/swaps/rfq/{swapId} (trader).
  2. Open the update on a participant that hosts your party or in Canton Scan.
  3. The transaction's root is an Auth_OpenAllocations exercise on a MemberAuth (with a nested Auth_RunAllocationsWith), containing one Allocation_ExecuteTransfer per leg (two legs plus one or two fee legs) and nothing else; every exercise carries settlementRef.id equal to swapId and executor equal to Rocky's operator party.
  4. Amounts equal the legs block of the trade object.

A SUCCEEDED swap is also included in the next epoch commitment; GET /v1/chain/proof?ref_id=<swapId> returns its inclusion proof.

Onboarding​

Commercial terms, symbols, sizes and support channels are captured in an Integration Pack. The technical steps:

StepYouRocky
1. PartyProvide the Canton party id that will hold inventory and its validator/wallet typeBinds an account to the party (Institutional Onboarding §2)
2. API keyRegister an Ed25519 public key (fingerprint read back over a second channel)Registers the key on the ext-mm rate tier
2b. MemberAuthComplete MemberAuth for your party once (Institutional Onboarding §4); it authorises Rocky to execute allocations whose executor is Rocky and whose legs are between you and the trader, nothing elseVerifies the contract exists before the first RFQ is routed to you
3. ServiceProvide serviceUrl, egress IPs, TLS details (and mTLS client cert requirements, if any)Registers the LP, publishes Rocky's signing key fingerprint to you
4. SymbolsList symbols with minBaseQty / maxBaseQtyConfigures fan-out; maxBaseQty caps a single swap
5. TestingKeep your service answering while Rocky drives test swapsRegisters you in TESTING: only Rocky's test traders reach you, with small sizes, on mainnet. Runs the go-live checklist below
6. Go-liveConfirm the manual checklist itemsSwitches you to ACTIVE; public RFQs start reaching you

There is no separate test network: the assets Rocky lists exist on Canton MainNet, so go-live testing runs on mainnet in TESTING status with small sizes (typically 0.00001 CBTC per swap). Nothing reaches you from the public until Rocky switches you to ACTIVE.

A reference LP service (signature verification, quote shaping, allocation through your JSON Ledger API) is in the Rocky API Maker Bot repository: python/rocky_spot/rfq_lp.py and python/examples/rfq_lp.py.

Service levels​

Rocky measures per LP: quote answer rate and p95 latency, accept rate, mismatch rate, and settlement success. DEGRADED health (three consecutive failed probes) removes you from fan-out automatically. The other measures feed fanOutShare: an LP whose accept rate over the trailing hour falls below 80 % or whose mismatches exceed 1 % receives a smaller share of RFQs until the numbers recover. In v1 fanOutShare is adjusted by Rocky operations after review, not automatically. Thresholds are published in the Integration Pack and can only be tightened with notice.

Go-live checklist​

  • GET /health answers in under 500 ms with your production party and symbols.
  • Quotes arrive within the quote timeout at p95 across a 30-minute sandbox run.
  • Ten consecutive test swaps settle; each cantonUpdateId verified with the shape above.
  • One forced rejection returns 409 REJECTED and the trader's allocation is released.
  • One forced timeout shows LP_ACCEPT_FAILED at GET /v1/lp/trades/{swapId} and no dangling allocation on your side.
  • POST /v1/lp/pause removes you from fan-out within one second; resume restores it.
  • Your validator's traffic balance monitoring is in place (Canton traffic).

What RFQ swaps are not​

  • They are not order-book trades: no @trade print, no kline or ticker impact, no effect on the Spot leaderboard of order-book volume.
  • They are not custodial: Rocky holds neither side's assets at any point.
  • They are not netted: every swap is its own transaction, so per-swap Canton traffic applies to both sides.