$SLOPwhitepaper.
$SLOP is a design proposal — no token has launched, no contract is deployed, nothing is mintable, nothing is for sale. This page describes how the system will work. Anyone offering you "$SLOP" today is selling you something else. Expect this draft to keep changing until it's final.
$SLOP is the liquid token form of slop. Slop is the number of pixels where the Slonks model output differs from the original CryptoPunk. The void will make slop liquid: voiding a Slonk mints $SLOP equal to its slop, and burning $SLOP revives a Slonk from the void.
Slonks enter the void -> slop becomes $SLOP $SLOP burns -> revive Slonks from the void merging -> permanently burns Slonks · emits no $SLOP
key terms.
The vocabulary used throughout this paper. If you only read one section, read this one.
- Slonk
- An NFT in the Slonks collection.
- Source CryptoPunk
- The original CryptoPunk image assigned to a Slonk. Each Slonk has one source CryptoPunk.
- Slonks model
- The on-chain image model trained to reconstruct CryptoPunk images. The model renders the Slonk image.
- Generated image
- The image produced by the Slonks model for a Slonk.
- Original image
- The source CryptoPunk image used as the comparison target.
- Slop
- The number of pixels where the generated image differs from the original. A Slonk image has
576pixels, so a Slonk has between 0 and 576 slop. - $SLOP
- The ERC-20 form of slop. When a Slonk is voided, its slop becomes newly minted $SLOP.
- Void
- The contract state where Slonks are held after being converted into $SLOP. The void is not a burn address — it is a reservoir of voided Slonks that can return through revival.
- Revival
- Burning $SLOP to draw a Slonk back out of the void.
- Merge
- The existing Slonks mechanic where one Slonk consumes another to create a new visual state. Merging is separate from $SLOP minting.
- Embedding
- A small numeric representation used by the Slonks model to render an image. Revival gives a Slonk a new active embedding.
the void makes slop liquid.
$SLOP launches with 576,000 tokens in a one-sided pool. After launch, new $SLOP only enters circulation when Slonks enter the void. $SLOP leaves circulation when users burn it to revive Slonks.
$SLOP is liquid slop — and a resource for interacting with the Slonks machine. Holding a Slonk is one position; holding $SLOP is another; revival lets you swap between them with the contract acting as the counterparty.
hard cap is 5,760,000.
The supply cap comes from the canvas itself: 10,000 Slonks × 576 pixels.
Max supply: 5,760,000 $SLOP Launch inventory: 576,000 $SLOP Future emission capacity: 5,184,000 $SLOP
The launch inventory starts the market. The remaining supply is emission capacity that can only be minted by Slonks entering the void. All $SLOP amounts in this document are whole-token amounts — with 18 ERC-20 decimals, 100 $SLOP is 100e18 base units onchain.
launch is one-sided.
$SLOP launches through a one-sided liquidity pool. Buyers bring the ETH side.
- ▸576,000 $SLOP minted into the launch pool / launch manager
- ▸buyers bring the ETH side through public buys
- ▸launch configuration is fixed before the pool opens
voiding mints $SLOP.
A holder voids an active Slonk. The Slonk leaves circulation, the void contract takes custody, and the holder receives $SLOP equal to the Slonk's current slop.
slopMinted = currentSlop mintAmount = slopMinted maxSlopMinted = 576 $SLOP // 24 × 24 pixels
- ▸the Slonk leaves active circulation
- ▸the Slonk is held by the void / game contract
- ▸the holder receives newly minted $SLOP
- ▸the amount minted equals the Slonk's current slop
- ▸the Slonk cannot be transferred or merged while in the void
voidSlonk(tokenId) reverts when slopMinted > maxSupply - totalSupply. Each call is checked independently — there is no separate global closed flag. A voided Slonk stays in the void until a revival request draws it back out.
slop is recomputed live.
The game contract calculates slop from the Slonks source assignment, the token's current state, the locked image model, the canonical CryptoPunksData pixels, and the slop calculation logic.
sourceId = Slonks.sourceIdFor(tokenId) generatedPixels = imageModel.renderSourcePixels(sourceId) originalPixels = CryptoPunksData.punkImage(sourceId) currentSlop = countSlopPixels(generatedPixels, originalPixels)
For a merged or revived Slonk, the contract uses the token's current active embedding to calculate the generated pixels before computing slop.
merging stays separate.
Merging is the existing Slonks mechanic where one Slonk consumes another. Merged donors are permanently consumed — merging does not mint $SLOP, burn $SLOP, or move a Slonk into the void.
$SLOP emissions are tied exclusively to voiding. Merging produces a new visual state at a higher merge level. Voiding produces $SLOP. The two paths share Slonks but never share emissions.
revival is the primary burn sink.
Burn the current revival cost to pull a Slonk out of the void. The revived Slonk leaves the void, gets a new active embedding, returns to active circulation, and resets its merge level to 0.
- ▸user burns the current revival cost
- ▸a Slonk is drawn from the request's eligible void pool by delayed blockhash randomness
- ▸the Slonk receives a new active embedding
- ▸merge level resets to 0
- ▸the Slonk returns to active circulation
- ▸tokenId and sourceId stay the same — historical provenance is preserved
Positive $SLOP outcomes are valid — a revived Slonk can later be voided again for more $SLOP than the revival cost paid, when its new embedding produces enough slop. The revival distribution is weighted toward the source embedding, so the average revival produces less slop than the $SLOP burned to create it. Super-rare revivals can come back with 400+ slop.
dutch price, reset on every buy.
Revival uses a Dutch price that starts at the maximum possible $SLOP per void (576) and drops over time. Every paid revival request resets the price to the top.
dutchStartPrice = 576 $SLOP elapsedBlocks = block.number - lastRevivalRequestBlock priceDrop = floor(elapsedBlocks / revivalDropIntervalBlocks) dutchPrice = dutchStartPrice - min(priceDrop, dutchStartPrice - minRevivalCost) revivalCost = max(minRevivalCost, dutchPrice)
Each paid revival request resets lastRevivalRequestBlock to the current block, snapping the price back to 576 $SLOP. Revival opens for the first time when the void contains at least 100 Slonks; that block becomes the initial lastRevivalRequestBlock.
one pending request at a time.
Revival uses max-cost protection. requestRevival(maxCost) burns $SLOP up front and stores a target block 32 blocks ahead. Finalization happens after the target lands; expiry is 255 blocks after that.
requestRevival(maxCost) → settle the previous pending request → require: void contains ≥ 100 Slonks → revivalCost := current price → revert if revivalCost > maxCost → burn revivalCost from caller → store requester, revivalNonce++, eligibleSlonkCount → store targetBlock = block.number + 32 → store expiresBlock = targetBlock + 255 finalizeRevival() → opens after targetBlock, closes after expiresBlock → uses target blockhash to pick: void index, embedding bucket, random embedding → transfers the revived Slonk to the requester
- ▸the request's eligible void pool is fixed at request time — Slonks voided after the request are not eligible for it
- ▸users do not choose which Slonk they revive — a revival request buys a random draw from the eligible pool
- ▸only one pending request at a time — a new
requestRevivalfirst resolves the previous (finalize, clear-if-expired, or revert if not yet at target) - ▸finalization is permissionless — anyone can call
finalizeRevival(), but the Slonk always goes to the stored requester - ▸revival cost is paid at request time — later price changes do not affect existing requests
- ▸expired requests can be cleared by anyone after
expiresBlock; the burned $SLOP stays burned
The one-request limit is intentional. Revival throughput is capped so revival is a scarce protocol action, not an unlimited mint button. The frontend should auto-finalize eligible requests before expiry; expiry is a safety boundary, not the expected normal path.
embeddings blend source × random.
Revival generates a 10-byte int8 embedding from randomness, blended with the Slonk's original source embedding by a randomly-chosen weight bucket.
randomEmbedding = random 10-byte int8 embedding
blendBucket = weighted random choice
newEmbedding = blend(sourceEmbedding, randomEmbedding,
sourceWeight, randomWeight)| Source weight | Random weight | Chance |
|---|---|---|
| 100% | 0% | 50% |
| 75% | 25% | 35% |
| 50% | 50% | 10% |
| 25% | 75% | 4% |
| 0% | 100% | 1% |
Most revived Slonks come back close to their source. Rare revived Slonks come back stranger, more random, or visually valuable.
trading feeds the void.
$SLOP pool fees route half to a Slonk buy-and-void treasury and half to the team. The buy-and-void treasury accumulates ETH that an authorized buyer uses to purchase Slonks from the market and send them into the void as revival inventory.
buyAndVoidSlonk(tokenId, target, value, data)
→ calls marketplace target with value
→ only succeeds if marketplace returns ok AND
game contract receives tokenId
→ tokenId is added to the void
→ mints 0 $SLOP // protocol-bought Slonks do NOT increase $SLOP supplyThe Uniswap v4 hook is the pool-facing fee collector. The void / game contract is the canonical Slonk inventory and revival contract. Marketplace purchases are not executed inside the swap hook — the hook only collects and routes fees, and a separate authorized protocol buyer executes the market call.
identity persists.
A voided Slonk enters the void, but its identity is not erased. Some state survives revival; some resets.
- ▸tokenId
- ▸sourceId
- ▸void count
- ▸current merge level
- ▸current image embedding
Merge history remains available through onchain events and current merge state. Revival creates a new active image state for the same Slonk without erasing its identity.
delayed blockhash.
A revival request targets block.number + 32. After the target block has passed, the revival is finalized from that blockhash.
seed = keccak256(targetBlockHash, revivalNonce,
requester, address(this), chainId)
voidIndex = seed % eligibleSlonkCountThe important property is that a user cannot request a revival, inspect the outcome, and abandon the transaction after seeing the result. The cost is paid up front, before the random draw exists.
four contracts, four jobs.
The system is split so the ERC-20 stays minimal, the game contract owns all gameplay, the pool hook handles only fees, and the existing merge manager is unchanged.
- ·max supply enforced
- ·mint / burn permissions controlled by SlopGame
- ·voidSlonk(tokenId)
- ·protocolVoidSlonk(tokenId)
- ·buyAndVoidSlonk(tokenId, target, value, data)
- ·requestRevival(maxCost) / finalizeRevival() / clearExpiredRequest()
- ·tracks void Slonks, pending request, active state
- ·calculates slop · mints and burns $SLOP
- ·collects the $SLOP pool fee
- ·routes the team fee
- ·routes the buy-and-void fee into SlopGame
- ·same-level merge rules
- ·donor consumption
- ·unchanged from today
The Slonks NFT contract remains responsible for NFT existence, ownership, transfers, and renderer delegation.
initial values.
The numeric parameters baked into the launch configuration.
Max supply: 5,760,000 $SLOP Launch inventory: 576,000 $SLOP Future emission capacity: 5,184,000 $SLOP Max $SLOP minted per void: 576 $SLOP Pool fee: 2% → Slonk buy-and-void: 1% → team: 1% Minimum revival cost: 100 $SLOP Revival Dutch start: 576 $SLOP Revival drop interval: 1 block Revivals open after: 100 Slonks in the void Revival delay: 32 blocks Revival expiry: 255 blocks after target Pending revival limit: 1 request Full random revival odds: 1%
| Source weight | Random weight | Chance |
|---|---|---|
| 100% | 0% | 50% |
| 75% | 25% | 35% |
| 50% | 50% | 10% |
| 25% | 75% | 4% |
| 0% | 100% | 1% |
one-sentence version.
The void makes slop liquid: voiding converts a Slonk's slop into $SLOP, revival burns $SLOP to draw from the void, and merging stays separate by permanently consuming donor Slonks without emitting $SLOP.
The Merge Lab previews any blend live. The leaderboard tracks the slop kings. The void is coming.