A year ago, Block 52 was a poker engine with a promising idea and a lot of rough edges. Today it is a live, provably fair, real-money poker platform that has dealt 13,837 hands across 76 tables — every one of them shuffled by verifiable randomness and settled on a public blockchain. This is the story of the twelve months in between: what we built, what broke, and how three separate codebases learned to agree on who is responsible for what.

Executive Summary

Between August 2025 and August 2026 we took Block 52 from a single-repo game engine to a three-layer platform in production. The headline moves:

The through-line for the whole year was determinism: in a system where multiple validators must independently agree on every outcome, any hidden source of randomness — a wall clock, a network call, a self-shuffled deck — is a bug waiting to halt the chain. Most of the hardest work below is a variation on that single theme.

Three Repositories, One Product

Everything at Block 52 lives across three codebases, and it helps to name them up front because the rest of this article moves between them constantly:

There is also a fourth, quieter member of the family — the indexer — whose only job is to watch the chain and keep the receipts. We come back to it near the end, because it is what turns "trust us" into "check for yourself."

Autumn 2025 — Standing Up a Chain

The year opened on the engine. In August and September we pushed the first real tournament work into the PVM — Sit & Go states and logic, a BlindManager, a PayoutManager — and ran a hard campaign on hand-evaluation correctness, fixing bugs as unglamorous and as important as "a straight loses to a high card" and a Sit & Go that refused to end when only one player remained.

Then, in October, the pivot that defined everything after it: we committed to a Cosmos-SDK blockchain. The chain repository was bootstrapped, the poker module scaffolded with on-chain game creation and queries, and the platform's identity model switched from Ethereum addresses to Cosmos bech32 addresses. From this point on, money and state had a real home. The first Ethereum→chain deposit bridge was built as a queue drained in an EndBlocker — a design that, as we will see, had a determinism trap hiding in it.

November was the busiest month in the chain's history — deployment infrastructure, an embedded WebSocket server for real-time gameplay, client-side signing so a player's hole cards are signed on their own device, and the first deterministic deck: the chain, not the client, would shuffle, seeded from consensus block data rather than the wall clock.

December 2025 — The First Determinism Reckoning

December is where the year's central lesson first drew blood. Adding a second validator to the network halted the chain: the two nodes could not agree on the application hash. The culprit was time.Now() — game state stamped with the wall clock instead of consensus block time, so every validator computed a slightly different world. The fix, "replace time.Now() with deterministic BlockTime()," was small; the principle behind it governed the next eight months.

The same month exposed a second, subtler instance. Automatic deposit-sync in EndBlock queried Ethereum for the "latest" block — but each validator hit the network at a slightly different moment and got a different answer, splitting the state. We disabled it within the hour and spent the following weeks re-architecting it around a stored Ethereum block height agreed by consensus. Gasless poker transactions and in-game top-ups also landed here.

The rule we kept re-learning: in a blockchain, every validator must compute the same result from the same inputs. A wall clock, a "latest block" RPC call, or an unshared random seed all violate that — and they don't fail loudly in testing. They fail in production, under load, the moment a second validator disagrees.

January – February 2026 — Open Source, Mainnet, and a Critical Halt

January delivered the most serious outage of the year — and the cleanest illustration of the determinism theme. The chain halted at block 67,301 in a two-against-two validator split, caused once again by non-deterministic Ethereum RPC calls in EndBlock. The fix pinned deposit-sync to a stored, consensus-agreed ETH block height, and made the whole path fail closed rather than guess. Alongside it, we did a data-model consolidation that the team still refers to by its house style guide, the "12 Commandments of Types": game_type became game_format, a game_variant field was introduced, and the definitions were unified across the protobuf schemas, the SDK, and every API response so there was exactly one source of truth. We also removed Date.now() from the PVM outright — a shuffle you intend to prove fair cannot depend on the clock.

February was about direction. We open-sourced the Block 52 UI — public repository, CI for lint, build and test, and a large styling standardization pass that moved inline styles into CSS Modules with documented visual-parity checks. And we migrated the settlement currency from Base-chain USDC to Ethereum-mainnet USDC — a change that rippled through the proxy, the bridge, and the UI, and forced a full chain reset and genesis regeneration.

Why open source? A platform that asks players to trust the deal should let them read the code that deals it. Open-sourcing the client is the first step toward the same standard we hold the shuffle to: don't trust us, verify us.

March – April 2026 — Hardening, Managers, and a Solver

