technical specsno off-chain assets214 KB model

how it actually works.

Slonks is an on-chain art experiment about neural reconstruction, not perfect copying. A tiny image model was trained on the canonical 24×24 CryptoPunks set and uploaded into bytecode. Every metadata read pulls the model's render and the original Punk live, then counts the pixels where they disagree. That count is your slop. The bigger the disagreement, the higher your slop.

§ 01

one slonk, three views.

The render is the artwork — a tiny neural reconstruction of the underlying CryptoPunk. The original and the slop are shown alongside so you can see the source and the pixels where the model disagreed.

Model output·render
Original Punk·punksdata
Slop field·128 slop
spec. #0 · three views of the same slonk
generated pixels
α
576
from the model · 24×24
original RGBA
β
2,304
bytes · CryptoPunksData
slop mask
γ
72
bytes · 1 bit per pixel
§ 02

the model is a candidate-palette renderer.

Not a transformer. Per pixel, the model picks one of 18 candidate colors from the exact 222-color CryptoPunks palette. A learned token embedding multiplies into a per-pixel head; the argmax selects the slot; that slot indexes into a precomputed candidate table to give a palette index.

slot[token, pixel]   = argmax_k dot( embedding[token], head[pixel, k] )
palette_index        = candidates[pixel, slot]
rgba                 = PALETTE_RGBA[palette_index]
the inference loop, repeated 576 times per render
tokens
vocab
10,000
one embedding per Punk
embed dim
d
10
bytes per token
candidates
k
18
colors per pixel
palette
P
222
exact RGBA, no nearest-color
packed bytes
bin
214,048
SSTORE2 chunks
pixel accuracy
acc
95.77%
quantized · all 10k punks
avg slop
slop
24.36
pixels · vs original
exact slonks
exact
32 / 10k
zero disagreement

Why so much error? The art concept is high recognizability with a persistent slop field. The team picked the candidate-palette checkpoint precisely because its mistakes read like learned reconstruction rather than random damage. Perfect was never the goal.

§ 03

the slop is not stored.

Zero bytes of slop data are uploaded. Every metadata read recomputes the mask live by comparing the model's 576 palette indexes to the 2,304 RGBA bytes pulled from CryptoPunksData. That's why your slop can drift if the model is ever swapped (the model is lockable on chain).

for pixel in 0..576:
    color   = PALETTE_RGBA[ generated[pixel] ]
    differs = color != originalRgba[pixel*4 : pixel*4+4]
    if differs:
        mask[pixel/8] |= 1 << (7 - pixel%8)
        count += 1

slop = count
tier = slop / 50           // floor
exactly what runs inside SlonksRenderer._slopMaskAndValue
slop dataset
upload
0 B
not deployed
recompute
live
every read
from canonical RGBA
tier
floor
slop / 50
integer division
§ 04

merging blends embeddings.

Two slonks of the same merge level fuse into one. The survivor keeps its original Punk anchor (the slop is still computed against that). The donor's embedding gets averaged into the survivor's; the model renders from that blended embedding from then on. The donor token is burned.

for i in 0..embedding_length:
    a = (int8) survivor.embedding[i]   // -128..127
    b = (int8) donor.embedding[i]
    blended[i] = (uint8)(int8)( (a + b) / 2 )    // truncates toward zero

survivor.mergeLevel  += 1
survivor.embedding   =  blended
burn(donor)
from SlonksMergeManager._blendEmbeddings — signed int8 element-wise mean
same level
rule
required
contract-enforced
slop source
anchor
survivor
punk stays the same
max level
cap
255
uint8 ceiling
survivor · #0
donor · #7
blended
renders from averaged embedding
§ 05

four contracts, four jobs.

The NFT shell, the model facade, the optional merge state, and the swappable renderer. Splitting them keeps tokenURI presentation independent from token ownership and keeps the model immutable once locked. Tap any address to open Etherscan.

ERC-721 shellsolidity

Slonks

Owns existence, transfer, the immutable 10,000 max supply, mint-time base source assignment, and the blockhash reveal. tokenURI just forwards the id to the renderer.

  • SeaDrop-compatible mint hook
  • Fisher-Yates source pool
  • permissionless finalizeReveal()
  • ERC-4906 metadata events
model facadesolidity

SlonksImageModel

Holds the model config and SSTORE2 weight chunk pointers. Exposes renderSourcePixels(sourceId) and renderEmbeddingPixels(bytes) for the merged case. Lockable by owner once final.

  • 214 KB packed weights
  • SSTORE2 chunk pointers
  • lockModel() makes weights immutable
cumulative statesolidity

SlonksMergeManager

Records the mergeLevel and packed cumulative embedding for survivor tokens. Burns the donor through Slonks. Holders approve this contract before merging.

  • level-match enforced on chain
  • packs embedding into bytes32
  • emits ERC-4906 on merge
metadata buildersolidity

SlonksRenderer

Builds the SVG, animation_url HTML, attributes, and live slop. Reads from Slonks, the model, the merge manager, and CryptoPunksData. Swappable so presentation can evolve.

  • renders LLM / Original / Slop
  • reads canonical Punk attrs
  • computes slop at read time
canonical sourcesolidity

CryptoPunksData

Larva Labs' on-chain Punks reference. Slonks pulls 2,304 raw RGBA bytes per Punk and the trait list from this contract — never mirrored, always live.

  • external dependency
  • punkImage(uint16) and punkAttributes(uint16)
Slonks.tokenURI(tokenId)
  → SlonksRenderer.tokenURI(tokenId)
      sourceId        = Slonks.sourceIdFor(tokenId)
      mergeLevel      = SlonksMergeManager.mergeLevel(tokenId)
      mergeEmbedding  = SlonksMergeManager.mergeEmbedding(tokenId)

      generatedPixels = mergeLevel == 0
                          ? imageModel.renderSourcePixels(sourceId)
                          : imageModel.renderEmbeddingPixels(mergeEmbedding)

      originalRgba    = CryptoPunksData.punkImage(uint16(sourceId))
      slop            = compare(generatedPixels, originalRgba)

      assemble JSON { image, animation_url, attributes }
the read path that runs inside every tokenURI() after reveal
§ 06

the palette is exact.

222 RGBA colors, mirrored from the canonical CryptoPunks set. No nearest-color quantization is used. Index 0 is fully transparent — every Slonk shows the renderer's #28313d background through it.

palette size
P
222
exact RGBA
transparent
0
index 0
background shows through
bg color
bg
#28313d
rendered behind
candidate cover
cov
99.4%
real-color hits
go play with it

The Merge Lab previews any blend live, no gas to look. Pick a survivor and tap around.

active
α
9,382
minted
β
10,000
burned
γ
618
phase
η
live