P2P prediction markets for everyday bets between friends.
Rob bets Tom 10 USDC that Tom can't finish a beer in 30 seconds. They open a market, both stake, the deadline hits, an AI oracle reads the criteria + any evidence, settles the verdict on-chain, and the winner takes the pot.
Toldya is intentionally smaller than centralized prediction markets: anyone can spin up a market with no approval, resolution is handled by an AI oracle against the criteria the creator wrote, and the economic model is a simple pari-mutuel escrow — no AMM, no shares, no curves.
Live on the Taiko Hoodi testnet: https://toldya-psi.vercel.app
- Anyone creates a market — a YES/NO question, resolution criteria, a deadline, a match mode (pool or pair), and an initial USDC stake on YES or NO. The creator chooses AI-oracle resolution or unanimous bettor vote.
- Friends stake — others deposit USDC into the YES or NO pool until the deadline (or a single counterparty matches the creator, in pair mode). A flat 1% fee is taken on every stake and sent to the protocol treasury — it funds oracle gas and discourages spam markets. Stakes are locked until resolution.
- Deadline passes — anyone calls
triggerResolution(marketId). If only one side has any stake (or a pool-mode quorum wasn't met), the market is voided immediately and everyone is refunded. Otherwise it opens an oracle request. - The AI oracle settles — resolution runs through
Veto, a multi-agent
council (a gatekeeper plus info- and judge-agents) that reads the question,
criteria, and any submitted evidence and records the outcome on-chain. Anyone
then calls
resolveMarket(marketId), which readsoracle.outcomeOf(...)and finalizes the market YES or NO. (Alternatively, bettors can settle a market early by unanimous vote before the deadline; a market that never settles can be voided by anyone after a 14-day timeout so funds are recoverable.) - Winners claim — each winner's payout is
(myStake / winningPool) * totalPot.
USDC here is a self-mintable test token: its public mint() is the in-app
faucet, and a small EthFaucet dispenses Hoodi ETH for gas.
Three components in this repo, plus the Veto oracle service in a sibling repo.
contracts/ Foundry — ToldyaHub (UUPS proxy), Usdc, EthFaucet, IOracle
backend/ Go — chain indexer + Postgres + REST /v1 API (on GKE)
frontend/ Next.js 15 + wagmi/viem + Privy/SIWE (on Vercel)
contracts/— the on-chain core.ToldyaHub.solis a UUPS-upgradeable pari-mutuel escrow (create/stake/trigger/vote/resolve/claim, pool + pair modes).Usdc.solis the 6-decimal, public-mint()test token used for bets;EthFaucet.soldispenses gas;interfaces/IOracle.solis the oracle boundary the hub reads through.backend/— a Go service that indexes hub events into Postgres and serves a read API the frontend can't get from the chain alone: live activity, comment threads, staker lists, friend graph + requests, and user profiles. Deployed on GKE. Seebackend/deploy/k8s/for the deploy chart.frontend/— the Next.js app: the market feed, create flow, market detail- betting panel, AI-verdict status, profiles, the friend graph (requests / accept / decline), comments, and social sharing. Wallet + auth via Privy and Sign-In-With-Ethereum. Deployed on Vercel.
- Veto oracle (taikoxyz/veto, a separate
repo) — the AI council that watches for
oracle requests, evaluates them, and settles
outcomeOfon-chain. The hub is registered with it per deployment.
| What | Address |
|---|---|
| ToldyaHub | 0x6b331e96129BCcaE043da8E1004b3C9b3b9d71D6 |
| USDC (bet token) | 0x50cb928C68992aE21138E7F46b4944553c4f3B37 |
| Veto oracle | 0x4395569A5983dbacBc9545b71126101D30f01a5C |
| Treasury | 0x5f2b097ffF3BC8fE3EB254aCCBe7E81Fe50160AA |
RPC https://rpc.hoodi.taiko.xyz · Explorer https://hoodi.taikoscan.io
Testnet addresses — they can change on a redeploy. The canonical source is the frontend's
NEXT_PUBLIC_*env vars and the backend's indexer config.
cd contracts
forge install foundry-rs/forge-std --no-commit
forge install OpenZeppelin/openzeppelin-contracts --no-commit
forge build
forge test -vvTo deploy locally against anvil:
anvil & # in another terminal
export DEPLOYER_PK=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # anvil[0]
export ORACLE_ADDRESS=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 # anvil[1]
export TREASURY_ADDRESS=0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC # anvil[2]
forge script script/Deploy.s.sol --rpc-url http://localhost:8545 --broadcastFor local dev the deploy script wires up a MockToken (standing in for USDC) and
the ToldyaHub; note both addresses from the logs. (On the testnet the bet token
is the real Usdc contract above, deployed via script/DeployUsdc.s.sol.)
Requires Go and a Postgres database. Point it at your DB and the chain, then run the indexer + API:
cd ../backend
# set DATABASE_URL, the RPC URL, and HUB_ADDRESS (see backend config / deploy chart)
go run ./cmd/backendMigrations are embedded and run on startup. The API listens for the frontend's
/v1/* calls.
cd ../frontend
cp .env.example .env.local
# Fill in the values: the hub + token addresses, the RPC URL, the backend API
# URL (NEXT_PUBLIC_BACKEND_URL), the Privy app id, and the IPFS gateway.
npm install
npm run devOpen http://localhost:3000.
Polymarket-style markets use AMMs because they need continuous price discovery across thousands of traders. Toldya is for friend-scale markets — usually 2 to 10 participants betting tens of dollars on whether someone is going to chug a beer. An AMM there would be all overhead and no signal: the "price" would jump wildly with every stake. A pari-mutuel escrow gives the same expected payout, with simpler contracts and zero LP risk for the creator.
- No early withdrawals. Once you stake, you're committed until resolution. Backing out would defeat the point of a friend bet.
- No share trading. You can stake more on either side, but you can't sell your position to someone else.
- No on-chain dispute path. Resolution is delegated to the Veto AI council
(an upgrade from the original single-agent oracle), but if it gets a verdict
wrong the only remedy is the hub owner swapping the
oracleaddress or letting the market void after the timeout — fine for friends-mode, not for high-stakes markets.
MIT