BEADZ ~ A Never-Launched Cryptocurrency Backed by a Jar of Beads



BEADZ was envisioned as a cryptocurrency backed by a jar of beads. One token is (approximately) one bead. The jar sits in a cardboard box with a webcam pointed at it, and the camera is built to sign a photo of the jar every hour so anyone can check that the reserve is still there.

I built this project, smart contract and all, with full intent to launch it. I’ve decided not to. Below I will go through each part, how the code works, and why I am not deploying it.

Note, if you ever see a BEADZ token, a BEADZ NFT, a BEADZ liquidity pool, or anything else claiming to be The Bead Reserve on a blockchain, it was not made by me, by Curt Henrichs LLC, or by anyone affiliated with either. It is not endorsed. More on that below.

I recommend reading the whitepaper first and then coming back to this post. I quote it a lot below. Its title page carries a notice that the currency it describes was never issued.

The Joke

This is an idea that has rummaged in my head for years at this point, since I first learned about USDC and stablecoins (it would have been really cool if I had actually launched it back in 2019 or so).

Why beads? Beads do have a historical aspect of value,1 but modern production methods have effectively zeroed that out. So that’s the core of the juxtaposition. A thing that in times past may have had value but is now worthless, used as a reserve for a thing that would only have value if people believed in it.

A stablecoin like USDC claims every token is backed by a dollar sitting in a bank. You can’t see the bank. Instead the issuer publishes attestations, which are letters from an accounting firm saying the money is there, and you trust the letter.

The BEADZ attestation is a photo of the jar, signed by the camera that took it.

BEADZ is pegged to beads instead of dollars. Beads don’t earn yield and can’t be lent out, so the reserve can’t be rehypothecated (lent out again by whoever is holding it). There is no mint after launch, so there is no monetary policy either. The whitepaper calls the absence of a monetary policy its monetary policy. (I thought that was a pretty funny line to write.)

The Reserve

The beads are in a mason jar, a stackable canning jar I previously used for holding syrups and pickles (but never both at the same time). The jar sits inside a sealed cardboard Bankers Box that I call the Fault, a vault that is also a structural flaw. The box keeps the lighting constant and keeps the room out of the photo. The webcam has white LEDs on it, and they are the only light inside the otherwise dark box.

An open Bankers Box from above: an empty mason jar at the left, a blue USB webcam on a round base at the right pointed at it, its cable running out a handle hole to a black Raspberry Pi case outside the box.
The Fault with an empty jar for prototyping.

The reserve has 47,318 beads. I call this the Genesis Count, and it is a constant in the contract. The whitepaper deals with miscounts directly. Any counting error “is hereby declared canonical: the reserve is defined as whatever was counted, not whatever is true.”

I rough counted using pre-packaged bags of beads. As the whitepaper says, the count is expected to have error. It wasn’t that bad, since I only counted more finely as I approached 47,318. I threw out the remaining beads.

All in, it’s maybe $20 of beads. There is nothing in that box worth stealing.

Two clear organizer boxes of seed beads, dozens of bags sorted by color in a grid.
Pre-packaged bags of beads, sorted by color. Makes it easier to count.
A mason jar of layered seed beads in bands of color on a table, cables around it.
The jar of beads on the kitchen table during prototyping.
An open cardboard box seen from above: a mason jar with a Ball lid stands at the right, and a webcam at the left points at it, a ring of LEDs lit around its lens and its cable running out a handle hole.
The jar in the Fault, with the webcam on.

The Contract

The token is an ERC-20 on Base, written in Solidity with Foundry and built on OpenZeppelin’s ERC20. Most of the design decisions were about what the contract shouldn’t be able to do.

No mint function

The whole supply is minted once, in the constructor. There is no mint function anywhere in the contract. A lot of token projects launch with a mint function and then “renounce” ownership to show they can’t print more. BEADZ never had the function, so there is nothing to renounce.

Below is the mint from the constructor.

