Skip to main content
RobinTwapOracle holds a time-weighted average YES price for every market. The vault reads it to split organic yield between the YES and NO sides, and refuses a deposit or withdrawal when the market’s TWAP is stale. Before you call batchDeposit, the push-deposit safeBatchTransferFrom, or batchWithdraw, fetch a signed update from Robin and prepend submitTwap to the same batch when one is needed.

Why TWAP

A market’s outcome tokens (YES and NO) earn yield as one pooled USDC position, but each side accrues at a different rate. The oracle’s time-weighted YES price is the split point. It determines how much of the pool’s yield belongs to YES holders versus NO holders. The vault enforces freshness per market. If the stored TWAP is stale, a deposit or withdrawal for that market reverts until a fresh value is submitted. You never compute this price yourself: Robin’s backend computes it from Polymarket trade data and returns it signed.
The TWAP payload is signed by a Robin operator key. This signer is migrating to an Oasis ROFL TEE, but the HTTP request and response shapes documented here stay the same — no integration changes are required.

Fetch a signed update

Request the update from the Integration API at POST /api/v1/twap — open CORS, no auth, rate-limited per IP like the rest of /api/v1. Pass the conditionIds (up to 25, unique) for every market in your upcoming batch.
The response is one of two shapes. Mode A — already submitted. The oracle was refreshed on-chain by someone else. There is nothing for you to do: skip submitTwap entirely.
Mode B — you submit it. You receive TwapData-shaped market entries plus a signature. Prepend submitTwap({ markets, signature }) to your batch (see Submit it).
All amounts and prices are 6-decimal integer strings. twapPriceYes is scaled by PRICE_SCALE (1e6), so 1000000 is 100%.

Submit it

When you get Mode B, prepend a single RobinTwapOracle.submitTwap call to your deposit or withdrawal batch — the oracle refresh and the vault action then land atomically in the same Safe or relayer transaction.

Short-circuit

You can skip submitTwap even in Mode B when no market actually needs an update.
If every returned market has required: false and marketEndedAt: "0", the on-chain TWAP is already fresh and no market has finalised — submitting is a pure no-op. Drop the submitTwap call and send your deposit or withdrawal batch on its own.
The reference fetchTwap helper folds all of this into one call: it returns null for Mode A and for the short-circuit case, and otherwise returns { markets, signature } with every field already coerced to bigint. Your batch builder then conditionally prepends submitTwap only when the helper returns non-null. See fetchTwap in src/shared.ts of the robin-markets-integration example repo, used by both deposit flows and the withdrawal flow.

Next steps

Deposits

Build the pull or push deposit batch that the TWAP update goes in front of.

Withdrawals

Burn shares and claim organic yield, with the same fresh-TWAP requirement.