Method

What is measured,
and what would break it

Every number on this site comes from one recorded stream of pump.fun launches, one perceptual hash, and one threshold. All three can be wrong in ways that would make the finding look bigger than it is. This page is the list of those ways and what each one measures out at.

1 · The corpus

The feed cannot be walked backwards, so the corpus is recorded forwards

pump.fun's launch feed pages back about 2,100 rows and then stops returning anything. At the current mint rate that is roughly the last 1.1 hours. Measured on 25 Aug 2026 against all three sort orders the API accepts — created_timestamp, market_cap, last_trade_timestamp — every one dies between offset 1,000 and 3,000. There is no query that reaches an older cohort.

So an aged cohort cannot be fetched. It has to be recorded off the live feed as it happens, which is what tools/record.mjs does: it walks the feed every 15 minutes against a window that holds an hour, so consecutive passes overlap roughly four-fold and coverage is contiguous by construction. MintMark hit the same wall and reached the same design; this is inherited, not invented.

That contiguity is load-bearing rather than tidy. The whole finding is a repeat rate over a lookback window, and that arithmetic assumes there are no holes in the past it looks back into. A coin scored against a stretch that was never watched would have its reuse read as a first use, and the rate would come out lower than it is with nothing on the site catching it.

Holes do happen. The recorder is a background agent on a real machine, and a machine that sleeps takes it down — while pump.fun's feed only reaches back an hour, so anything longer than that is gone for good. The first version of the build gate simply refused to publish whenever it found a gap, which sounds strict and is useless: one overnight sleep would have frozen the site permanently.

So the recording is treated as segments. A gap does not invalidate the data on either side of it — it only means you cannot look back across it. Each coin is scored against its own unbroken segment, and a coin whose lookback window would reach into a gap is dropped from that point on the curve rather than counted. What tools/validate.mjs checks is therefore the thing that actually matters: enough continuously-observed time, and a longest segment long enough to give the curve some reach. The header above prints observed time, not wall-clock span, and names every gap.

2 · The hash

How two pictures are decided to be the same picture

Each image is fetched at 128px from pump.fun's own CDN, converted to greyscale, box-filtered to a 32×32 grid, and run through a 2-D DCT-II. The 64 lowest-frequency AC coefficients — a zigzag prefix, with DC dropped — are thresholded at their median to give a 64-bit code. Two coins wear the same picture when their codes are within n bits, and n is the slider on the front page.

Three choices there are worth stating because each one changes what "same" means. Aspect ratio is not preserved: a wide banner and a square crop of that same banner get different codes, which is the right answer for a project about what a coin is wearing. Alpha is composited onto white, on both sides, because a sticker on white and the same sticker on black are different pictures to a DCT. Luma only, so a recolour of a picture still counts as that picture — the site says when a match is a recolour rather than quietly hiding it.

Because the threshold is the median of the 64 coefficients, every code has exactly 32 bits set. That is a useful invariant: any code that breaks it means tied DCT coefficients, which means a synthetic or degenerate image, and the build gate checks for it.

3 · Instrument checks

Five ways this could be lying, and what each measures

Run by tools/verify-hash.mjs against real corpus images, not synthetic ones. tools/validate.mjs blocks a publish if any of them regresses.

4 · The null

How often two unrelated pictures collide anyway

Pick two coins at random and measure the distance between their codes. If that happened anywhere near as often as the measured reuse rate, the finding would be chance.

5 · The trap

The metric that was nearly the headline, and why it is not

The first version of this site led with a single number: the share of launches in the recorded window that reuse a picture. It came out around 50%, it was arresting, and it was worthless — because it is a property of the recording rather than of pump.fun. The same corpus scored over a one-minute lookback gives a much smaller number, and over an hour a much larger one, and it is still climbing at the edge of the data. A longer recording would have produced a bigger headline out of identical behaviour.

That is the same mistake Halflife made, where a ten-minute activity window produced a ten-minute half-life; the real answer there was three minutes. It is the eighth time in this family of sites that a metric turned out to be tracking its own threshold rather than its subject, and by now the tell is reliable: the wrong version always flatters the thesis.

So the site leads with the whole curve, every quoted figure carries its lookback, and the headline uses sixty seconds because a one-minute window is too short for window length to inflate it much.

6 · Limits

What this does not measure

  • A wallet is not a person. The split between "one wallet reusing its own picture" and "a picture crossing wallets" is exactly that — wallets. A fresh wallet costs a fraction of a cent, so the crossed-wallet figure is an upper bound on how much of the reuse is people rather than software. In the recorded window the same pairs of wallets mostly do not keep turning up together on different pictures, which is evidence against a small coordinated group and no evidence at all against many disposable ones.
  • Unreadable images are not spread evenly. Coins whose picture is hosted on IPFS almost always resolve. Coins that link a picture directly from somewhere else fail far more often, because those links rot. Those coins are missing from the corpus and they are not a random sample of it — the exact rates are in the header above.
  • Only what was recorded can match. A coin whose picture was last used three hours before the recording started reads as a first use. Every figure here is a floor.
  • Byte identity is partly circular. When two coins point at the same IPFS CID, fetching both returns the same bytes by construction. IPFS is content-addressed, so an identical CID does genuinely mean identical content — but the SHA-256 in the record adds no independent confirmation in that case. It earns its place only for the coins whose pictures came from somewhere else.
  • The outcome test is weakly powered. Holding the picture fixed and asking whether the first coin did best is the right comparison, but almost nothing in an ordinary hour goes anywhere, so there is very little for the test to find. It is reported as the null it is.
  • A perfectly uniform image would break the hash. Flat colour gives all-zero AC coefficients, and the code would then be decided by floating-point residue rather than by the picture. No such image is in the corpus — the build gate checks — but the failure mode is real and it would collapse every blank picture into one false cluster.

7 · Reproducing it

Everything regenerates from four commands

No build step, no package manager, no dependencies outside Node and macOS's sips.

  • node tools/record.mjs — walk the live feed, fetch and hash every new coin's picture, append to data/raw/coins.jsonl
  • node tools/follow.mjs — read the cohort's market caps back through the batch endpoint
  • node tools/verify-hash.mjs — the five instrument checks
  • node tools/build.mjs && node tools/validate.mjs — write what the page reads, then refuse to publish it if anything above regressed

The WebAssembly is regenerated the same way: node tools/emit-wasm.mjs writes wasm/hamming.wasm byte by byte and verifies its output against a JavaScript reference on random problems first. There is no toolchain to install and nothing committed that cannot be rebuilt from source in this repository.