ISS
← Field Notes
Games screenshot
November 17, 2025 · Games · 2 min read

Building a Solana Dare Platform With On-Chain Rulings and Appeals

A Solana dare and bounty platform where challenges, proofs, votes, and appeals all run through Anchor smart contracts, kept in sync by a real-time indexer.

DoubleDog is a Solana-based dare and bounty platform. Users create challenges, fund a pot, submit proofs, and earn rewards through community voting. Underneath that simple loop is a full-stack system with four distinct pieces: Anchor smart contracts on-chain, a Node and Fastify API gateway, a real-time indexer, and a React frontend. You can see it at doubledog.fun.

Putting the dispute logic on-chain

The core challenge in any dare-and-reward system is not creating the dare, it is deciding whether someone actually did it, and handling the arguments when people disagree. DoubleDog pushes that logic into the Anchor and Rust programs rather than trusting a server to arbitrate.

The contracts model the whole lifecycle: a DareRegistry to create, fund, and manage dares; Submission for proofs with optional stakes; Ruling for creator, committee, and crowd voting; Appeal for challenging a decision by putting up stake; Reputation for tracking scores and strikes; and Refunds for claiming back money on expired dares. There are 18 error types with validation across all of it, plus fee calculation covering both the platform fee and voter rewards. Encoding rulings, appeals, and reputation on-chain means the rules of the game are enforced by the program, not by whoever runs the backend, which is the entire point of building this on Solana in the first place.

Keeping off-chain state in sync

On-chain truth is only useful if the app can read it quickly, and querying the chain directly for every feed load does not scale. That is the indexer's job. It holds a WebSocket subscription to the program logs and parses 11 different Anchor event types in real time, backfills historical transactions so nothing is missed, and reconnects with exponential backoff when the connection drops.

The detail I like most is how it stays honest under failure. It does crash recovery and resume, so a restart does not leave the database half-synced, and it invalidates the API's Redis cache through pub/sub whenever chain state changes. The API gateway sits in front of all this with wallet challenge and verify authentication issuing JWTs, transaction building for every program instruction, rate limiting at 100 requests per minute per IP and wallet, and the usual hardening. The React frontend ties in through the Solana Wallet Adapter and message signing for authenticated calls.

The takeaway

The hard part of a system like this is the seam between the chain and everything else. The contracts give you tamper-proof rules, but a chain is slow to query and events arrive as an unreliable stream. An indexer that parses events in real time, survives crashes with resume, and invalidates caches on change is what turns authoritative-but-awkward on-chain state into something a responsive app can actually serve. Get that boundary right and the rest of the stack has a clean, trustworthy source of truth to build on.

Have something that needs building, or stabilizing?

These notes are the work log. The paid work runs through Moonshine Labs, my product and engineering studio. Tell us what you're building, or grab a call.

Work with us →
the studio: moonshinelabs.io