Trustless parametric prediction markets for the World Cup, settled by real cryptographic proof — not a promise.
Built for the TxODDS × Superteam Earn World Cup Hackathon (Prediction Markets & Settlement track).
Live devnet program: 8aTe46s6bVun696q4aXucLwiXmPXV7iRkg2oDB4JjzUK
Most prediction markets ask you to trust that whoever resolves the market did it honestly. VARdict doesn't ask for that trust — settle_market performs a genuine Cross-Program Invocation into TxLINE's own validate_stat oracle instruction, which cryptographically verifies a Merkle proof against an on-chain root before returning the outcome. Our program cannot lie about the result; it can only report what TxOracle's own verified math says.
This isn't theoretical. Two real World Cup semifinals have been fully settled on devnet, verifiable right now on Solana Explorer:
| Fixture | Market | Result |
|---|---|---|
| France vs Spain (semifinal, Jul 14) | Total Corners > 6 | ✅ Settled YES |
| England vs Argentina (semifinal, Jul 15) | Total Corners > 0 | ✅ Settled YES |
- Subscribe — a real on-chain transaction into TxOracle's own program, registering the wallet for World Cup data access (free tier for this event)
- Create a market — locks in a fixture, a stat key, a threshold/comparison (or a two-stat combo predicate), and a close time that defaults to the fixture's real kickoff and cannot be pushed later
- Take a position — real devnet USDC, escrowed by a PDA-owned vault, split proportionally between YES/NO
- Settle — anyone can call this, permissionlessly. It fetches the real Merkle proof from TxLINE's REST API, transforms it into the exact shape TxOracle's
validate_statexpects, and CPIs in with a 1.4M compute budget - Claim — pari-mutuel payout: stake back plus a proportional share of the losing pool. Provably solvent — total payouts can never exceed the vault, by construction (see
docs/ARCHITECTURE.md)
Beyond simple win/lose predicates, VARdict supports two-stat compound conditions — e.g. "Team A's corners − Team B's yellow cards > 3" — evaluated atomically by the same CPI.
A Groq-powered analyst (two-tier routing: a cheap classifier gates an expensive reasoning model) that can propose markets based on real fixture context. It never executes anything — only proposes, for a human to review and sign. Critically: it's instructed to explicitly decline any question it wasn't given verified data for, rather than invent statistics — a real bug we found and fixed during testing (see docs/SUBMISSION.md).
Several genuinely non-obvious things had to be discovered empirically, not from documentation, because they weren't documented:
- TxLINE timestamps are milliseconds throughout, not seconds — including inside the on-chain CPI arguments
- Proof byte fields (hashes, roots) arrive as plain JSON integer arrays, not base64, despite the OpenAPI spec's
format: binaryannotation - Anchor's JS client expects camelCase object keys for CPI arguments, silently producing wrong on-chain data if you pass snake_case
- The
daily_scores_merkle_rootsPDA is keyed by the standard Unix epoch day (ts_ms / 86,400,000), confirmed by directly reading real account data on-chain after several other plausible hypotheses were tested and disproven
Full write-up in docs/SUBMISSION.md, including our experience and friction points with the TxLINE API.
- On-chain: Anchor/Rust, Solana devnet
- Frontend: Next.js, real-time via TxLINE's SSE stream
- AI: Groq (
gpt-oss-120b/gpt-oss-20b)
See docs/SETUP.md.
- TxLINE's fixture snapshot endpoint is forward-looking only; already-finished fixtures require a direct-lookup fallback (implemented) rather than appearing in the default list
- No refund path exists for a market that never receives an opposing position — documented, not yet built