March was a hardening month. We upgraded to Cosmos SDK v0.53.6 and CometBFT v0.38.21, and spent real effort resolving a persistent AppHash divergence at block 150 — the kind of consensus bug that only appears in production and only under load. Its root cause was, once more, non-determinism in the deposit-sync path. Player-facing, the marquee feature was NFT avatars, delivered end to end: on-chain registration via Ethereum signatures, protobuf and SDK support, and a polished selection modal. The UI also shipped hand replay and sharing, and a stage-geometry engine that auto-fits 2-, 6-, and 9-max table layouts.

April was the busiest month of the year and had three threads. First, we refactored the PVM's internals into a clean manager architecture — extracting PotManager, RakeManager, SidePotManager, and a showdown evaluator into injectable, interface-driven components behind a format factory. This is the plumbing that lets cash games and tournaments share one engine while behaving differently where they must. Second, we built a poker solver from scratch in Go: a native Cactus Kev hand evaluator, range-versus-range board equity, and a CFR-based solver across the 1,755 canonical flops, wired into our Telegram bot so it plays chart-driven poker instead of flipping a coin. Third, and most consequentially, the first stage of the verifiable-randomness initiative landed.

The Random Bug — A Family of Five

Every provably fair platform lives or dies on one question: is the shuffle actually random, and can you prove it? Over the year we found and fixed not one randomness bug but a whole family of them, and they are worth telling honestly because together they are the reason the current system is trustworthy.

The clock and the network. The first two — the time.Now() halt and the Ethereum-RPC-in-EndBlock split described above — were not about card randomness at all. They were about hidden randomness leaking into consensus, and they halted the chain twice. They taught us to treat every non-deterministic input as radioactive.

The biased shuffle. The third was in the cards themselves. Our legacy Fisher-Yates shuffle reused too few hash bytes and selected positions with a direct modulo, which introduced modulo bias — some cards came up measurably less often than others. In the worst case, spades were being dealt at roughly 75% of their expected rate. The fix was the full VRF migration: an ECVRF construction (RFC 9381) feeding an HKDF-SHA256 stream with rejection sampling, so every position is drawn without bias. After the fix, card distribution sat within 0.1% of expected. Verifiable randomness went live in production on 1 May 2026.

VRF Shuffle: From Proposal to Verified Deck

PrepareProposal Proposer generates VRF seed
→
ProcessProposal Validators verify the proof
→
Record Seed Committed on-chain
→
Shuffle Deterministic deck
→
Anyone Verifies Reproduce & check

The fork. The fourth was the most instructive, and it did not surface until the optimistic gateway was live. In gateway mode, the front-end was self-shuffling a deck and sending it to the fast path, while the chain shuffled its own VRF deck for settlement. Same hand, two different decks — so a different player would bust on the chain than on the table players actually saw, the "who acts next" pointer diverged, and every subsequent action failed with ErrNotYourTurn. The hand would play out optimistically but never settle; only the final "leave" transaction persisted. We caught it with a 20-hand smoke test that deliberately compares chain and gateway outcomes, and fixed it by making the deck chain-authoritative: the chain rejects any client-supplied deck, and the front-end now sends only a seed, never cards.

The tradeoff. The fifth is where we are today, told plainly. Anchoring the deck to the chain made seeding asynchronous — the seed for the next hand only commits after the current hand settles — which, behind a serial settlement drain, could stall live play. Our current resolution shuffles synchronously in-handler from a client-supplied seed and keeps the full VRF machinery dormant behind it. It is a deliberate, documented tradeoff for playability, with the verifiable path ready to re-enable. We would rather tell you exactly where the seam is than pretend it isn't there.

None of these bugs were hidden after the fact — each has a dated commit, a reproduction test, and a paper trail. That is the point. "Provably fair" is not a slogan; it is a discipline of writing down where the randomness comes from and letting anyone check the math.

The Funding Rails

A poker platform is a money platform, and money has to move correctly before anything else matters. The funding architecture came together over the year as: external crypto → USDC on Ethereum → a bridge contract → the chain's deposit-sync credits the player's balance, keyed to a pinned Ethereum block height. Two on-ramps feed it — a NOWPayments proxy that accepts 100+ cryptocurrencies and auto-converts to USDC, and direct Web3 USDC/USDT deposits. Withdrawals burn the balance and produce a validator-signed redemption.

The reliability lessons here were bought the hard way. Early on, a user's real payment was processed by NOWPayments but never credited, because an undefined RPC URL silently defaulted to localhost; the fix was strict environment validation that panics on a missing value rather than guessing. Another payment got stuck until we moved IPN handling to be asynchronous with proper gas pricing. The recurring pattern — fail loudly and closed, never silently and open — is the same discipline that governs the shuffle.