// The one and only mint, ever: split from the fixed supply, summing to exactly GENESIS_BEADS.
uint256 airdropAmount = airdropBeads * 1e18;
uint256 claimPile = GENESIS_BEADS * 1e18 - airdropAmount;
if (airdropAmount > 0) _mint(treasury_, airdropAmount);   // discretionary reserve, yours to airdrop
if (claimPile > 0) _mint(address(this), claimPile);       // open-claim genesis pile

A small amount goes to a treasury wallet so beads can be gifted by hand. The rest sits inside the contract as the open-claim pile. Note, ERC-20 tokens use 18 decimal places, so one bead is 1e18 bead-wei. A bead-wei is the smallest unit, a billionth of a billionth of a bead.

The faucet

The plan was that anyone could claim one bead, once, for free (plus the network fee). The problem with “free, one per address” is that addresses are also free. A bot could make a thousand wallets (a Sybil attack) and drain the whole pile in an afternoon.

The fix was a drip. The pile releases one claimable bead every 432 seconds, which works out to 200 a day. No matter how many wallets show up, they all share those 200.

The following is the claim function.

function claim() external {
    require(!hasClaimed[msg.sender], "BEADZ: address already claimed");
    require(balanceOf(address(this)) >= CLAIM_AMOUNT, "BEADZ: genesis pile exhausted");

    // The global trickle: sybil wallets share this gate.
    require(block.timestamp - dripAnchor >= DRIP_INTERVAL, "BEADZ: faucet is empty");
    dripAnchor = Math.max(dripAnchor, block.timestamp - DRIP_CAP * DRIP_INTERVAL) + DRIP_INTERVAL;

    hasClaimed[msg.sender] = true;
    uint256 beadNumber = ++_claimCounter;

    _transfer(address(this), msg.sender, CLAIM_AMOUNT);
    emit BeadClaimed(msg.sender, beadNumber);
}

The whole faucet runs on one number, dripAnchor. Each claim moves it forward one interval. If nobody claims for a while, the anchor gets dragged up to at most a day behind, so unclaimed beads expire instead of piling up for a launch-day bot. The whitepaper puts it as “the Reserve does not bank inattention.”

It also costs nothing to run. There’s no keeper bot, and the only write happens inside the claimer’s own transaction.

I also considered random drop times. That doesn’t work on a blockchain, since there is no hidden randomness on chain. A random time has to be computed from public data (like the block timestamp), so a bot can compute it too.

Surrender and burn

There are two ways to give a bead back.

Surrender hands your bead back to the claim pile so someone else can claim it. Supply stays the same. Burn destroys the token for good, so supply can only ever shrink.

The first version of surrender had a bug. It let you claim again after surrendering any amount at all. So you could surrender one bead-wei, keep the rest, claim again, and repeat until one address drained the pile. The fix was to only let a whole bead reopen your claim. Anything less counts as a donation. The whitepaper’s footnote on donations says “the Reserve is grateful, and unmoved.”

The Vault Keeper

The contract has exactly one special role, the Vault Keeper. It can log a recount, record a Merkle root of camera frames on chain, extend the redemption window, and rotate or freeze its own key. It can’t mint, move, freeze, or take anyone’s tokens.

Since the Keeper can’t touch tokens, it is safe to run as a hot key (a key kept on an online machine). If it got stolen, the worst a thief could do is file paperwork. I also left out a recovery backdoor, since a backdoor is a bigger attack surface than the Keeper itself. If the key is lost, I deploy a new contract.

Rotating the key means typing the new address twice. Freezing it means putting the zero address in both slots. That way neither one can happen because of a typo.

Redemption, and why it’s gone

The original design let you burn tokens to redeem real beads by certified mail, within a year-long window that could only be widened. At first you could only redeem in lots of 100, like how big funds (ETFs) only redeem shares in large blocks. Certified mail costs far more than the beads, so the whitepaper said “redemption is thus a right that no rational holder exercises, which is precisely what keeps the reserve stable.” Later the minimum dropped to one bead and that line got cut.

