Skip to main content

Zero-Knowledge Proofs in guessmyNFT

Why ZK?

In a traditional digital game, you'd trust a server to enforce honest answers. We don't have a server. Every answer in guessmyNFT is backed by a cryptographic proof — generated in your browser, verified on-chain. Nobody can lie.

How it Works

Commit phase

When you start a game, you select a hidden NFT. Your browser generates:

commitment = Poseidon2(game_id, player_address, character_id, salt)

The salt is a random 251-bit value (constrained to the Stark field). This hash is stored on-chain. Your opponent sees the commitment but not the NFT.

Answer phase

When your opponent asks a question, you answer. Your browser generates a ZK proof that:

  1. You know the preimage of your commitment (your actual NFT)
  2. The answer to the question is consistent with that NFT's traits

The proof is submitted on-chain. Garaga verifies it. If the proof is invalid, the transaction reverts.

Reveal phase

At the end of the game, you reveal your NFT. The on-chain verifier checks the Merkle proof — confirming your NFT's traits are part of the registered collection.

The Circuit

// Simplified guessmyNFT circuit
fn main(
character_id: u32, // private
bitmap: [Field; 4], // private (your NFT's traits)
salt: Field, // private
commitment: pub Field, // public (stored on-chain)
question_bit: pub u32, // public (which trait was asked)
answer: pub bool, // public (your answer)
) {
// Verify commitment
let computed = poseidon2([character_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]]);
assert(computed == commitment);

// Verify answer is honest
let bit_value = (bitmap[question_bit / 64] >> (question_bit % 64)) & 1;
assert((bit_value == 1) == answer);
}

Stack

ComponentTechnology
Circuit languageNoir 1.0.0-beta.16
Proof systemUltraHonk
Client proverbb.js (runs in browser)
On-chain verifierGaraga (Starknet)
Verifier address (Mainnet)0x64cb378d475b6247b0bbbe5ff5c3ec0615fbc2d63ed8e09b55e39c0a8597595

Performance

Proof generation runs in the browser using WebAssembly. Current times:

  • Proof generation: ~8–15 seconds (warm: 5–10s after first proof in session)
  • On-chain verification: included in the answer transaction
  • No server round-trip needed

We are actively working to reduce proving time to under 3 seconds. Read the full performance roadmap.