Inspiration
I loved the idea of arcade games that live fully on-chain. An earlier generation of games like this needed a trusted server to generate levels and validate scores. Midnight removes that need. Compact lets the rules of a game become a zero-knowledge circuit. We also wanted to fix what leaderboards usually get wrong. They expose everything about everyone. We wanted friendly competition where your score is provably real but stays your secret until you choose to share it.
What it does
Moonray gives every player in the world the same puzzle each day. Two irregular plates of moonlight hold 8 to 14 moonlets. You get up to 3 straight cuts. When a cut leaves a moonlet alone in its shard, the shard dissolves and the moonlet is collected. Each moonlet is worth 10 points. Clearing the whole field with fewer cuts earns a bonus.
When you finish, the game builds a zero-knowledge proof of your run. The circuit rebuilds the level from the tournament seed, checks that every cut and every piece is geometrically valid, and computes your score. The chain receives only an anonymous nullifier and a hidden commitment. Nobody can see your score, your cuts, or who you are. You can reveal your score on the leaderboard whenever you want, or never. One entry per player per day is enforced by the nullifier. A nickname registry makes the leaderboard friendly for groups.
How I built it
The contract is written in Compact and compiles to 4 circuits. The heart of it is a geometry verifier that runs entirely in-circuit. It checks piece convexity, cut alignment, area tiling against both plates, and moonlet isolation. Compact has no negative numbers, so all the geometry uses a positive and negative sum decomposition of cross products. Nothing ever subtracts.
Level generation also happens in-circuit. The tournament seed is hashed into two entropy streams and decomposed into limbs that jitter the plate vertices and moonlet positions. There is no level server to trust.
A TypeScript engine mirrors the circuit exactly. The compiler exports pure circuits as ordinary functions, so the frontend preflights every run with the same code the proof will execute. A run that passes preflight cannot fail in proving.
The frontend is React with a canvas renderer. The 1AM wallet handles balancing, fees, and submission on Midnight preprod. Proving runs on a local proof server because the main proving key is 68 MB. The site is deployed on Vercel as a static build with a small serverless function for the name registry. An unlinked admin console at a hidden route deploys the contract and opens daily operations straight from the browser wallet.
Challenges I ran into
Compact is a constraint language, not a scripting language. There are no mutable variables, no unbounded loops, and no subtraction on naturals. Rewriting computational geometry under those rules was the hardest part of the project.
Degenerate geometry nearly broke us. A cut that grazes a polygon corner creates a one pixel edge that the circuit cannot attribute to any source line. I fixed it with vertex merging in the engine and by rejecting unprovable cuts before they cost the player anything.
The proving key for a run is 68 MB. The wallet's messaging channel refused it, so I routed proving to a local proof server while the wallet still balances, pays, and submits.
Accomplishments that I am proud of
The entire rule set of a real game is enforced by a zero-knowledge circuit. No server exists anywhere in the stack. Level generation, move validation, and scoring all happen inside the proof. Scores are private by default and revealing is a genuine choice. The engine and the circuit share one source of truth, verified by 19 contract tests and a suite of lockstep property tests. The game is live on Midnight preprod with a full wallet flow and a public deployment.
What I learned
I learned to design algorithms without subtraction, without division, and without loops of unknown length. I learned that witness data is always untrusted and every claim needs an in-circuit check. I also learned the practical texture of Midnight. Dust generation, proving key sizes, and indexer behavior shape the user experience as much as the circuit does.
What's next for Moonray
Mainnet
P.S I apologize for the video size it is over 2 minute. I might have not mentioned this on the video but this game is completely built from the ground up for this hackathon
Built With
- compact
- love
- nextjs
- typescript
- vite
Log in or sign up for Devpost to join the conversation.