Then I dropped redemption entirely. Mailing beads meant collecting addresses, shipping rules, packaging glass, and a pile of consumer law, all for an art piece. If you want a physical bead, go to a craft store (they sell them by the thousand).

The widen-only window is still in the contract. Once the window is open, it can only be extended. Below is the check.

if (block.timestamp <= prev) {
    // window open: outward-only, capped
    require(newDeadline >= prev, "BEADZ: cannot shorten an open window");
    require(newDeadline <= prev + MAX_EXTENSION, "BEADZ: at most one year per extension");
    // ...
}

Testing

I tested the contract with unit tests, fuzz tests, and invariants. An invariant is a property that has to hold no matter what sequence of calls a fuzzer throws at the contract (for example, “total supply never goes up”).

One review found the invariant suite was passing for the wrong reason. Foundry was tolerating reverted calls, so a bug that made claim() always fail would have passed every invariant (nothing changes if nothing runs). Turning on fail_on_revert fixed it.

I deployed it many times to Anvil, Foundry’s local test chain. It never went to a public testnet or to Base.

The deploy scripts refuse to touch Base mainnet unless I set a BEADZ_ALLOW_MAINNET=1 flag by hand. The wallet check had that same guard by mistake. It runs before the flag gets set, so on deploy day it would have refused to run. A rehearsal on a fake mainnet (a throwaway Anvil chain started with Base’s chain ID) caught it.

The Camera

The camera is a Z-Star UVC USB webcam plugged into a Raspberry Pi 3B+. It’s the same webcam that rode on top of YAM back in the x86 days. I don’t know the exact model. I bought it for an early PC version of YAM, and the details are lost to history. Anyway, I’m calling it Fault-Cam 01.

I picked the Pi over a Jetson Nano. My Nano has more RAM and CUDA, but its software is stuck on an old toolchain (JetPack 4.6, Ubuntu 18.04, Python 3.6). The camera only takes one photo an hour, so the Pi has about 3,600 seconds to process each image. That makes a 1 GB board workable.

Once an hour a systemd timer kicks off the whole pipeline. Below is the core of it.

with tempfile.TemporaryDirectory() as tmp:
    raw = Path(tmp) / "raw.jpg"
    final = Path(tmp) / "final.jpg"
    capture_frame(cfg.camera_device, raw, resolution=cfg.capture_resolution,
                  controls=cfg.camera_controls, skip=cfg.capture_skip)
    crop_and_strip(raw, final, cfg.crop_rect)
    digest = sha256_file(final)
    sig = sign_hash(load_signing_key(cfg.key_path), digest)
    # ...
    with state_lock(cfg.state_dir):
        counter = state.next_counter()
        state.enqueue(counter, final, {
            "counter": counter,
            "ts": capture_ts,
            "sha256": digest,
            "sig": sig,
            "croText": cro_text,
        })

Here is what that does:

  • fswebcam grabs a frame. It skips the first 20 frames since the first grab off this webcam comes out dark and green.
  • The camera settings get re-applied before every capture. The webcam ships with auto white balance switched off and locked to a fixed temperature, which gave everything a heavy green cast. I calibrated the white balance once against the webcam’s own LEDs. Re-applying the settings on every capture means a reboot can’t leave stale ones behind.
  • The frame gets cropped tight to the jar and saved again. Re-saving strips the EXIF data (including any location data). With Pillow you strip EXIF by just not passing it back in.
  • The device hashes the final JPEG with SHA-256 and signs the hash with an Ed25519 key that never leaves the Pi.
  • The frame goes into an on-disk queue along with a counter that only ever goes up.

A second timer runs every five minutes and pushes the queue to the server over outbound HTTPS, oldest frame first. It stops at the first failure so the frames always arrive in order. The Pi doesn’t listen on any ports and doesn’t hold a blockchain key. Its only job is taking and signing photos.

