How it works.

Qunks is an on-chain AI art experiment on Ethereum. A neural network stored entirely on-chain renders mirror images of CryptoPunks. The pixels where the model disagrees are the art.

§ 01

the model is a candidate-palette selector.

Not a transformer. Not an MLP. For each of the 576 pixel positions, the model selects one of 8 pre-computed candidate colors from the 222-color CryptoPunks palette.

// inference per pixel (repeated 576 times)
for k in 0..8:
    score[k] = dot(embedding[8], head[pixel, k, 8])
slot = argmax(score)
color = candidates[pixel, slot]
EMBED DIM
8
bytes per token
CANDIDATES
8
colors per pixel
PALETTE
222
exact CryptoPunks RGBA
ACCURACY
94.7%
pixel-exact match
MODEL SIZE
122 KB
on-chain (SSTORE2)
PIXELS
576
24×24 image
AVG DIFF
30
pixels vs original
INFERENCE
free
view function
§ 02

pixel_score determines value.

Each pixel in a Qunk is a palette index (0-221). The pixel_score is the sum of all 576 palette indices. It's computed on-chain via a view function (free) and determines your dissolve reward.

pixel_score = sum(generated_pixels[0..576])
// each pixel is a palette index: 0-221
// range: ~4,000 - ~47,000 (uint32)
// higher score = more colorful = more valuable

effective_score = pixel_score + level × 10,000

The palette is the exact 222-color CryptoPunks palette. Index 0 is the background. Higher indices tend toward brighter/more saturated colors, so higher pixel_score generally means a more vivid image.

Loading palette...

Live Example: pixel_score calculation

Loading...
§ 03

fully on-chain on Ethereum.

The entire model — embeddings, scoring heads, and candidate tables — is stored on-chain using SSTORE2 (contract code storage). Inference runs in view functions, so it's free to call. Mint and fuse only store 8-byte embeddings (cheap). No off-chain computation, no oracles, no IPFS.

Embeddings80 KB · 4 SSTORE2 chunks
Scoring Heads36 KB · 2 SSTORE2 chunks
Candidates4.5 KB · 576 × 8 palette indices
Palette666 bytes · 222 RGB colors
Mint gas~150K gas (only stores embedding)
Fuse gas~97K gas (blend + burn)
Inferencefree (view function)
§ 04

five actions, one economy.

Mint0.001 ETH

Pick a seed (0-9999). The contract stores the model's embedding for that seed. Image is rendered on-demand via view function.

Fusefree (burn donor)

Select a survivor and a donor. Donor is burned, survivor's embedding becomes the average of both. Survivor keeps its ID. Level increases by 1. Deterministic — no randomness.

Dissolvefree (burn NFT → get $QUNK)

Burn a Qunk to receive $QUNK tokens. Output = pixel_score + level × 10,000. Deterministic. Seed goes to void pool for summon.

Summondynamic $QUNK

Burn $QUNK to pull a seed from the void pool. Cost = last dissolve output. Re-minted with its original embedding at level 0.

Custom Mintdynamic $QUNK

Provide your own 8-byte embedding. The model generates a unique image from it. Cost = last dissolve output. Pick any unminted seed ID.

§ 05

live examples.

Loading...
Loading...
§ 06

$QUNK token.

$QUNK is an ERC-20 token. It's only minted through Dissolve and only burned through Summon and Custom Mint. No pre-mint, no team allocation.

STANDARD
ERC-20
Ethereum
DECIMALS
18
MINT
Dissolve only
no pre-mint
BURN
Summon + Custom
deflationary pressure
MAX SUPPLY
dynamic
depends on dissolves
CONTROLLER
Qunks contract
only it can mint/burn
§ 07

two contracts, all on-chain.

Qunks uses two Solidity contracts: the main ERC-721 NFT contract (handles minting, fusing, dissolving, summoning, and model inference) and the $QUNK ERC-20 token.

Qunks.sol (ERC-721)
mint · fuse · dissolve · summon · customMint
renderPixels · pixelScore (view, free)
uploadEmbedding · uploadHeads · lockModel
QunkToken.sol (ERC-20)
mint (only by Qunks contract on dissolve)
burnFrom (only by Qunks contract on summon/custom)
Storage (SSTORE2):
4× embedding chunks · 2× heads chunks · candidates · palette
§ 08

not a copy.

Qunks is inspired by Slonks but differs in several ways:

ChainEthereumEthereum
SourceCryptoPunks (original)CryptoPunks (mirrored)
Score metricslop (pixel count)pixel_score (index sum)
Fuseburn 1, keep 1burn donor, modify survivor
Token outputfixed (= slop)deterministic (score + level × 10K)
RevivalDutch auctiondynamic (= last dissolve output)
Custom mintnoyes (dynamic cost)
Inferenceview functionview function (same approach)