A growing family of governance mechanisms does not count votes. Futarchy settles a proposal by comparing two conditional market prices; Caper's optimistic window settles one by comparing a token's average price during a window against its average before it. In both, the thing that decides is a price reading, and a price reading is a piece of infrastructure with its own failure modes, its own cost of attack, and its own quiet assumptions about how much history it can see.
This page is the general case those mechanisms rest on. The argument in one line: a governance system that reads a price inherits its oracle's manipulation cost as its own quorum. It does not matter what threshold the contract declares. If the price behind the threshold can be moved for $40,000, the decision costs $40,000 – and if the oracle can only see thirty minutes of history, the attacker only has to hold the price for thirty minutes.
Spot, cumulative, time-weighted
A spot read is the price right now, as a single contract call. It is the cheapest thing to read and the cheapest thing to falsify: a trader borrows, buys into the pool, takes the reading, sells back, and repays, all inside one transaction. The whole round trip costs slippage and fees, and it is over before any other participant can respond. Any governance decision settled on a spot read is settled by whoever is willing to pay that round trip.
A time-weighted average price replaces the point reading with an integral. The system records the price at intervals, multiplies each observed price by how long it held, sums, and divides by the elapsed time. The cost of moving the result is therefore displacement multiplied by duration: to lift a seven-day average by 10% an attacker must lift the spot price far higher than 10% and keep it there against every arbitrageur who wants to sell into it, for a meaningful share of seven days. There is no atomic version of that. The single-transaction attack that beats a spot read does not exist against an average, because the average is defined over time an attacker cannot compress.
That is the entire security argument, and it is worth being precise that it is an economic argument rather than a cryptographic one. Uniswap Labs' own 2022 analysis of v3 TWAP manipulation (Adams, Wan and Zinsmeister, 27 October 2022) puts numbers on it and reaches a two-sided conclusion: two-block manipulations of a deep pool are prohibitively expensive – a single $1m wide-range mint on USDC/WETH raises the two-block attack cost by hundreds of billions – while longer manipulations became more feasible under proof of stake, where a validator with consecutive slots can hold a price without competing with arbitrage in between. The defence scales with the liquidity behind the price, not with the length of the window alone.
Uniswap v2: the pool keeps one number
The pattern nearly every on-chain TWAP descends from is UniswapV2Pair.sol. The pool holds two running accumulators, price0CumulativeLast and price1CumulativeLast, and its _update function advances them by price × timeElapsed. Two properties of that function do the security work, and both are visible in four lines of source:
- It accumulates at most once per block. The source comment reads "update reserves and, on the first call per block, price accumulators", and the guard is
timeElapsed > 0. A hundred trades in one block advance the accumulator once. - It accumulates the pre-trade reserves.
_updateis handed_reserve0and_reserve1as they stood before the swap being settled. The price a block contributes to the accumulator is therefore the price the previous block left behind. An attacker who spikes the price must survive to the next block for the spike to be recorded at all.
What v2 does not do is keep history. The pool stores only the most recent accumulator value, so computing an average is the caller's job: read the accumulator at the start of your period, store it yourself, read it again at the end, subtract, divide. The v3 whitepaper is blunt about the consequences – every consumer "will have to provide their own methodology for checkpointing previous values of the accumulator", and "there is no way to guarantee that every block in which the pool is touched will be reflected in the accumulator". A governance contract that reads a v2 pool and forgets to checkpoint does not have a weak oracle. It has no oracle.
Uniswap v3: the pool keeps a ring, and someone has to pay for it
Uniswap v3 moved the checkpointing into the pool. Each pool holds an Observation[65535] array and writes a checkpoint the first time it is touched in any block, "cycling through an array where the oldest checkpoint is eventually overwritten by a new one, similar to a circular buffer". Consumers stop keeping their own records and simply ask the pool for the accumulator value at a past timestamp.
The detail that matters for governance is in the next sentence of the same paragraph, and it is a funding problem rather than a cryptographic one. The array starts with room for exactly one checkpoint. The Oracle library's own header says so – "Every pool is initialized with an oracle array length of 1. Anyone can pay the SSTOREs to increase the maximum length of the oracle array" – and the growth path is a public call, increaseObservationCardinalityNext, that any address may make and that somebody must pay for. A pool nobody has paid to grow has a lookback of one block, however long the window a consumer asks for.
And v3 is explicit about what happens when the ask exceeds the history. getSurroundingObservations ends with require(lte(time, beforeOrAt.blockTimestamp, target), 'OLD'): a query reaching further back than the oldest retained observation reverts. That is a design choice, and a defensible one – a consumer asking for thirty minutes from a pool holding four gets an error, not a four-minute average dressed up as a thirty-minute one.
Observation retention: the window a system asks for is not the window it gets
Every implementation above shares one bound, and it is the bound most descriptions of TWAP governance omit entirely. A time-weighted average is only as long as the price history still stored behind it. Storage is finite, so every design either keeps a fixed number of observations and evicts the oldest, or keeps none and makes the caller do it. The nominal window – "thirty minutes", "seven days" – is an upper bound on what the average actually covers, and a busy market is precisely the case where it binds, because a busier market fills the buffer faster.
That is the same failure shape in three systems, and each answers it differently:
| System | What it retains | On breach |
| Uniswap v2 | One accumulator value, no history | Nothing to breach – the consumer's own checkpoints are the history, and a missed checkpoint is a missed period |
| Uniswap v3 | A circular buffer, cardinality 1 until someone pays to grow it (max 65,535) | Reverts with 'OLD' |
| Caper | A running price-time accumulator, checkpointed once per traded minute into a ring of CHECKPOINT_CAP entries – eight days of traded minutes, since a minute with no trade writes nothing | Extends the window forward to the oldest retained checkpoint and returns that longer average; the baseline's own length is pinned under the ring at compile time, so only a very late resolve can reach the bound |
Of the three, Caper's is the one that has to be stated as a governance parameter, because it is one. Two things follow from checkpointing on a minute grid. The trailing baseline a trigger reads is never shorter than it claims, because its length is pinned under the ring's retention when the logic is compiled. And a resolve that lands inside the retention reads the price-time integral at its window end exactly, however busy the market was in between; one that lands later extends the window forward to the oldest checkpoint still held and returns that longer average rather than an error, deterministically. Reverting, as v3 does, is louder; extending trades the loudness for the guarantee that a resolve never gets stuck, and puts the bound in a named constant rather than in a return value that looks like the one asked for.
The inversion is worth stating plainly, because it runs against the intuition that deeper markets are safer. Under a fixed observation count, the more actively a market trades, the shorter its effective lookback becomes. A quiet asset's observations may span months; a heavily traded one's may span an afternoon. Checkpointing once per traded minute rather than once per trade, as Caper does, blunts the effect – a burst inside one minute costs one slot – but the retention is still counted in traded minutes, so the busiest market is still the one with the shortest history. So the market with the most liquidity behind its price can be the market with the least history behind its average, and the two effects – more expensive to displace, cheaper to outlast – pull in opposite directions.
The oracle's manipulation cost is the real quorum
Ballot-based governance states its threshold in its own terms: a share of supply, a share of turnout, a delegate count. Price-settled governance cannot. Its threshold is denominated in whatever it costs to move the price the mechanism reads, for as long as the mechanism reads it – a quantity set by the market's depth, by who else is trading, and by the retention bound above, none of which the governance contract controls or can even observe.
Three practical consequences follow, and they are what makes this a governance topic rather than a market-infrastructure one:
- The threshold moves without a vote. Quorum and threshold design treats the bar as something an organisation sets. Here it is something the order book sets, and it falls every time liquidity leaves. A thin market is a low quorum, and nothing in the contract announces the change.
- The venue is part of the mechanism. Which pool, which fee tier, which chain – each is a different manipulation cost for the same nominal rule. The v3 whitepaper notes that consumers can strengthen their oracles by choosing which fee-tier pool to read from; a governance system that leaves that choice undocumented has left its own security parameter undocumented.
- Attacks migrate from the ballot to the book. Governance attacks on a token-weighted DAO buy or borrow voting power. Against a price-settled system there is nothing to borrow: the attack is a trade, it is legal, it looks like ordinary market activity, and it leaves no proposal-level evidence at all.
The corollary is the honest recommendation. A price-settled mechanism is strongest on a deep, well-observed market and weakest on a thin new one – which is the reverse of where new organisations actually start. Optimistic governance with a human veto-holder degrades gracefully when the market is thin; a market veto does not.
How Caper approaches this
Caper settles the second phase of every proposal on a price reading, so the whole of the above is load-bearing rather than academic. A ballot passes a proposal legislatively; triggering it locks the caper's trailing time-weighted average as a baseline and opens the market window; and the proposal executes if and only if the average over that window is at or above the baseline. Holding is consent, and the only way to defeat something that already won its ballot is to sell hard enough, for long enough, to hold the window's average below where the token had been trading.
Two of this page's points apply directly, and both are documented rather than glossed. The averaging is an exact integral, not a sample: the state tier adds price multiplied by time at every trade and checkpoints the running total once per traded minute, and the resolve reads that integral at the recorded window end rather than at the moment of the crank, so a late crank reads the same number a prompt one does. An atomic buy-resolve-sell round trip buys no verdict; a displacement has to be held for a real share of the window. And the retention bound is real and is named: the checkpoint ring holds CHECKPOINT_CAP traded minutes, the baseline's length is pinned under it when the logic is compiled, and a resolve cranked past it extends the window to the oldest checkpoint still held – the behaviour in the table above. Execution sets that out against the contract source.
What Caper does not claim is that the market veto is cheap to use or that it makes the price unmanipulable. It makes the manipulation cost the threshold, deliberately, and then says so – which is the one thing this page argues every price-settled system owes its readers.
Sources
- Uniswap v2-core –
UniswapV2Pair.sol. The_updateaccumulator: once per block, on pre-trade reserves. - Uniswap v2 whitepaper. The original on-chain TWAP construction.
- Uniswap v3 whitepaper, §5.1 “Oracle Observations”. The circular buffer, the cardinality-1 start, and the one-time gas cost of growing it.
- Uniswap v3-core –
Oracle.sol. TheObservation[65535]array, the library header on paying for slots, and the'OLD'revert. - Uniswap v3-core –
UniswapV3Pool.sol.increaseObservationCardinalityNext, the permissionless growth call. - Adams, Wan & Zinsmeister, “Uniswap v3 TWAP Oracles in Proof of Stake” (Uniswap Labs, 27 October 2022). Manipulation cost against wide-range liquidity, and why proof of stake changes the long-window case.
A note on citations: docs.uniswap.org is not cited here because, as of 5 September 2026, every path on that host – including invented ones – redirects to app.uniswap.org/swap and returns the swap application with an HTTP 200. A link to it would resolve, and would reach nothing it claimed to.