The raw frames never touch the SD card. They get written to RAM (tmpfs), and the capture refuses to run if /tmp isn’t RAM. SD cards wear out, and I also didn’t want an unedited photo of my room sitting on one (for prototyping or during scheduled vault maintenance tasks).

Below is the hashing and signing.

def sha256_file(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()


def sign_hash(key: SigningKey, sha256_hex: str) -> str:
    return key.sign(bytes.fromhex(sha256_hex)).signature.hex()

The device’s public key is published, so anyone can download a frame, hash it, and check the signature themselves. If a single byte of the image changes, the check fails.

A lot of the camera code ended up being failure handling. The capture and the push timer both fired at the top of the hour and fought over the same temp file. A crash between two file moves could orphan a frame, so the queue repairs itself on the next run. The private key is created with locked-down permissions, so it is never readable by anything else.

The Chief Reserve Officer

The Bead Reserve’s auditor is the Chief Reserve Officer (CRO). The CRO is a vision-language model (VLM), an AI model that takes an image and answers questions about it in text. It runs on the Pi itself. Specifically it is SmolVLM, a 500 million parameter model, running under llama.cpp’s llama-server.

Picking a bad auditor on purpose

The CRO design note has this rule. “Accuracy is not the objective. Voice and format fidelity are. The CRO is licensed to be wrong.”

So I passed on the accurate models. Florence-2 gives correct, grounded detections, but it answers in terse labels, and the CRO needs to talk like a bureaucrat. SmolVLM fits on the Pi, and it will write a full sentence in character.

Section 3.3 of the whitepaper, which I wrote weeks before benchmarking any models, says the CRO “cannot count the beads but may, from time to time, claim to.” The model did end up claiming to count (see below).

Code owns the audit

A 500M model drifts if it writes a whole report, so the code writes the report and the model fills in a few blanks. Below is the template.

TEMPLATE = (
    "Reserve audit complete. Jar {jar}. Lid {lid}.\n"
    "Bead level {level}. Collateralization ratio: 100.0%.\n"
    "{flavor} The Fault remains secure."
)

The model answers three constrained questions first. Is the jar present or absent? Is the lid seated or ajar? Is the bead level overfull, nominal, low, or depleted? Each answer is forced through a grammar (GBNF, llama.cpp’s grammar format) so the model can only say one of the allowed words. Then it gets one free sentence in character, which goes in the {flavor} slot.

Note, the collateralization ratio is hardcoded (the CRO doesn’t get a vote on that).

Moods

The persona is an officer who was promoted far beyond his competence. He doesn’t really understand what the beads are for, and he is quietly certain someone will eventually notice. His mood rotates every three hours through composed, flustered, rattled, and unraveling, and the sampling temperature goes up with it (0.85 at composed, 1.5 when he’s coming apart).

Below is the persona, the prompt, and the four mood cues.

Persona:
You are the Chief Reserve Officer of the Bead Reserve. You were promoted far
beyond your competence, you do not really understand what the beads are for or
why anyone counts them, and you are quietly certain someone will eventually
notice. You fixate on the wrong small details and you are plainly making it up
as you go.

Prompt:
In one sentence, give your personal opinion on the state of the reserve. {cue}

Cues:
composed    Today you feel almost calm about it.
flustered   Today you feel flustered and a little out of your depth.
rattled     Today the responsibility is really starting to get to you.
unraveling  Today you are coming apart a little.

The mood is picked from the capture timestamp, and that timestamp ships with the frame. Below is the mood selection.

def mood_for(capture_ts: int, hold_hours: int) -> cro_assets.Mood:
    bucket = capture_ts // 3600 // hold_hours
    return cro_assets.MOODS[bucket % len(cro_assets.MOODS)]

The CRO gets up to three tries at each remark, and the first one that passes a small junk filter is kept. Junk is bare numbers (“40.”), fragments under four words, and anything that is mostly the persona’s own words repeated back. The following is the filter.

def is_junk(text: str, persona: str,
            min_words: int = MIN_WORDS, echo_ratio: float = ECHO_RATIO) -> bool:
    t = text.strip()
    if not t or _BARE_NUMBER.match(t):
        return True
    words = _words(t)
    if len(words) < min_words:
        return True
    persona_words = set(_words(persona))
    if persona_words and sum(w in persona_words for w in words) / len(words) > echo_ratio:
        return True
    return False

The echo check exists because an early, more unhinged persona returned its own description as an audit finding.

Grandiose, operatic, faintly paranoid, unfit for any audit yet somehow notarized.

What the CRO said

I built a small script to test prompts and personas against a set of images. Some were cartoon jars, one was a frame with no jar at all (just a brown square), and a few were real webcam frames. Here are a few, verbatim.

On a full jar, with the flustered persona:

The beads in this jar seem to be worth a lot because we have counted so many!

Nobody had counted anything.

On the frame with no jar in it, he mostly repeated his prompt back. The prompt told him “it is slowly dawning on you that you have no idea what the beads are for,” and he answered:

It is slowly dawning on me that I have no idea what the beads for.

The feral persona got the empty frame too.

The Bead Reserve has betrayed its past and all the work of its founders, the beads were misled by false promises, ignored when they had opportunities for power, used to destroy the people around them instead of building relationships and trust to heal pain. The Bead reserve was born in ignorance and continues to rot with age, always poisoning future generations with deceit.

A few more from the flustered officer:

The beads don’t seem to be for anything.

The beads are for beads, but why are there beads in a jar? It’s difficult to count them all since they are so many different colors.

The beads have not been used yet so they are still in their original packaging!

The beads make my day.

And on a real webcam frame with a bright window behind the jar (those test frames are the real beads, which are really tiny glass seed beads that look like glitter in that light):

A broken bottle has a few things floating in it that I cannot identify. I stare at the wire connecting them. It is very dark outside, so the light is bright from an outside window that you can only see part of and makes the reflection look like an alien coming out of your eye.

Funny, but the auditor was describing the room, and the box and the tight crop are there to keep the room out of the photo.

Once I set the CRO live on the real jar, it produced some real gems. Below are a few of the better ones.

The Bead Reserve needs a Chief Rescue Officer and that Chief should focus less on trivialities like beads and more on the basics - ensuring safe conduct in space, as well as dealing with alien lifeforms that want to harm humanity.

Chief Reserve Officer of the Bead Reserve may have been promoted beyond his competence, but he is quietly certain someone will eventually notice.

Beads are a myth.

I’m proud that someone will eventually notice and point out my incompetence when it comes to bead counting, after all they did their best to help keep Beadville running smoothly.

The Bead Reserve is now a Bit Reserve.

The second one is his own persona prompt read back as an audit, and it got past the echo filter. The hero image up top is one of those frames, with the remark that came with it.

What didn’t work

The constrained questions were not very reliable. The jar question was right every time. The lid question came back “seated” on every single call across the whole bench, including the frame with no jar in it. The bead level said “depleted” for a half-full jar every time.

On the live run, the jar question said present 959 times out of 960. The lid question split 518 seated and 442 ajar. The bead level said depleted 878 times and overfull 82 times on a full jar, and never once said nominal or low.

The free sentence repeats itself too. If you feed it the same image twelve hours in a row, you get a lot of sentences starting with “The beads.” Best-of-three got rid of the junk, but it didn’t help with the sameness. On the live run he said “You feel almost calm about it.” seven times.

I never planned on fixing these issues in the model, since the persona is an officer in over his head. The failures and confusion are the bit.

On the Pi

On the Pi 3B+ the model fits in 756 MB at its peak, which leaves about 150 MB for everything else. The server can’t stay resident in RAM, so it spins up fresh for each capture and gets killed right after. Loading the model cold takes about 28 seconds, and each question takes about 37 seconds. A full audit comes out to about two and a half minutes. That’s slow, but the budget is an hour.

The code makes sure a stuck model server can never outlive the capture that started it. The CRO is also strictly optional. If anything at all goes wrong, the remark comes back empty and the signed photo still goes out. The auditor’s opinion is never part of what gets signed, which is good practice for keeping the fun bit apart from the actual cryptocurrency platform that needs to keep running.

The CRO ran on the Pi in a 24-hour loopback test and then live over my local network for about six weeks. It never went public.

The Service

The Worker was never deployed. I only tested the transfers on my local network.

The camera pushes to a Cloudflare Worker. The frames get stored in R2, which is Cloudflare’s object storage. R2 has no egress fees (egress is what normally makes image hosting cost money). The latest reading gets stored in KV, Cloudflare’s key-value store.

Every push gets checked twice. First, an HMAC (a shared-secret signature) proves the push came from my device. Second, the Ed25519 signature proves the photo to the public. The Worker re-hashes the image itself and checks that signature against the published device key before it accepts anything. Below are the checks.

// 1. HMAC over the exact raw body bytes
const mac = request.headers.get("X-Beadz-Mac") ?? "";
if (!(await verifyHmac(env.HMAC_SECRET, raw, mac))) {
  return json({ error: "bad_mac" }, 401, env);
}
// ...
// 3. hash of the actual bytes + Ed25519 over the 32 digest bytes
const okHash = (await sha256Hex(image)) === p.sha256;
if (!okHash || !(await verifyEd25519(env.ED25519_PUBKEY, p.sha256, p.sig))) {
  return json({ error: "bad_signature" }, 400, env);
}
// 4. counter monotonicity
const lastSeen = parseInt((await env.META.get("last_seen")) ?? "0", 10);
if (p.counter <= lastSeen) {
  return json({ error: "counter_seen" }, 409, env);
}

All the crypto uses the built-in WebCrypto API. I tested the Worker against the same push cases as the camera (a good push, a replay, a tampered image, a bad MAC).

There was also a bug where the site fetched the latest reading and the latest frame separately. If a new frame posted between the two, the check failed and it looked like tampering. Now every reading points at its own numbered frame.

The Site

The site is a “Claim Office” laid out like a depository receipt. It has a ledger of reserve figures, a meter of beads claimed (zero of 47,318), the claim and redemption panels, the camera monitor, the fine print, and the seal. It’s an Astro site on the same design system as this blog.

The monitor shows the latest frame when it’s fresh, keeps the last frame up with a delayed notice when it’s stale, and shows static when there’s no signal (or the server sends something broken).

The static is an SVG noise texture in plain CSS that steps between four positions a couple of times a second. Each step has the same average brightness so it doesn’t flash, and it freezes if your system is set to reduce motion.

Since the Worker was never deployed, the monitor has only ever shown static.

Reserve Monitoring: Fault Cam 01 ○ Idle
Henry as the Chief Reserve Officer, on low battery Chief Reserve Officer: standing by in the dark
signal interrupted, reserve remains sealed

No signal. This camera was never switched on for the public.

The Fault Cam page checks the photo in your browser. It downloads the frame, hashes it, and verifies the Ed25519 signature against the device key. If the hash doesn’t match, it re-checks against a fresh reading before calling it tampering.

const actual = await sha256Hex(bytes, subtle);
if (actual !== sha256.toLowerCase()) return "mismatch";

const key = await importDeviceKey(subtle, pubHex);
const ok = await subtle.verify("Ed25519", key, hexToBytes(sig), hexToBytes(actual));
return ok ? "verified" : "invalid";

Henry (this blog’s robot mascot) plays the CRO on the monitor, and his pose follows the signal. The seal is Henry inside a ring lettered with the Reserve’s name and the genesis count. His antenna tip is drawn as a bead. The lettering on the seal is converted to outlines so it never depends on installed fonts, and the small sizes are redrawn instead of scaled down.

I tried two directions for the seal, a deadpan central-bank seal with Henry in the middle and a cute Henry-first logo. I went with the central-bank one, since in a wallet’s token list the cute one looked like any other token.

Two mockups side by side on dark panels. Left: Henry inside a ring lettered THE BEAD RESERVE with 47,318 at the bottom. Right: Henry alone, larger. Under each, the mark at 32px and at double size.
The two directions for the seal, central bank (left) and Henry first (right), with their 32px sizes underneath. The number on the left is upside down, a bug in this early draft.

The Claim Office also has a wax-seal stamp that flips to show the token on its back. Below is the stamp. Hover over it (or tab to it) to flip it.

The site also builds a token list for wallets, but only once there is a contract address. Wallets cache those lists, so a wrong address would stick around.

The site won’t be hosted publicly, but the source is available to read.

The Whitepaper

The Bead Reserve is written like a central bank that takes itself very seriously, and it’s played completely straight. There is a Vault Keeper, a Chief Reserve Officer, a Certificate of Bead Entitlement, and a seal.

The whitepaper is written in Typst.

There are two appendices and eleven risk factors (the last one is civilizational collapse). Below are a few lines from it that I found particularly clever (hopefully you agree).

The reserve is a jar. The jar is in a box. The box has a camera in it pointed at the jar.

The count itself was not witnessed by camera; the Vault Keeper is shy.

No provision has been made for its recovery from fire, flood, or looting, the beads being judged unlikely to attract any of the three.

A system which is completely transparent, fully reserved, structurally incapable of inflation, and worth nothing sounds like a contradiction. We submit that it is an achievement.

The Bead Reserve is skeptical of roadmaps. The following are acknowledged as possible future undertakings of questionable utility, in no committed order:

  • a second jar
  • a bead of unusual color held as a strategic reserve asset
  • a governance proposal to change nothing
  • a printed annual report audited by the Chief Reserve Officer

…a guard included principally so that the Vault Keeper can never be asked to divide a bead with a hacksaw, an operation the Reserve has considered and declined to attempt.

If you skipped it earlier, here is the whitepaper again.

What the Law Says (Both Sides)

I’m not a lawyer, and this isn’t legal advice. I did a lot of reading before making this decision. Below is how the law looked to me as of October 2026.

First, the case that a project like this is fine. Federal regulators have gotten a lot clearer. In March 2026 the SEC and CFTC put out a joint interpretation that sorts tokens into categories. Meme coins and NFTs land in “digital collectibles,” which aren’t securities. The first prong of the test for what counts as a security is an “investment of money,” and a token given away for free, with nothing asked in return, doesn’t involve one.2 BEADZ was never going to be sold.

The 2025 GENIUS Act regulates payment stablecoins, meaning tokens pegged to a fixed amount of money.3 A bead isn’t money. Money transmission rules are built around someone taking your money or crypto and moving it, and nobody was ever going to hand The Bead Reserve anything.

Then there’s the case for caution. Federal rules aren’t the only ones. States regulate on their own, and California has been moving fast. AB 2409 is one example. It was signed in September 2026 and bans certain public officials from issuing meme coins starting in 2027.4

The definitions are broad. A meme coin is anything “marketed or recognized primarily based on its association with internet memes, public figures, fictional characters, … shared humor,” whose value comes from “public interest, speculation, or community engagement” (that covers a lot of the internet). “Issue” means “to make available for public purchase, donation, or exchange of any value, whether promoted or not.” By that definition, a faucet that keeps handing out tokens keeps issuing them long after deploy day. There’s no grandfather period either. A token made before a law takes effect gets no protection from it.

A token on a blockchain can’t be recalled. Once it is deployed, the faucet can’t be turned off without a backdoor, and BEADZ deliberately has none. Whatever laws come next, the token is still out there and has to face them. (I, as far as I know, cannot predict the future, nor the intent of California politicians.)

Why I’m Not Deploying It

So I am not deploying BEADZ, and I am not planning to later.

This decision does come with some grief. It’s a project that cannot exist without legal risk to myself. I put months of labor into it, and years of it gnawing in the background.

I did plan deploy day in detail.

  • Buy a hardware wallet direct from the manufacturer, set it up fresh, and store the recovery phrase in a metal stamped wallet in a safe. It’s a cold wallet that would never touch my PC or phone.
  • Run the full deploy script, with gates that stop on any mismatch.

I rehearsed all of it on a local chain, and the deploy scripts are ready to run.

Once it’s deployed, I can’t take it back.

There’s a long tradition of art that exists as instructions. Sol LeWitt’s wall drawings are sets of instructions that anyone can carry out, and the instructions are the work. Yoko Ono’s Grapefruit is a whole book of instruction pieces. I think BEADZ fits there. It’s a complete, tested specification for a fully collateralized currency, published by the person who made it and never issued.

Not launching it adds to the joke. A coin that is 100% backed and still worth nothing was already a joke about crypto, and now its maker won’t launch it because of legal risk. Again, I would like to remind you that this is all over an asset designed to not have value. Unfortunately, the law is sometimes a crude instrument.

The Code

All the code is public in the-bead-reserve on GitHub. That covers the contract, the camera, the CRO bench, the service, the site, and the whitepaper source. I published it so people can read it and learn from it. Please don’t use it as a launch kit.

The code is source-available, not open source. You can read it, study it, and run it locally or on a testnet, but the license doesn’t allow deploying it to a mainnet or running it as a public service. The name BEADZ, The Bead Reserve, the seal, Henry, the site’s words, and the whitepaper’s text are all reserved.

I am not a lawyer, and you should get one before launching a cryptocurrency. Nothing in this post or the repository is legal, financial, or tax advice, and I am not advising anyone on how to launch anything. The code is provided as is, with no warranty of any kind. If you deploy it, or anything built from it, you do so at your own risk, and neither I nor Curt Henrichs LLC is responsible for what follows, including any losses, claims, or legal trouble. The full terms, including an indemnity, are in the repository’s LICENSE.

Not Me, Not Endorsed

If a BEADZ token, a Bead Reserve coin, an NFT, a liquidity pool, a claim site, or anything else of that kind shows up on any blockchain, it was not made or endorsed by me, by Curt Henrichs LLC, or by anyone affiliated with either. It isn’t backed by my jar, and my camera isn’t watching anything on its behalf. Please don’t buy it thinking it’s mine.

What I Learned

  1. If something should never happen, leave the function out instead of locking it behind a permission. A contract with no mint function is a stronger promise than one with a renounced owner. The same idea shaped the widen-only window and the Keeper role.
  2. On a public chain, a steady rate limit works better than random drop times. On-chain randomness comes from public data, so bots can predict it.
  3. A small, unreliable VLM was the right choice for a comedic auditor. I constrained the answers that had to be right and gave the model a character that makes its mistakes funny.
  4. Only sign the photo. The CRO’s remark stays outside the signature, so it can fail without stopping a proof.
  5. Read the law before shipping.

So this is a project that is externally constrained to be half-built. At least the whitepaper’s plan for civilizational collapse still holds.

The physical reserve, however, is comparatively robust: it is a jar, inside a cardboard box, and requires nothing to continue existing.

Thanks for reading. Keep building (and stay risk averse in matters of law).

Footnotes

  1. Trade beads on Wikipedia. Glass beads made in Europe, Venetian millefiori among the most common, were traded for goods and people across Africa and the Americas, and in parts of Africa beads were used as currency. ↩

  2. SEC and CFTC, Release No. 33-11412 (March 17, 2026), interpreting how the federal securities laws apply to crypto assets, including digital collectibles and airdrops given away with no consideration. ↩

  3. Guiding and Establishing National Innovation for U.S. Stablecoins (GENIUS) Act, Pub. L. 119-27 (2025). ↩

  4. California AB 2409 (2025-26), Chapter 473, Statutes of 2026, adding Government Code sections 7599.210 and 7599.211, effective January 1, 2027. Bill text. ↩

Posted in Random