Everything, in the open.
One contract, Robinhood’s price feeds and USDG. Here is exactly what each does.
The rules
A pool is three things: a price feed, a lock instant and a close instant. Until the lock anyone may put USDG on UP (the feed’s price at the close will be above its price at the lock) or DOWN (below). At least 1 USDG; as many calls as you like, on either side.
- UP or DOWN wins: every winner collects
stake × whole pool ÷ winning side, rounded down to the unit (a millionth of a dollar). - Same price at both ends: everyone gets their stake back.
- Nobody on one side: everyone gets their stake back, without the feed being read at all.
- Nobody settles within seven days of the close: anyone can refund the pool.
The contract accepts any window from one hour to 90 days, locking up to 90 days ahead. The board offers two, so that everyone calling a stock lands in the same pool: the week (Friday 20:00 UTC to the next Friday 20:00) and the next trading day (one weekday’s 20:00 UTC to the next weekday’s).
The price feeds
Robinhood runs a Chainlink-style feed for each tokenized stock on Robinhood Chain. Vane lists the 25 stocks whose feed answers at 8 decimals and records its updates in time order (checked at block 80,163,058). They publish when the price moves by about half a percent: the median move between two updates is 54 basis points.
SGOV, a Treasury fund, is left out: its feed moves about 1 basis point per update, nearly always upward, so “up” is not a call anyone could lose.
Settling: proving the price at a second
Every feed update is a round with an id, an answer and updatedAt — the time of the block it landed in (measured: on these feeds updatedAt equals the block timestamp of the update). The price at instant t is the answer of the last round that landed at or before t.
Whoever settles names that round for the lock and for the close. The contract (priceAt) checks it: the round landed at or before t, and the round after it landed after t or does not exist yet. When a feed moves to a new aggregator (a new “phase”), the last round of the old phase stays in force until the first round of the new one — the contract checks that too. The app finds the rounds by bisecting the feed’s history; you never type one.
The contract
Vane.sol, Solidity 0.8.26, 5.8 KB of runtime code. It is deployed through Arachnid’s deterministic deployer, so its address is fixed by its code before anyone deploys it: 0x7632cCF9704B093362629592c4Be49503dff02ce. The first person to make a call sends that deployment; nobody holds a key to it afterwards.
predict(feed, lock, close, up, amount)— call a side before the lock. The first call opens the pool and checks the feed answers with a positive price.settle(feed, lock, close, lockRound, closeRound)— anyone, after the close.claim(key, who)— anyone; payswho.abandon(feed, lock, close)— anyone, seven days after an unsettled close: everyone refunded.permitUsdgandmulticall— so a first call is one transaction (a USDG permit and the call), and collecting is one transaction (settle every pool, then claim each).
No owner, no fee, no upgrade, no pause, no other token. Read the source: Vane.sol (the exact file this site compiles), and its address on the explorer.
What was tested
The last run (01 Oct 2026): 16/16 properties and 9,738 checks. Each property installs this exact build at its published address and runs it with eth_simulateV1 against live Robinhood Chain state — the real USDG, the real feeds, the real deployer — from test wallets with real keys, so permits are real signatures. Prices the tests need to move come from a mock with the behaviour measured on Robinhood’s feeds; P9 and P16 use the real feeds. Nothing is broadcast.
| # | Property | Checks |
|---|---|---|
| P1 | The page’s deploy transaction puts exactly this build at the published address | 6 |
| P2 | UP wins: winners share the whole pool pro rata, to the unit; losers get nothing | 38 |
| P3 | DOWN wins, including a caller on both sides | 27 |
| P4 | A tie (same price at lock and close) gives everyone exactly their stake back | 26 |
| P5 | A pool with nobody on one side refunds without reading the feed | 18 |
| P6 | Settling names the round in force at each instant — no earlier, no later; a non-positive price is refused | 35 |
| P7 | A feed that changes phase: the last round of the old phase is in force until the new phase’s first | 37 |
| P8 | Every guard on calling and settling refuses at its edge and allows one unit inside it | 36 |
| P9 | On Robinhood’s real feeds, priceAt agrees with the definition at(r) ≤ t < at(r+1) | 476 |
| P10 | A first call needs no approval: a real USDG permit and the call go in one transaction | 11 |
| P11 | Anyone may deliver a winner’s payout, and it always goes to the winner | 14 |
| P12 | A pool nobody settles refunds after exactly seven days, and then cannot be settled | 19 |
| P13 | Collect: one transaction settles, abandons and claims several pools for a wallet | 19 |
| P14 | Random pools against the test’s own arithmetic: every payout pinned by two inequalities | 126 |
| P15 | The page’s schedule, keys and payout arithmetic match the contract and the calendar | 8,834 |
| P16 | A whole pool on a REAL Robinhood feed, settled with rounds the page found | 16 |
Then a sabotage sweep plants 38 bugs one at a time — in the contract (an inverted outcome, a payout one unit too large, a round accepted one second late, a claim that pays whoever delivers it) and in the page’s own code (a permit for the wrong spender, a lock at the wrong hour, settle rounds swapped) — and requires the property named for each to fail: 37/38 caught, 1 declared untestable with the reason written down.
The browser run: 8/8 journeys (38 checks) clicked through the real pages in Chrome — deploy, call with a permit, a second wallet on the other side, the week passing, collect — against a private copy of the live chain (02 Oct 2026).
Risks
- Not audited. The contract is short and tested, but nobody independent has reviewed it.
- The feed is the truth. If Robinhood’s feed reports a wrong price, pools settle on the wrong price. If it stops reporting, a pool may tie or, after seven days, refund.
- Odds move until the lock. What a call pays depends on the final split, which later calls change.
- You can lose everything you put on a call. Check that prediction pools are lawful where you live.
Addresses
| Vane | 0x7632cCF9704B093362629592c4Be49503dff02ce |
| USDG (Global Dollar, Paxos) | 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168 |
| Arachnid’s deterministic deployer | 0x4e59b44847b379578588920ca78fbf26c0b4956c |
| Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 |