CryptoKitties: The Genome Project

Someone reverse-engineered the breeding algorithm.

The GeneScience contract was the only part Axiom Zen kept closed. Everything else was open-source: KittyCore, the auction house, the CEO controls. All on Etherscan.

But the breeding logic? Bytecode only. No source code, no comments. Just machine instructions.

The main contract even taunts you:

// Call the sooper-sekret gene mixing operation.
uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1);

Makes sense. If you know the breeding math, you can game the market.

Didn't last. The community cracked it in five days.


December 18, 2017. Kai Turner figured out the genome structure. Each kitty has a 256-bit integer. Break it into 5-bit chunks and you get 48 genes. Four genes per trait. Primary (visible) plus three hidden recessives.

He created a notation to make genomes readable.
Base32 using 123456789abcdefghijkmnopqrstuvwx. No digit-0, no lowercase-L.
CryptoKittydex adopted this "Kai notation."

December 22, 2017. Sean Soria reverse-engineered the mixing algorithm. He stepped through the bytecode and published the pseudocode:

def mixGenes(mGenes[48], sGenes[48], babyGenes[48]):
  # PARENT GENE SWAPPING
  for (i = 0; i < 12; i++):
    index = 4 * i
    for (j = 3; j > 0; j--):
      if random() < 0.25:
        swap(mGenes, index+j, index+j-1)
      if random() < 0.25:
        swap(sGenes, index+j, index+j-1)

  # BABY GENES
  for (i = 0; i < 48; i++):
    mutation = 0
    if i % 4 == 0:
      gene1 = mGenes[i]
      gene2 = sGenes[i]
      if gene1 > gene2:
        gene1, gene2 = gene2, gene1
      if (gene2 - gene1) == 1 and iseven(gene1):
        probability = 0.25
        if gene1 > 23:
          probability /= 2
        if random() < probability:
          mutation = (gene1 / 2) + 16

    if mutation:
      babyGenes[i] = mutation
    else:
      if random() < 0.5:
        babyGenes[i] = mGenes[i]
      else:
        babyGenes[i] = sGenes[i]

The black box was now transparent.

December 23, 2017. Alex Hegyi verified everything with Python and published his implementation to GitHub.

January 6, 2018. Kai published part two, synthesizing the community's findings.

Six weeks after launch, Kai's synthesis had turned raw bytecode into a practical breeding guide.

What they found

Inheritance favors primary genes. But hidden recessives can bubble up:

Gene PositionInheritance Chance
Primary37.5% per parent
Hidden 19.4% per parent
Hidden 22.3% per parent
Hidden 30.8% per parent

Before inheritance, genes swap positions. Each swap has 25% odds. A deep recessive can climb three positions and end up dominant.

Mutations create new traits. When both parents contribute adjacent genes (N and N+1, where N is even), there's a 25% chance the offspring gets gene (N/2) + 16. This is how M1 mewtations appear. Breed two M1 genes the same way and you get M2. And so on.

TierGene RangeChance
Base0-15-
M116-2325%
M224-2725%
M328-2912.5%
M43012.5%

Gene 31 is impossible to reach through mutation. Easter egg territory.

Community tools followed:

How the cats are drawn

Each kitty image works like a police facial composite. The genome encodes traits. A server assembles layers.

To generate each cat's image, Axiom Zen's servers read the 256-bit genome from Ethereum, map each gene to a pre-drawn SVG component, swap colors via a palette lookup, then stack the layers: body shape, pattern overlay, eyes, mouth, accessories. The result is a composed SVG unique to that genome.

Fancy cats break the system. They're hand-drawn PNGs that don't fit the compositing pipeline. Special recipes, special art.

The irony: the genome is immutable and on-chain. The art is off-chain and owned by Axiom Zen. You own the token. You own the genes. The visual representation? That's served from their CDN, rendered by their code, governed by their license.

If Axiom Zen disappeared tomorrow, the genomes would survive on Ethereum. Rendering them into images would require reconstructing the entire art pipeline. Someone archived most of the assets. The compositing logic is reverse-engineerable. But it's not trustless the way the breeding is.


Reverse engineering succeeded because the contract runs on Ethereum. The bytecode is public. The state is public. The inputs and outputs are public. You can reverse-engineer anything if you can see it running.

Axiom Zen could have deployed on a private server. Kept control. Kept the secrets.

They didn't.

That's the point of this whole thing. The ownership can't be faked. The breeding history can't be rewritten. But the company kept admin keys. They can pause the contract. They can swap the breeding algorithm. They can change the rules going forward. What they can't do is change the past. Every breeding event, every genetic roll, every transaction is permanent. The record is trustless. The game isn't.

This is what "decentralized" actually means.

It's not about currency. Not about absolute control. It's about verifiable constraints.


I looked at one of my cats, Simpatico.
Gen 17. Visible traits:

Three diamond-tier traits. That's rare. But what made Simpatico "valuable for breeding" wasn't just what you could see. It was what genes were hiding.

The website shows the genome broken into 12 trait groups. Each group has 4 genes: one primary (visible) and three hidden recessives. Simpatico's Eye Shape genes are 7, 5, 7, 4: thicccbrowz dominant, with simple, thicccbrowz, and raisedbrow lurking behind it.

When I bred Simpatico with Mongo, the algorithm rolled dice across 48 gene positions. First the swapping phase: each hidden gene had a 25% chance to swap toward the primary slot. Then inheritance: each position pulled from one parent or the other.

Dozer came out with "crazy" eyes. Neither parent showed that trait. But Mongo carried it in a hidden slot. The swap mechanic promoted it to primary. The inheritance roll selected it.

That's the game. You're not just breeding visible traits. You're breeding probability distributions.