Security
TAPE2's only input from the outside world is the pool's observation ring. This page lists the ways someone might try to bend that input, and what the design does about each.
The tape cannot be rewritten
A Uniswap v3 pool writes one observation per block in which it is touched, at the end of the swap, mint or burn that touched it. Each entry stores the block time and the cumulative tick up to that moment. Entries are never edited; the ring only moves forward and eventually overwrites the oldest entry. Nobody, including the pool's own creator, can insert a false past.
Moving the price for one block
An attacker can push the tick a long way with one large swap, then swap back in the next block. Three things limit what that buys.
- The pricing price is the higher of the 30-minute time-weighted average and spot, so pushing the price down for a block changes nothing, and pushing it up for a block moves a 30-minute average by one block's share of 30 minutes.
- Realized volatility is measured on 10-minute to 2-hour average ticks over 24 hours to 21 days, and the contract prices with the highest window plus 20 points. A spike that lasts one block barely moves those averages, and if it did, it would make calls dearer, not cheaper.
- The spike costs the attacker the pool's fee twice plus the price impact on both legs, paid to the pool's liquidity providers.
Pushing volatility up to make calls dear, or down to make them cheap
Making the tape look calm would require trading the pool quietly for days across all three long windows, which is simply the pool being calm. Making it look wild costs fees and slippage and only raises the price of calls. The contract also refuses purchases while the 6-hour realized vol is above 3 times the long vol, so a sudden storm pauses the market rather than mispricing it; cached windows older than 12 hours block purchases until anyone refreshes them.
Thin or new pools
A pool with a small ring, or a ring that only covers a few hours, cannot support 7-day pricing. The contract requires the full 7-day window to be available (the observe() call reverts with OLD if a requested time predates the ring) and the protocol can grow a pool's ring with increaseObservationCardinalityNext, which costs a few tens of dollars in gas on Robinhood Chain. Uniswap v4 pools have no ring by default and are out of scope.
Open interest
Coins under live options per market may not exceed 10% of the pool's coin balance. A market that is small next to its pool cannot be used to profit from moving the pool. A strike must also sit within 100x of the TWAP when written, and an expiry between 1 hour and 7 days.
Settlement
Exercise and expiry read no price. The holder pays WETH and receives the coins, or the coins return to the writer. A manipulated price at expiry changes nothing in the contract; it only changes whether the holder chooses to exercise.
Keys and upgrades
The contract has no owner functions; every parameter is a constant or set once at deployment (the TAPE2 token, its pool and the treasury address). There is no pause for existing tickets, no withdrawal of locked coins, and no change to strike, expiry, fee or burn share. The burn crank can only swap the burn pot's WETH for TAPE2 and burn it, at no worse than 3% under the TWAP.
What this does not cover
- Smart contract bugs. The engine is tested against a fork of Robinhood Chain with the real pools' observation rings copied in (
engine/test/Tape2.t.sol,engine/test/Math.t.sol). No audit is claimed here. - Pool bugs. TAPE2 trusts Uniswap v3's ring to be what Uniswap v3's code says it is.
- Chain halts. If the chain stops, expiry times still pass; tickets can be exercised or expired when it resumes.
- The RPC the website uses. The site is a viewer; the contract does not depend on it.