How it works

A TAPE2 call has two people and one pool. The writer owns the coins and wants a premium. The buyer wants a 7-day shot at the coin for a known, capped cost. The pool's tape sets the price between them.

The ticket

FieldMeaning
PoolA Uniswap v3 pool on Robinhood Chain with an observation ring (CASHCAT/WETH and PONS/WETH at launch)
AmountHow many coins the writer locks and the holder may buy
StrikeThe price per coin the holder pays on exercise, in WETH
ExpiryA block time at most 7 days after writing
MarkupThe writer's ask above the chain's price, from 0% to 100%
PremiumWhat the buyer pays, in WETH, at purchase: the chain's price plus the markup
WriterThe address that locked the coins
HolderThe address that paid the premium (empty until bought)

Step by step

1. Write

The writer approves the contract for the amount, then calls write(coin, amount, strike, expiry, markupBps). The contract pulls the coins in and holds them. The offer is listed at the chain's price plus the markup; the price itself is computed fresh at every purchase, not frozen at write time.

Guards checked at write time: the strike must sit within 100x of the 30-minute TWAP, the expiry between 1 hour and 7 days ahead, the markup at most 100%, and the coins under live options in that market may not exceed 10% of the pool's coin balance.

2. Read the tape

The contract calls observe() on the pool with a list of secondsAgo values and receives the cumulative tick at each, straight from the pool's ring. Four windows are read: 24 hours in 10-minute steps (145 points), 7 days in hourly steps (169), 21 days in 2-hour steps (253), and the last 6 hours in 10-minute steps (37). The three long windows are cached in the contract and anyone may recompute one with refresh(coin, window); a purchase reverts if any of them is older than 12 hours. The 6-hour window is read fresh inside every quote.

3. Measure the swing

For each window the contract forms the average tick per step (each difference divided by the step), then the log returns (each tick difference times ln 1.0001). The sample standard deviation of those returns, times the square root of the number of steps in a year, is the realized volatility of that window.

The sigma used for pricing is the highest of the four windows plus 20 points of annual vol, so a quiet week does not make calls too cheap. If the 6-hour vol is above 3 times the highest long window, the market is in a storm and purchases revert until it settles.

4. Price

With price S the higher of the 30-minute TWAP and spot, strike K, time T to expiry and volatility sigma, the premium is the Black-Scholes call with zero rate:

d1 = (ln(S / K) + sigma^2 T / 2) / (sigma sqrt(T))
d2 = d1 - sigma sqrt(T)
C  = S N(d1) - K N(d2)

On the chain this runs in 18-decimal fixed point (src/lib/Pricing.sol), tested against a floating-point reference at the same block. The number the site shows comes from the same rule in floating point.

5. Buy

The buyer calls buy(offerId, amount, maxPremium) and the contract pulls the premium in WETH: the chain's quote at that moment, times the amount, plus the writer's markup. It keeps 1% as the protocol fee (half into the burn pot, half to the treasury), forwards the rest to the writer at once, and records the buyer as the holder. The premium is the writer's whether or not the ticket is exercised. A buyer can buy part of an offer.

6. Exercise or expire

Before expiry the holder may call exercise(callId) and pay the strike times the amount in WETH. The contract sends the locked coins to the holder and the strike payment to the writer. After expiry anyone may call expire(callId), which returns the coins to the writer; the ticket is finished. An unsold offer, or the unsold part of one, can be taken back with cancel(offerId, amount) at any time.

Settlement never reads a price. The holder decides whether the coins are worth more than the strike, and acts or does not.

Why there is no oracle

Three places usually need a price feed, and TAPE2 needs none of them.

Who does what

ActorDoesGets
WriterLocks coins, names strike and expiryThe premium at once, and either the strike (if exercised) or the coins back
BuyerPays the premiumUp to 7 days of the right to buy at the strike
AnyoneRefreshes a vol window, calls expire after expiry, calls the burn crankNothing but the chain doing its job
The poolKeeps the tapeNothing; it was keeping it anyway

The contract is engine/src/Tape2.sol; its constants (TWAP_WINDOW, VOL_MAX_AGE, VOL_BUFFER, SPIKE_MULTIPLE, OI_CAP_BPS, MIN_EXPIRY, MAX_EXPIRY, STRIKE_BAND, MAX_MARKUP_BPS, FEE_BPS, BURN_SHARE_BPS, CRANK_SLIPPAGE_BPS) are public and readable by anyone.

OverviewPricing recipe