Live edition loading…

PXke Algorand

Independent daily coverage of the Algorand ecosystem — verified reporting on wallets, DeFi, NFTs and infrastructure, fact-checked on-chain before it publishes.

← Latest stories

ZK Color Sort verifies daily puzzle scores on-chain with zero-knowledge proofs

· · · · · · ·

ZK Color Sort verifies daily puzzle scores on-chain with zero-knowledge proofs

A Daily Puzzle With a Cryptographic Scoreboard

ZK Color Sort looks like the color-pouring puzzler you play on a phone while waiting for coffee: twelve tubes, ten colors, pour until every tube holds a single color. The twist is what the page asks for when you finish. 'Connect your Algorand wallet to unlock this feature,' it reads beside a 'Scores' button and a move counter. That is not a paywall. Connecting a supported wallet — currently Lute or Pera — is the entrance to the game's actual point: submitting your score to an Algorand [mainnet](/glossary/mainnet "The main public blockchain network where transactions are recorded and have real value, as opposed to a test network used for experimentation.") smart contract together with a zero-knowledge proof, a cryptographic certificate that a claim is true without revealing the data behind it. Here the claim is 'I solved this specific puzzle in N moves,' and the data kept private is the move sequence itself. Playing the puzzle needs no wallet at all; the proof-gated scoreboard is the [on-chain](/glossary/on-chain "Describes transactions that are recorded and permanently stored on a blockchain ledger, making them publicly visible and tamper-resistant.") layer.

The day's puzzle is itself drawn from the chain. The frontend asks an Algorand [indexer](/glossary/indexer "A service that organizes and indexes blockchain data so that applications can quickly search and retrieve information from the blockchain.") for the first block header after UTC midnight and deterministically derives the board from that header's seed, so the challenge is public and reproducible from chain history rather than chosen by a developer. The rules follow the standard Color Sort format, pinned down precisely in the project's README: twelve tubes of capacity four; ten colors appearing exactly four times each; two empty tubes to pour into; a legal pour moves the maximal contiguous run of a single color onto an empty tube or one whose top color matches; the puzzle is solved when every non-empty tube is fully monochrome. The score is the move count, lower is better, and local best scores with their full move histories live in browser localStorage. The on-chain registry never accepts a score that does not beat the player's own recorded best.

What the Zero-Knowledge Proof Actually Proves

Any on-chain leaderboard for a skill game has a credibility problem: a contract that accepts a number will accept any number. A trusted server that validates play reintroduces centralization, and publishing the winning solution gives away the strategy that produced it. ZK Color Sort tries a third path — prove it, don't show it.

When a player submits, the browser runs a Circom circuit through snarkjs, the open-source JavaScript proving library, and produces a Groth16 proof, one of the most widely used zero-knowledge schemes. The first submission downloads the roughly 55 MB proving key the game ships as a static asset; from then on the entire pipeline runs client-side, with no proving server behind the game. The choice of stack is deliberate: the snarkjs-algorand library's README notes that gnark, the compiler behind the alternative AlgoPlonk verifier, does not support WebAssembly, which would rule out in-browser proof generation — snarkjs is TypeScript and runs where the player is.

The circuit is tuned to this game's exact profile — twelve tubes, capacity four, up to 120 moves, ten colors, two empty tubes — and enforces the full game semantics: a valid starting board, legal moves under the pour rules above, correct state transitions after every move, a fully solved final board, and a move count equal to the number of active moves. What is public and what stays private is the whole design:

ConceptReal-World Implication
Public: the starting boardAnyone can confirm which puzzle a score refers to
Public: the move countThe number the registry stores and the leaderboard ranks
Public: puzzle identity and the wallet addressBound into the proof, so a proof minted for one puzzle or one account cannot be replayed for another
Private: the full move sequenceObservers can verify the claim without copying the winning strategy — the usual death of on-chain puzzle leaderboards

The On-Chain Score Registry

