Skip to main content
Skip to main content

xStocks Market Making

This guide is for market makers integrating with Silhouette's RFQ surface to quote and settle xStocks: Backed's tokenized US-equity ERC-20 series deployed on HyperEVM, such as xTSLA, xAAPL, and xSPY. Each xStock trades against USDC as an RFQ instrument (for example XTSLA-USDC-SPOT): takers request a price, makers compete to fill it, and the winning quote settles on-chain.

By the end of the four pages you will be able to authenticate to the API, receive open RFQs on the xStock instruments you are approved for, price and submit quotes, deploy the settlement contract those quotes settle through, and take a fill from selection to settled, in either of the two settlement modes this venue supports.

The defining property of this venue, stated up front: you deploy your own settlement wrapper contract. On Silhouette's other settlement adapters a maker approves a Silhouette-deployed contract; here the wrapper is your code, deployed by you on HyperEVM, and it is the only on-chain code you contribute. Silhouette reviews the wrapper's source and pins its deployed code hash before it may settle, and every settlement authorization Silhouette signs names your wrapper, and only your wrapper, as the contract allowed to act on it.

If you have not met the RFQ surface before, read the RFQ overview for the lifecycle and the RFQ API overview for authentication and transports first. This guide assumes both.

Two settlement modes

Both modes settle atomically: the taker's USDC and your xStock change hands in one transaction, or the whole transaction reverts and nothing moves. They differ in where the xStock comes from.

Inventory mode (XSTOCKS_INVENTORY): you hold xStock inventory inside your wrapper and deliver from that balance on each fill. At fill time the wrapper pulls the taker's USDC from the omnibus through Permit2 and transfers the xStock back to the omnibus from its own holdings, in the same transaction. This is the simplest mode to run: quoting needs no per-quote third-party interaction, but you fund the wrapper and top it up on your own schedule, and the wrapper's own ERC-20 balance caps the size of any single fill.

xChange mode (XSTOCKS_XCHANGE): inventory-less atomic settlement. Your wrapper composes the USDC pull with a call into Backed's AtomicSwapUpgradeable, which sources the xStock against the underlying equity exposure you hold off-chain as a Backed Authorized Participant. You hold no on-chain inventory; for each RFQ you quote, you request a Backed-signed SwapMessage from Backed and attach it to the quote. What you manage is cash, your AP allowance, and the Backed API.

The swap does not have to be struck at the price you quoted. Your spread is whatever you do not pass on to Backed, or whatever you take from Backed above what you quoted, and it stays in your wrapper for you to withdraw. Silhouette bounds both legs so that difference never comes out of the taker: the omnibus pays the taker amount you quoted and receives the maker amount you quoted, whichever leg your spread sits on. The settlement page has the exact bounds.

Inventory (XSTOCKS_INVENTORY)xChange (XSTOCKS_XCHANGE)
On-chain inventoryHeld in your wrapper; its balance caps single-fill sizeNone
Backed relationshipNone requiredAuthorized Participant; your wrapper allowlisted with Backed
Per-quote workPrice and submitRequest a Backed-signed SwapMessage from Backed, attach it to the quote
You manageWrapper funding, top-ups, withdrawing proceedsCash, AP allowance, the Backed API
Wrapper interfaceIInventoryWrapperIXstocksXchangeWrapper

A wrapper is bound to one mode. A maker running both modes deploys two wrappers under one maker identity, and may then quote a single RFQ through both modes at once, one quote per adapter.

Parties and trust

Five parties touch an xStocks settlement. What each does, and what you are relying on:

PartyWhat it doesWhat is assumed of it
You (the maker)Prices RFQs and submits quotes over the authenticated API; submits the wrapper's fill() transaction and pays its gas.Nothing, at the protocol level. Your on-chain authority is mediated entirely by your wrapper's bytecode, which Silhouette reviews at onboarding.
Your wrapperThe contract you deploy. Consumes the Silhouette-signed Permit2 authorization and produces the maker leg in the same transaction, then emits the Filled event Silhouette observes.Nothing, at the protocol level. The authorization binds your wrapper as its only permitted spender and binds the maker leg into the witness; the fill succeeds or the whole transaction reverts. Silhouette pins the reviewed code hash before the wrapper may settle.
OmnibusHolds Silhouette users' USDC and xStock balances on HyperEVM. It is the counterparty on every fill: your wrapper pulls the taker token from it and delivers the xStock to it. Signing one Permit2 authorization per selected quote is Silhouette's entire on-chain action on this adapter.Silhouette signs only after selecting a winning quote and validating it; the signature is narrowly scoped to that quote (see below).
Permit2The canonical Uniswap deployment at 0x000000000022D473030F116dDEE9F6B43aC78BA3, identical on every EVM chain. Executes the USDC pull when, and only when, the call matches the signed authorization.Audited and immutable. Its nonce bitmap provides replay protection, and its spender check binds each authorization to the one contract named in it.
Backed's AtomicSwapUpgradeable (xChange only)Backed-operated HyperEVM contract that executes the two transfer legs of a Backed-signed SwapMessage: it pulls the USDC from your wrapper and transfers the xStock from Backed's transfer account.It is upgradeable, so Silhouette verifies its implementation before signing, and both your wrapper and Silhouette independently verify the delivered amounts; a short delivery reverts rather than settling.

Bounded authorization

The property that makes a maker-deployed contract safe for both sides is that the authorization it consumes is narrow. For each quote it selects, Silhouette signs exactly one Permit2 PermitWitnessTransferFrom. That signature names:

  • the taker token and the exact quoted amount: nothing else can be pulled;
  • your wrapper as the only permitted spender: no other contract can consume it;
  • the quote id as the nonce: it settles that quote once, and never again;
  • a deadline no later than the RFQ's settlement deadline: after it, the authorization is dead;
  • your maker leg, bound into the witness: the xStock and amount you quoted (inventory), or the exact Backed SwapMessage Silhouette validated together with the amount the omnibus is owed out of it (xChange).

The signature cannot be reused to pull a different token or amount, redirected to a different spender, or replayed to settle a different quote. Because the witness binds the maker leg, your wrapper cannot deliver anything other than what was quoted while still consuming the pull. Permit2 burns the nonce only on a successful fill, so a reverted transaction leaves the authorization intact until its deadline. The exact binding of every field is on the settlement page.

Inventory mode, end to end

xChange mode, end to end

In both modes the quote is submitted over REST and its outcome arrives as a quoteStatus push on the WebSocket; the SELECTED push carries the Silhouette-signed Permit2 payload your wrapper consumes. Everything between fill(...) and the Filled event is one transaction.

How this guide is organized

  • Quoting: connect, subscribe, price RFQs, submit quotes, track outcomes.
  • Settlement: what Silhouette signs, and the wrapper contract you deploy.

For the RFQ surface itself, see the RFQ overview and the RFQ API.