A small model.
All on-chain.

16 × 16 pixels. A neural network trained to make faces.
The whole thing, small enough to live on the EVM.

thousands of possibilities.

click a face to make another.Tap a face to make another.16 × 16 pixels black & white

How it fits on-chain.

  1. 01

    Train a VAE.

    We trained on 9,958 resized Normies faces. We tested GANs and selected a variational autoencoder (VAE), trained with binary cross-entropy reconstruction loss, KL regularization, beta warmup, and Adam optimization.

  2. 02

    Export the decoder as integers.

    The encoder is only needed during training. Inference uses the 4,896-parameter decoder. We quantize its weights to signed 8-bit integers, with a power-of-two scale per output neuron. Fixed-point activations and bit shifts keep inference entirely in integer arithmetic.

  3. 03

    Pack the model into bytecode.

    Each neuron occupies 25 bytes: 16 one-byte weights, an eight-byte bias, and a one-byte scale shift. All 288 rows fit into 7,200 bytes embedded in contract bytecode. This avoids a separate storage slot for each parameter. Each inference copies the packed model into memory once.

  4. 04

    Run one forward pass.

    SHA-256 expands a seed into 16 fixed-point inputs. Solidity runs the decoder using integer multiply-accumulates and ReLU hidden layers. The final layer thresholds directly to black or white. Unrolled Yul operations and two reused memory buffers reduce loop overhead and memory allocation.

  5. 05

    Store each face in one slot.

    A 16 × 16 face contains 256 binary pixels. We pack them into one 32-byte bitmap, using one bit per pixel and one storage slot per image. The contract builds the SVG from those bits when requested, so the SVG itself does not need to be stored.

In the end: 10 kB contract size. ~300,000 gas unit inference. FULLY on-chain pixel art. Mwah.

Go to mint

Trained on CC0 Art.

Normie #3657 on its original 40 by 40 pixel grid

40 × 40Original grid

The same Normie reduced to the 16 by 16 training grid

16 × 16Training grid

Normie #3657, shown in the binary training palette.
  1. Scale down the art.

    We took the original 40 × 40 Normies bitmaps and resized them to 16 × 16 with nearest-neighbor sampling. It picks existing pixels without blending colors. Eyes, outlines, and accessories become simpler, leaving just 256 black-or-white pixels per face.

  2. Build the training data.

    We used 9,958 original-mint Normies. Every image uses the same binary pixel format.

  3. Teach the model.

    A variational autoencoder (VAE) learned to compress and reconstruct those faces over 60 epochs: 60 passes through the dataset. Its small decoder now turns a seed into a new face.

Shoutout to Normies and its creators, Serc and Yigit Duman, for creating open-source, CC0 art and making experiments like this possible.