The receiving end is a smart contract called PuzzleScores, written in Algorand TypeScript, the modern Puya-compiled contract language that has replaced the older PyTeal. It holds one score per (puzzle, wallet) pair in app [box storage](/glossary/box-storage "On-chain key-value state attached to a smart contract, used by AlgoDirectory to store listing data directly on the blockchain instead of in a traditio") — key-value state attached to the contract itself. The key is a 20-byte puzzle code concatenated with the 32-byte wallet address (52 bytes total); the value is a single byte, which caps stored scores at 255 moves, far beyond what any solve of this puzzle needs. Creating an entry costs the exact box minimum-balance requirement, which the contract derives at runtime (2,500 microALGO base plus 400 per byte) and refunds if the player deletes the entry via removeScore. Read-only methods let a player fetch their own score or anyone else's.

Two write paths exist: addScore for a first entry, and updateScore, which the contract accepts only when the new score is strictly lower than the stored one. Both require an accompanying 'verifier' transaction in the same atomic group, and this is where the proof actually gets checked. The frontend composes a group of three transactions — a zero-value payment signed by a logic-signature account (an account whose authority is a program rather than a private key, derived from the game's verification key), the minimum-balance payment, and the app call. The contract verifies that the attestation payment comes from the configured verifier address and that the proof's public signals line up with the claimed score, puzzle code, and sender; the Groth16 verification math itself runs inside the logic-signature program, which produces the attestation payment only when it accepts the witness. Because a player's score, puzzle, and wallet are all pinned into the same proof, a submission generated for one puzzle or one account cannot be recycled for another. On the frontend, the same box store powers a percentile view: after connecting, the game scans the on-chain entries for the day's puzzle and tells the player how many others they beat.

Live on Mainnet — But Who's Playing?

The contract is real, deployed, and current: application 3603459425 was created at round 62,209,315 on June 16, 2026, by the account behind the project (which owns the .algo name tools.orange.algo), with its verifier configured minutes later. It now holds 94 score boxes, and the ledger shows app calls as recently as round 64,130,520 — August 16, 2026, two days before this writing. The web bundle confirms the frontend's default network is mainnet, matching the app ID in the repo's network config.

The sender ledger, though, tells a more modest adoption story. The developer's own wallet dominates both the transaction log and the box keys; a second submitting wallet was created on launch day and funded with 1 ALGO by the developer — a test account. Two further wallets trace their first funding to unrelated accounts created in 2022 and 2024, which is consistent with outside players, though neither carries an .algo name. The honest reading: this is a live but small registry, with most entries attributable to the developer's own testing and no evidence of a substantial player base yet.

The project itself is the work of a single developer — the GitHub account funk-af, whose profile names the owner 'Andrew' — and the same account publishes other Algorand contract work, including repositories described as smart contracts for Baanx and for the Immersve flexi-card funding protocol. The game repo shows 18 commits from June 2026 and no activity since June 18, while the deployed frontend and on-chain contract keep running.

Where the Trust Model Has Limits

Three caveats matter for anyone reading this registry as more than a game. First, the daily-puzzle derivation is a frontend convention, not a contract rule: the contract never checks that a submitted puzzle code corresponds to today's block-derived puzzle, and the circuit only validates that a puzzle is well-formed and solved. A proof for any well-formed puzzle from the same circuit profile would be accepted; nothing on-chain anchors a submission to the current date. Second, both the verifier address and the contract itself are creator-controlled — setVerifier and updateApplication are restricted to the creator's wallet — so the registry's integrity ultimately rests on a single developer not swapping the verifier or rewriting the contract. Third, the proving stack is un-audited: the snarkjs-algorand README warns that the SDK 'is a work in progress and not yet stable' and that 'The code in this repo has not been audited. Use at your own risk!'

None of that diminishes what is genuinely notable here: a working end-to-end demonstration of browser-side Groth16 proof generation feeding an on-chain verifier on Algorand mainnet, with a daily puzzle seeded from the chain's own block headers. If the pattern matures — an audited verifier, contract-enforced puzzle anchoring, and real players — ZK-verified skill gaming is a niche with a credible foundation. For now, it is an honest, small experiment, and it works.

Source

Source: https://zk-colorsort.netlify.app/