The subtlest funding bug came late, and it is a good example of how architecture changes create new failure modes. When money-movers — buy-in, leave, top-up — were briefly routed through the optimistic gateway like ordinary gameplay, a buy-in could be applied to the table optimistically, seating a player before the chain ever checked their balance. The result: players could buy in for free. We closed it in three layers — the gateway now rejects any money-in mover that doesn't carry a real settlement transaction, the UI gates the button on an actual balance check, and money-movers stay strictly ordered on-chain even as gameplay went unordered for speed. Speed where it is safe; the chain where it matters.

The Optimistic Gateway

June was the architectural turning point. We introduced the optimistic gateway: a WebSocket-first transport where player actions are signed on the client, relayed over WebSockets for fast play, and settled to the chain behind the scenes. The chain became the opt-out path rather than the hot path for every keystroke. On the back end this meant a new Go WebSocket gateway with per-viewer state masking — the deck is always hidden, your hole cards are yours alone — Redis-backed persistent state, real PVM-backed action application, and a settlement relay that forwards signed transactions to the chain. In parallel we began porting the engine to Go for the gateway's needs, validated against a parity corpus so the Go and TypeScript engines agree action for action.

July was about making the new architecture trustworthy and making the client keep up. On settlement we converged on a trustless, unordered, serially-drained model: a drain worker with no-drop retry of recoverable rejects, resync on sequence mismatch, and unordered signing in the SDK so transactions no longer depend on a fragile account-sequence counter. The chain stopped running its own payout math entirely and now settles purely from PVM-authored results, pushed up via a new hand-end message. In the UI we rebuilt event handling around a WS Action Bus with paced draining, backpressure, and animation-acknowledgment gates, so the table stays in sync even when the socket delivers frames out of order or in bursts. And on the engine we deleted the ALL_IN action entirely — a shove is now just a raise for a player's whole stack, with "all-in" a pure front-end label — quietly removing a whole category of edge cases.

The core idea: most poker actions are cheap and reversible until money settles. Sign them, send them over a socket, play at real speed — and let the chain be the authoritative backstop that settles the hand, not a toll booth on every fold.

The Indexer — Keeping the Receipts

None of the fairness work means anything if you can't audit it, which is why the quietest repository is one of the most important. The indexer is a small, standalone Go service with exactly one job: read every dealt hand off the chain into a PostgreSQL database and run statistics on the cards. It captures each hand_started event — with its deck seed and shuffled deck — and each hand_completed showdown, and it exposes the totals over a public API. Its headline capability is a chi-squared test on card frequency: a live, ongoing check that the dealer produces a uniform one-in-fifty-two distribution.

The indexer has been running continuously since 1 May 2026 — the exact day verifiable randomness went to production, which is not a coincidence. It is the instrument that lets us make a claim about fairness and then hand you the evidence to check it. As of this writing, here is what it has seen:

13,837 hands dealt
13,763 played to showdown
139,329 cards revealed
76 unique tables

Those are not marketing numbers rounded up from a dashboard. They are live counts — COUNT(*) over a table of hands with a uniqueness constraint on (game_id, hand_number) — served on demand from the chain's own event stream, spanning roughly 1.6 million blocks. Every one of those 13,837 hands has a recorded seed and deck that anyone can reproduce and check. That is the whole point of the platform, expressed as a number.

The Arc of the Year

Step back and the twelve months trace a clear line. We started with a single-repo game engine, a wall-clock bug that could halt the chain, and a shuffle that quietly favored some cards over others. We finished with three cleanly separated layers — the client presents, the PVM rules, the chain settles — a verifiable-randomness pipeline wired into consensus, real money moving over hardened rails, an optimistic transport that plays at socket speed, and an indexer standing over all of it counting hands and testing the cards.

The consistent theme was drawing sharp lines of responsibility between the layers and then rebuilding the connections between them so each does its job and nothing else — and, underneath that, chasing down every last place where hidden randomness could sneak into a system that has to be deterministic to be provable. That work is rarely glamorous. But it is exactly the work that lets us make the one promise that matters: every hand is provably fair, and you don't have to take our word for it. Nearly fourteen thousand hands in, the receipts are public.

We build provably fair poker at Nine High Studios.

Twelve months of engineering behind every hand on Block 52. If you're building a poker platform and want it done right, let's talk.

Get in Touch ♦