W02 / Case study
A real-money prediction market, built end to end
Contracts are the source of truth and everything else can be rebuilt from on-chain events, so a small team can run real money safely.
- Client
- Tennis Expert · own product
- Role
- Founder and lead engineer: contracts, worker, frontend, infrastructure
- Period
- 2025 — now
- Stack
- Solidity
- Polygon
- NestJS
- BullMQ
- Supabase
- Next.js
- Thirdweb
- sync time behind the chain on Polygon
- 42 s → 6 s
- automated tests, including contract invariants
- ~2,800
- languages, with parity checked in CI
- 12
01 / Context
Context
Tennis Expert is a real-money prediction market for professional tennis, live on Polygon. Fans back the exact set score of a match with USDC in one signature, and everyone who picked the winning score splits the pool, minus a 3% rake. The house never quotes odds, so it never takes price risk. Around that core sit tournament brackets with on-chain escrow, free matches, achievement badges, a leaderboard with prizes, private leagues and a daily quiz.
02 / Problem
Problem
Real money on a chain that can reorganise, run by a very small team. Every write had to be safe to repeat, results had to become final without paying for an oracle, and the off-chain database could never quietly become the source of truth. The first version, which minted an NFT ticket per prediction, also had to give way to a simpler pool model.
03 / Architecture
Architecture
- Browser — Next.js on Vercel
- Thirdweb — wallet, social login
- Pool contracts — USDC escrow, settlement
- Sync worker — NestJS on Fly.io
- Job queue — BullMQ on Redis
- Read cache — Supabase Postgres
Money and outcomes live on-chain. The worker replays events into a read cache that can be rebuilt at any time.
04 / Key decisions
Key decisions
05 / Hard problems
Hard problems
Reorgs versus sync speed
The worker trusts the chain's finalized head only when it is fresher than a fixed confirmation depth. Polygon sync dropped from about 42 s to 6 s, and another chain was saved from a silent 20-minute stall.
Writes that are safe to repeat
Events are stored under a unique chain, transaction and log key, jobs are de-duplicated by id, and a distributed lock keeps two worker instances from doing the same work.
One-signature bets
Bets use a USDC permit so there is no separate approval step, with a fallback to the existing allowance when a permit is front-run.
06 / How it was built
How it was built
Agents work inside hard rules: an AGENTS.md with constraints, a 21-principle constitution, a domain glossary, a guard hook that blocks edits to secrets and retired contracts, a security-review agent on every contract change, and a nightly headless run that reviews production logs. 522 commits are co-authored with Claude.