docs
everything the site claims, with the numbers from the program and the addresses to check. long on purpose.
how it works
- launch. anyone launches a coin on /launch. under the hood it is a normal raydium launchlab pool that carries the hashpay platform id, quoted in sol. it trades from second one on raydium like any launchlab coin. nothing of ours sits in the trade path.
- trade. every trade pays launchlab's fees. the hashpay platform fee (1%) accrues in launchlab's platform fee vault, which only our program's treasury pda can claim. the launcher's creator fee (0.5%) is paid to the launcher by launchlab itself.
- register. anyone calls
register_coin(mint). the program reads the pool, checks it carries our platform id, creates the coin'sCoinaccount and its cbbtc pot, and opens block 0 withchallenge = keccak(mint || block || slot_hash). - mine. open the coin page, paste any solana address (or connect a wallet), hit mine. your browser hashes
keccak256(challenge || address || nonce)and sends every nonce that beats the coin's target. no money in. the address is inside the hash, so nobody can redirect your credit. - the block. every 600 seconds the block closes (anyone can crank it; the keeper does). the program takes a sixth of the coin's unallocated pot, splits it over the block's shares, retargets the difficulty for the next block and opens it with a fresh challenge.
- the payout. a miner's sats settle on their next submit, or when anyone calls
payoutfor them. above the minimum (2,000 sats) the cbbtc is pushed to the address; below it, it waits and the beneficiary canclaimwith a wallet at any time. one block, one coinbase transaction, linked on the coin page. - the pot. the public keeper calls
sweep(claims the platform fee as wsol into the treasury),convert(80% of it to cbbtc, into that coin's pot) andconvert_burn(20% buys $hashpay and burns it in the same instruction). every transaction is on the ledger.
fees
per child coin, per trade. rates in launchlab's units of 1/1,000,000.
| who | rate | mechanism |
|---|---|---|
| raydium protocol | launchlab's global trade_fee_rate | launchlab, not ours |
| hashpay platform fee | fee_rate = 10000 (1%) | accrues in the platform fee vault pda(platform_config, quote_mint), claimable only by the treasury pda |
| launcher | creator_fee_rate = 5000 (0.5%, launchlab's cap) | paid to the pool creator by launchlab |
of the 1%: 80% becomes cbbtc in that coin's pot (pot_bps = 8000), 20% buys and burns $hashpay (burn_bps = 2000). the split is in the config account and every conversion is a Converted or Burned event on chain.
worked example, in words: a coin that trades 1,000 sol pays 10 sol of platform fee. 8 sol of that is swapped to cbbtc into its pot and paid out over the following blocks; 2 sol buys $hashpay that is burned. the launcher receives 5 sol from launchlab. after graduation the pool's lp fee key goes to the same treasury pda, so cpmm fees keep feeding the pot (collect_lp_fees is a stub in this build and will be filled in; until then those fees sit under the nft).
$hashpay, the platform coin, launches on launchlab through the same platform id. its creator fee goes to the launcher wallet like any coin. its platform fee share goes into its own pot, so $hashpay is mineable for btc too.
the block maths
a share
share = keccak256(challenge[32] || beneficiary[32] || nonce_le[8]). it is valid when the first 8 bytes, read big endian, are below the coin's target. expected hashes per share = 2^64 / target. the program checks each share with the keccak syscall, at most 8 nonces per transaction, strictly ascending per miner per block. keccak256 here is the original keccak (0x01 padding), as in ethereum and sol_keccak256, not nist sha3.
difficulty
at every close: next = target × S × duration / (shares × 600), with S = 600 shares per block as the aim, clamped to [target/4, target×4] and then to [2^30, 2^56]. the start target is 2^46 (about 262,144 hashes per share). zero shares: four times easier. a dead coin's block closes late; the retarget only counts the time it was accepting shares.
the 1/6 rule
at close: unallocated = pot − (allocated − paid), reward = unallocated / 6, sats_per_share = reward × 10^9 / shares. every block pays a sixth of what is left, so fees stream out over about an hour instead of one spike, and a block with no shares allocates nothing and rolls forward. the rounding dust stays in the pot.
settlement and the 144-block forfeit
a miner's run of shares in block n earns floor(shares × sats_per_share / 10^9). it settles on their next submit, on payout (anyone) or claim (the beneficiary). the coin keeps a ring of the last 144 blocks (one day). when block n closes it overwrites the slot of block n−144: whatever that block allocated but nobody settled goes back to the pot for everyone. a miner who does not settle within 144 blocks loses those shares. the keeper runs payout for every miner each block, so in practice this never bites; it exists so the pot can never be locked by a forgotten account.
minimum payout
min_payout_sats = 2000. a push payout below that is refused (it would cost more in rent for the cbbtc token account than it pays). pending sats never expire once settled; claim with the beneficiary's wallet has no minimum.
mining without a wallet
the share transactions have to be paid by someone. with a connected wallet, you pay them yourself (about 60k compute units each, 8 shares per transaction). without one, the site posts your batches { coin, block, beneficiary, nonces } to the relayer, a small public service that re-verifies every share, rate-limits per address, and pays the transaction fee from its own wallet.
- the relayer can refuse. it caps shares per address per block and fees per coin per day; past the caps it answers 429 and your shares are dropped. then connect a wallet and submit yourself.
- the relayer cannot steal. the beneficiary is inside every share hash. a relayed share credits the address you typed or it fails on chain. there is no instruction that lets the payer redirect credit.
- the relayer is repaid from the 20% slice, capped per coin per day, and the amounts are on the ledger. if that slice cannot cover a dead coin, the relayer stops relaying that coin and self-submission still works.
the program
anchor 1.2.0, program id 8MRaZudvzEXeijxSvUxLVXttbXgnGgESAdHoUyBEDjG1. the idl is published on chain so explorers decode every instruction. a verified build on an anonymous github org is planned; until then the exact instruction and account layout below is the spec.
| account | pda | holds |
|---|---|---|
Config | ["config"] | admin, converter, share_target 600, block_seconds 600, start / min / max target, pot_bps 8000, burn_bps 2000, min_payout_sats 2000, btc_mint, platform_coin_mint, launchlab_platform_config, paused |
| treasury | ["treasury"] | system account, no data. token authority of every pot, owner of the treasury wsol account, launchlab's platform fee wallet and nft wallet |
Coin | ["coin", mint] | mint, pool, pot, block, block_start, challenge, target, shares this block, total shares, miners, allocated and paid sats, claimed and converted lamports, burned $hashpay, the 144-block ring (shares, sats per share, settled) |
| pot | ["pot", mint] | the coin's cbbtc token account, authority = treasury |
Miner | ["miner", coin, beneficiary] | block, block_shares, next_nonce, pending_sats, total_shares, paid_sats |
| instruction | who | what |
|---|---|---|
register_coin | anyone | checks the launchlab pool (owner, discriminator, platform id, mints), creates coin + pot, opens block 0 |
submit_shares(block, nonces[≤8]) | anyone | verifies each share with keccak, ascending nonces; a share inside the 3 s grace closes the block in the same transaction |
crank | anyone | closes a due block (settle, retarget), opens the next |
payout | anyone | settles a miner; at or above the minimum, creates their cbbtc account and transfers |
claim | the beneficiary | the same, no minimum |
sweep / sweep_vault | anyone | cpi launchlab claim_platform_fee with the treasury pda as signer; books the wsol to the coin |
convert / convert_burn | the converter key (the keeper) or the admin | jupiter v6 route with the treasury signing; checks the spend, that the cbbtc landed in the right pot, and that no other treasury account was touched; the burn variant burns what arrived |
set_config, set_platform_coin | admin | config fields, the platform coin mint (once) |
why convert is not permissionless: the caller picks the swap route and the minimum out. a public caller could route through a bad pool and keep the difference. so only the converter key can call it, every call is checked on chain (the wsol spent, the cbbtc that must land in that coin's pot, the treasury's sol unchanged), and every call is a Converted or Burned event on the ledger. everything else is permissionless: if the keeper dies, anyone can crank, pay out and sweep.
addresses
every address the site uses, from one file (/addresses.json). rows marked set at deploy are filled when that step runs on mainnet; nothing here is simulated.
platform parameters on the launchlab platform config: fee rate 10000 (1%), creator fee rate 5000 (0.5%), platform scale 1,000,000, burn scale 0, creator scale 0; fee wallet = nft wallet = the treasury pda.
caveats
- upgradeable. the upgrade authority, the program admin and the launchlab platform admin are one key held by the team. not a multisig. the people holding that key can change the program, the hashpay config, the platform fee wallet and the fee rate (up to launchlab's caps). it is not frozen.
- unaudited. the program has unit, sdk and local end-to-end tests, and a mainnet canary before the platform coin launches. no third-party audit.
- cbbtc is coinbase-custodied btc. you are paid cbbtc on solana, an spl token backed by bitcoin that coinbase holds. it is not bitcoin on the bitcoin chain. coinbase can freeze it.
- btc price risk until payout. fees arrive in sol and are swapped to cbbtc when the keeper converts. between a trade and the conversion, and between the conversion and your payout, the price moves. the pot is cbbtc, so once converted the sats are sats.
- the converter is keeper-only. see the program section. if the keeper stops converting, sol sits in the treasury wsol account where anyone can see it; the admin key can convert too.
- the relayer can go quiet. rate limits, daily caps and an empty wallet all stop relaying. self-submission with a wallet always works.
- launchlab is raydium's program. the pool, the curve and graduation are theirs; we only hold the platform id and the fee wallet.
- the 144-block forfeit. shares not settled within a day return to the pot. the keeper settles everyone each block; if it is down for a day, use
payoutorclaimyourself. - browser mining is cpu or gpu work. the intensity slider throttles it; it still costs power and battery.
faq
- do i need a wallet?
- no. paste any solana address and mine; cbbtc is pushed to it once your pending sats pass 2,000. a wallet lets you submit your own shares and claim any amount.
- where does the bitcoin come from?
- from the coin's own trading fees. 1% of every trade on a hashpay coin is the platform fee; 80% of that is swapped to cbbtc and put in that coin's pot. no inflation, no promise, only fees that already happened.
- how much does a block pay?
- a sixth of the coin's unallocated pot, split by shares. a coin nobody trades pays nothing. the coin page shows the next reward live.
- what is a share worth?
sats_per_shareof that block, shown on every closed block. your share of the block is your shares divided by all shares in it.- can the relayer take my sats?
- no. your address is inside every share hash; the relayer can only submit or refuse.
- why cbbtc and not real bitcoin?
- payouts happen on solana every ten minutes to any address, which bitcoin itself cannot do cheaply. cbbtc is the deepest btc on solana. you can bridge or sell it any time.
- who closes the block?
- anyone. a share that arrives inside the 3 s grace closes it in the same transaction; otherwise the keeper cranks; if the keeper is down, anyone can.
- what does the launcher get?
- 0.5% of every trade, paid natively by launchlab, plus a coin whose traders mine bitcoin.
- is $hashpay needed to mine?
- no. mining needs nothing. 20% of every platform fee buys and burns $hashpay, and $hashpay itself is a mineable coin.
- webgpu, wasm or js?
- the miner picks the fastest engine your browser has and says which one. every share is re-hashed in js before it is sent, so a faulty gpu can never send a bad share.
verify it yourself
the verify page recomputes a share and a block's sats per share in your browser. from a terminal:
# the program and its idl
solana program show 8MRaZudvzEXeijxSvUxLVXttbXgnGgESAdHoUyBEDjG1
anchor idl fetch 8MRaZudvzEXeijxSvUxLVXttbXgnGgESAdHoUyBEDjG1
# the config and treasury pdas (seeds "config" and "treasury")
solana account 2UVRZypnCoADLYkZKtvtBs4kmPHpyfmDd2Qkw9hYRgAZ
solana account 5GabfviikKTqJy5FLB896oDAPGaS1ukGq5kNktnXYVse
# every coin registered with the program (Coin accounts are 3760 bytes)
curl -s https://api.mainnet-beta.solana.com -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"getProgramAccounts","params":["8MRaZudvzEXeijxSvUxLVXttbXgnGgESAdHoUyBEDjG1",{"encoding":"base64","filters":[{"dataSize":3760}]}]}'
# a coin's pot balance (its cbbtc token account)
spl-token balance --address <pot>
# a share, by hand (node, js-sha3): keccak256(challenge || beneficiary || nonce_le) first 8 bytes big endian < target
node -e 'const {keccak256}=require("js-sha3");/* see the verify page for the exact bytes */'
the platform config on launchlab must show platform_fee_wallet = the treasury pda above. the pot of every coin must be owned by the treasury pda. every Converted event must show the cbbtc landing in that coin's pot. if any of that is false, the site is lying and you should say so loudly.