Introduction
token22 starts from one rule: a coin isn't real until Bitcoin has seen it. Bitcoin blocks prove themselves, since each one carries the work that made it. Tokens on Solana carry nothing. token22 fixes that by binding coins to real Bitcoin blocks with proof-of-work, and keeping the books on Solana.
There are two ways a coin gets proven. New coins can be launched on the launchpad, already stamped. Coins that already exist sit on the Unstamped Board until someone pays their hash on the prover, and that person is paid in $T22.
Where token22 comes from
In a 2022 thread on r/solana about Solana's new Token22 program, co-founder Anatoly Yakovenko wrote: “It's very possible that the next version of token ends up being built by someone outside of Labs.” (the comment on Reddit). token22 started from that line: a token standard from outside Labs, where a coin has to carry real Bitcoin proof-of-work to count.
token22 is inspired by that comment only. It is not affiliated with or endorsed by Anatoly Yakovenko, Solana Labs or the Solana Foundation.
The Unstamped Board
Every SPL token owes Bitcoin one hash from the moment it is minted. The ledger is where that debt is written down. Anyone can file any mint, which creates a ledger entry marked UNPROVEN with hash_owed = 1. When someone pays the hash, the entry flips to PROVEN and records the Bitcoin block, the nonce and the proof hash.
A coin can only be proven once. After that, the entry points at its Bitcoin block forever.
Launch status
The token22 program isn't deployed yet and $T22 has no mint address, so the ledger counters read zero and the prover can't submit. The launchpad is different: it works today, by deploying through pump.fun. Launches are real mainnet transactions that spend real SOL.
Anyone selling $T22 before a mint address appears on this site is not token22.
Launching a coin
Until the program is live, the launchpad deploys real coins on pump.fun and writes the Bitcoin stamp into each coin's metadata.
- Run the launch server on your computer: double-click start.bat (Windows) or run node server.js, then open http://localhost:3000/launch.html. It needs Node.js 18 or newer.
- Fill in a name, ticker, description, image, links and an optional dev buy. pump.fun coins have a fixed 1,000,000,000 supply.
- Your browser makes a fresh mint keypair, pulls the current Bitcoin tip and checks its header, then mines a stamp bound to the new mint and your wallet.
- The image and metadata go to pump.fun's IPFS, with the stamp line added to the description. PumpPortal builds the create transaction.
- The mint key signs in your browser and your wallet signs the rest. The server only relays; it never sees a private key.
- When the transaction confirms you get links to the coin on pump.fun and Solscan.
Optional settings for the server: SOLANA_RPC_URL (defaults to the public mainnet endpoint, which is rate-limited), BTC_ESPLORA_URL (defaults to mempool.space) and PORT.
Birth stamps don't pay $T22. If they did, launching junk coins would be a cheaper way to farm rewards than paying real debts. Once the program is live, launch_stamped will do all of this on-chain in one instruction.
Proving an old coin
Paste any mint into the prover. If nobody has filed it yet, the same transaction files it. Your machine finds a proof against one of the six newest relayed Bitcoin blocks, the program checks it, the coin is marked PROVEN, and $T22 is minted to your wallet.
The proof includes your wallet address. If someone copies your nonce out of a pending transaction, the hash comes out different for their wallet and the program rejects it with ProofMismatch.
$T22 rewards
$T22 has no presale, no team allocation and no admin mint. Its mint authority is a program address, and the only instruction that signs with it is prove. Every unit in existence has a proof receipt behind it.
| Bitcoin era | Bitcoin heights | $T22 per proof |
|---|---|---|
| 0 | 0 – 209,999 | 50 |
| 1 | 210,000 – 419,999 | 25 |
| 2 | 420,000 – 629,999 | 12.5 |
| 3 | 630,000 – 839,999 | 6.25 |
| 4 (today) | 840,000 – 1,049,999 | 3.125 |
| 5 | 1,050,000 – 1,259,999 | 1.5625 |
Each Bitcoin block can back at most 21 proofs or stamps, so issuance can't outrun Bitcoin's pace.
The Bitcoin relay
Anyone can submit the next Bitcoin block header to relay_header. The program accepts it only if:
- it is exactly 80 bytes;
sha256d(header)is at or below the target encoded in itsbits;- its
prev_blockequals the hash of the current relay tip; - its timestamp isn't more than two hours before its parent's.
Each accepted header becomes a BtcAnchor account. The poc relay command fetches headers from any Esplora-compatible API, checks the work locally, and submits them in order.
# follow Bitcoin's tip, six blocks at a time
poc relay --api https://your-esplora-endpoint/api --max 6
The proof puzzle
Proofs and stamps solve the same puzzle. The input is 120 bytes:
message = "TOKEN22:STAMP:v1" // 16 bytes, domain tag || anchor // 32 bytes, Bitcoin block hash (internal order) || mint // 32 bytes, the coin || prover // 32 bytes, the wallet doing the work || nonce_le // 8 bytes, u64 little-endian proof = sha256(sha256(message)) valid = leading_zero_bits(proof) >= required_zero_bits(anchor.bits)
Zero bits are counted the way Bitcoin explorers display a hash, from the last byte backwards. The first 64 bytes never change during a search, so the prover compresses them once (the midstate) and each nonce costs three SHA-256 compressions instead of four. The page's prover, the SDK, the CLI and the Rust program all produce byte-identical hashes; the test suites check that against the same fixtures.
Difficulty Mirror
required_zero_bits = clamp(anchor_target_zero_bits / 4, 16, 32)
A 2009 Bitcoin block has a target with 32 leading zero bits, so a proof against it needs the minimum of 16 (about 65,000 hashes). A recent block has around 78, so a proof needs 19 (about 524,000 hashes). Because only the six newest relayed blocks can be used, proofs get harder exactly when Bitcoin does.
Program interface
| Instruction | Who | What it does |
|---|---|---|
| initialize | deployer, once | Creates the config, the $T22 mint and a checkpoint Bitcoin header. |
| relay_header | anyone | Adds the next Bitcoin header after checking work and linkage. |
| file_unproven | anyone | Puts a mint on the Unstamped Board. It owes one hash. |
| prove | anyone | Verifies a proof, marks the coin PROVEN, writes a receipt and mints $T22. |
| launch_stamped | anyone | Verifies a birth stamp, creates the coin with fixed supply and marks it PROVEN. |
| set_paused | admin | Stops relaying, proving and launching. Filing stays open. |
| transfer_authority | admin | Moves the admin key, or burns it by passing none. |
Errors
BrokenLink, InsufficientWork, TimeTravel, StaleAnchor, AnchorExhausted, AlreadyProven, ProofMismatch, NotEnoughZeros, RewardExhausted, BadMetadata, ZeroSupply, Paused, Unauthorized.
Accounts
| Account | Seeds | Holds |
|---|---|---|
| Config | ["config"] | Relay tip, counters, admin, pause flag. |
| $T22 mint | ["poc-mint"] | 9 decimals; authority is the config PDA. |
| BtcAnchor | ["anchor", block_hash] | One verified Bitcoin header and how many proofs it has backed. |
| LedgerEntry | ["ledger", mint] | UNPROVEN or PROVEN, and which Bitcoin block proved it. |
| ProofReceipt | ["receipt", proof_hash] | The nonce, zeros and reward. One per proof hash, so work is never paid twice. |
| Launch | ["launch", mint] | Name, ticker, URI, supply and birth stamp of a launchpad coin. |
SDK and CLI
The TypeScript SDK builds every instruction by hand (no IDL step), decodes every account, and ships the same Bitcoin and proof code the site uses.
import { ProofOfCoinClient } from "@proof-of-coin/sdk"; const poc = new ProofOfCoinClient(connection); // launch a coin that's born proven const { mint, stamp } = await poc.launchStamped(wallet, { name: "Stamped Dog", symbol: "SDOG", supply: 1_000_000_000_000_000n, }); // pay an old coin's hash and get $T22 await poc.proveCoin(wallet, someMint); // PROVEN, UNPROVEN, or not filed const verdict = await poc.check(someMint);
# the same from a terminal, hashing on every core poc launch --name "Stamped Dog" --symbol SDOG --supply 1000000000 poc prove --mint So11111111111111111111111111111111111111112 --threads 8 poc status
Limits and honesty
- It's a meme with real maths. The hashing is real and verifiable. The idea that a coin "owes" Bitcoin anything is the joke.
- The relay is a light client, not a full node. It checks each header's work and that it links to the last one, but not Bitcoin's difficulty retarget rules, and it trusts the checkpoint it starts from. Somebody with enough hash power could feed it a private chain. A production version would validate retargets and track cumulative work.
- Not audited. The program has unit tests and an integration test against a local validator. It has not been audited.
- Proofs say nothing about a coin's quality. PROVEN means someone did work tied to a Bitcoin block. It doesn't mean the coin is good, safe or worth anything.
Questions
Does this put anything on the Bitcoin blockchain?
Can I prove my own coin to get $T22?
Why can't I prove against the genesis block once it's live?
Why does my browser get hot?
When is launch?
References
- Bitcoin: A Peer-to-Peer Electronic Cash System (2008)
- “Bitcoin minting is thermodynamically perverse”, bitcointalk.org forum thread, August 2010
- Bitcoin block header reference
- Anchor framework
- SPL Token program