docs

everything the site claims, with the numbers from the program and the addresses to check. long on purpose.

how it works

  1. 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.
  2. 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.
  3. register. anyone calls register_coin(mint). the program reads the pool, checks it carries our platform id, creates the coin's Coin account and its cbbtc pot, and opens block 0 with challenge = keccak(mint || block || slot_hash).
  4. 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.
  5. 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.
  6. the payout. a miner's sats settle on their next submit, or when anyone calls payout for them. above the minimum (2,000 sats) the cbbtc is pushed to the address; below it, it waits and the beneficiary can claim with a wallet at any time. one block, one coinbase transaction, linked on the coin page.
  7. 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) and convert_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.

whoratemechanism
raydium protocollaunchlab's global trade_fee_ratelaunchlab, not ours
hashpay platform feefee_rate = 10000 (1%)accrues in the platform fee vault pda(platform_config, quote_mint), claimable only by the treasury pda
launchercreator_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.

accountpdaholds
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
instructionwhowhat
register_coinanyonechecks the launchlab pool (owner, discriminator, platform id, mints), creates coin + pot, opens block 0
submit_shares(block, nonces[≤8])anyoneverifies each share with keccak, ascending nonces; a share inside the 3 s grace closes the block in the same transaction
crankanyonecloses a due block (settle, retarget), opens the next
payoutanyonesettles a miner; at or above the minimum, creates their cbbtc account and transfers
claimthe beneficiarythe same, no minimum
sweep / sweep_vaultanyonecpi launchlab claim_platform_fee with the treasury pda as signer; books the wsol to the coin
convert / convert_burnthe converter key (the keeper) or the adminjupiter 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_coinadminconfig 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 payout or claim yourself.
  • 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_share of 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.