zkVerify blog

Vibe Coding Blackjack Part 2

a poster for vibe coding blackjack part 2
a man in a suit and white shirt is smiling for the camera .
John Camardo

For those who may have read previous parts of my vibe coding series, I started very early with a version of blackjack. The idea was to create a verifiably random shuffle, prove that randomness with zk-proofs and allow the player to have a guarantee that they’re not playing against a “stacked” deck of cards.

The early version of this application did solve for this issue, but it had an issue with latency. As you were playing, you would have to wait up to 30 seconds for the proof to be created and verified. With this version I’ve solved that and the deal takes only a few seconds.

You can access this new version here: https://horizen-zk-blackjack-client.vercel.app/

Bear in mind that you must get Testnet Eth on Base Sepolia testnet and then bridge it into the Horizen Appchain on Base by using this bridge link (it’s lightning fast).

Bridge link: https://horizen-bridge.vercel.app/

The On-Chain Foundation: The Smart Contract as the Banker

The entire financial layer of our game is handled by a smart contract on the blockchain called BlackjackEscrow.sol. Think of this contract as a completely transparent and automated banker that no single person controls. Its job is simple but critical:

  1. Hold the Money: When a player starts a game, they send their bet (the "ante") directly to the smart contract's startGame() function. The contract holds this money in escrow, along with a matching amount from the house.
  2. Pay the Winner: The contract has a function called resolveGame(). This function can only be called by the trusted owner (our server). The server tells the contract who won the game, and the contract automatically sends the funds to the correct address.

Crucially, the smart contract itself knows nothing about the rules of blackjack. It doesn't deal cards or count scores. It only knows how to hold money and how to pay out based on instructions from its owner. This keeps the on-chain logic simple, secure, and cheap to run. Couple that with being on Horizen’s L3 and it’s almost free to run on chain (except for the buy-in transaction).

The Brains of the Operation: The Off-Chain Server

If the smart contract is the banker, the server is the dealer. It runs all the game logic off-chain, which is much faster and more flexible than doing it on the blockchain.

Here are the server's main responsibilities:

  1. Game Management: The server keeps track of the deck, the player's hand, and the dealer's hand for every active game.
  2. The Provably Fair Shuffle: This is where the magic happens. When a new game starts, the server shuffles a digital deck of 52 cards. At the same time, it uses a library called snarkjs to generate a Zero-Knowledge Proof. This ZKP is a cryptographic guarantee that the shuffle was mathematically random. The server can show this proof to the world to say, "I shuffled the cards fairly," without ever revealing the order of the cards in the shuffled deck. This is the "provably fair" part of our game.
  3. Executing Game Logic: When a player clicks "Hit" or "Stand" on the website, they are sending a request to the server. The server deals a new card or plays out the dealer's hand according to the rules of blackjack.
  4. Settling the Bet: Once the game is over, the server determines the winner and then calls the resolveGame() function on the smart contract, passing in the winner's address. This is the final, authoritative step that moves the money.

Conclusions

It would be easy to be critical of this game - it’s not built for production. In order to be truly random, rather than generating a random number in a private server, I’d reach out to Chainlink’s VRF or some other source of randomness that’s on chain. But my goal here wasn’t to be perfect. It was to generate some traffic on Horizen’s new testnet, and also to demonstrate yet another use case for zk proofs.