Docs

How a coin's trading fees become real Megapot tickets, and how winnings come back to its holders.

Overview

Every coin launched on Lottopad has a jar. The coin's pump.fun creator fee goes to the jar (the creator of every coin is a program address, ["jar", mint]); 20 % of each collected fee goes to the pad, the rest stays in the jar.

When a jar holds at least the threshold, the keeper takes it to Base once per Megapot drawing: it bridges the SOL to USDC and buys real Megapot tickets (each a $1 NFT on Base). Megapot draws every day at 17:00 UTC with Pyth randomness. Lottopad has no randomness of its own.

Whatever comes back (winnings plus our own referral cashback, since the pad is its own referrer) is bridged back to SOL and buys this coin on its curve or pool. The bought tokens go to the coin's holders pro rata to a snapshot at the drawing; each holder claims with a merkle proof.

Megapot is an independent protocol on Base. Lottopad buys tickets there; it does not run a lottery, set prizes or pick numbers. Ticket NFTs are held by the keeper's Base wallet (see trust points).

Lifecycle of a round

statuswhat it meanswho moves it on
openSOL moved from the jar to the keeper for one drawingkeeper: bridge
bridgingUSDC arrived on Base (fill tx recorded)keeper: buy tickets
ticketsticket ids + numbers stored on Solana, NFTs on BaseMegapot draws; keeper posts the result
settledwinnings back in the round vault; buying this coin in chunks; holder root posted; veto window; claimsanyone: buy chunks, claims
closedclaim window over; unclaimed tokens carry into the coin's next paying roundanyone
no winless than the minimum payout came back: it goes to the jar, nothing to buy-
refundedno tickets could be bought: SOL back to the jarkeeper
defaultedthe keeper missed a deadline; anyone marks it publicly and no new round of any coin opens until it is resolvedanyone / keeper / admin write-off

The transactions, with an example

  1. Launch (you): launch(name, ticker, uri, dev_buy) creates the pump.fun coin with the jar as creator and your optional first buy. Launch fee: 2.5 % of the dev buy (a launch without a dev buy is free).
  2. Collect (anyone): pump creator fees into the jar; pad share booked.
  3. Open round (keeper): when the jar holds the threshold, up to 1 SOL goes to the keeper for the next drawing.
  4. Bridge + tickets (keeper, Base): SOL → USDC (Relay or Mayan), then Jackpot.buyTickets with us as referrer and the coin's mint as source. attest_bridge and post_tickets record both chains' hashes and every ticket id.
  5. Draw (Megapot): 17:00 UTC, Pyth randomness. post_draw records the numbers, the Pyth random number and the Base tx.
  6. Settle (keeper): claimWinnings + claimReferralFees on Base, bridge back, then settle pulls exactly the SOL that came back into the round vault.
  7. Buy back: buy_chunk buys this coin with the vault's SOL, at most 2 % of the curve's SOL per chunk. Only the keeper sends chunks in the first 12 h after a settle (sandwich protection); anyone may after.
  8. Claim (anyone, for a holder): after the guardian veto window, claim(index, weight, proof) pays the holder's share to the holder's token account.

Example. A jar holds 0.10 SOL. At $120/SOL the bridge delivers about 12 USDC, the keeper buys 12 tickets. Megapot pays 3 of them (about 1 in 4 wins something) for $7.20 gross; Megapot keeps 10 % of each prize as the referrer's share, which comes back to us as referral cashback together with 10 % of the $12 spent: $6.48 won + $1.92 referral = $8.40 → about 0.07 SOL → bought back and paid to the holders.

How ticket numbers are made

The keeper cannot choose numbers. The program computes them in post_tickets and stores them with each ticket id:

seed_sig = the coin's last pump / PumpSwap buy in a slot strictly before the round's open slot
h = sha256("lottopad:numbers:v1" || seed_sig[64] || mint[32] || u64le(draw_id) || u32le(ticket_index))
read h as u16 little-endian words (h = sha256(h) when used up)
normals: v = 1 + word % ball_max, keep if new, until 5 picked, sorted ascending
bonus:   1 + next word % bonus_max           (ball_max / bonus_max: Megapot's, per drawing)

Every round page has a Check it yourself button that recomputes every ticket in your browser and compares it with the chain. The numbers do not change the odds: the drawing happens later, on Megapot.

Trust points

1. The keeper holds the round's SOL while it bridges, and the USDC / ticket NFTs on Base. Megapot pays the NFT owner. Bounded by: 1 SOL per round, 5 SOL over all unsettled rounds, one round per coin per drawing, drawings at least 12 h apart, at most 2 rounds of a coin in flight, deadlines (tickets by the drawing + 1 h, settle by the drawing + 72 h) after which anyone marks the round defaulted and no new round opens anywhere until it is resolved. Every coin's rounds follow one Megapot drawing at a time, so the keeper holds at most 5 SOL per drawing. Keeper key changes wait 48 h.

2. Keeper attestations. Bridge fills, ticket ids, the drawing's numbers, winnings and the SOL that came back are not verifiable on Solana. Each carries its Base tx hash in events and in the keeper log (the tape). The program checks what it can: numbers are derived on chain, USDC spent never exceeds USDC received, the drawing matches the round, exactly the attested SOL is pulled.

3. The holder table. Keeper-posted merkle root, bound to the round, published as JSON and rebuildable by anyone; the guardian can veto it during the veto window; excluded accounts are refused on chain too.

4. The guardian can only delay (veto a root). 5. The admin sets bounded parameters, pauses new launches and rounds, changes the keeper / guardian with a delay, and can write off a defaulted round (moves nothing).

Parameters (read from the program now)

Reading the config…

Program reference

Program id LoTYmdHDiNwZH8RYDjo1vzBzjB6nUnJhSxx46qoKJNJ. IDL: /idl/lotto.json.

accountseedsholds
Config["config"]admin, treasury, keeper, guardian, params, exposure
Coin["coin", mint]jar balance, pad share (fixed at launch), totals
Jar["jar", mint]system account, the coin's pump creator
Round["round", mint, u64le(draw_id)]one per coin per Megapot drawing: every step's record
Vault["vault", round]SOL that came back; buys the coin; holds bought tokens
TicketBatch["tix", round, u16le(batch)]one Megapot buy tx: ≤ 10 ticket ids + numbers
Draw["draw", u64le(draw_id)]one Megapot drawing: numbers, Pyth random, Base tx, snapshot slot

Errors

Verify on chain

  • Tickets: every ticket links to its NFT on Basescan (JackpotTicketNFT 0x48Ff…66e4); the buy tx carries the coin's mint as source.
  • Draws: Jackpot.getDrawingState(id) on 0x3bAe…42a2; the draw studio compares the posted numbers with Base live.
  • Numbers: the round page recomputes every ticket in your browser.
  • Holders: the table JSON of each round, rebuildable from Solana balances at the snapshot slot.
  • The keeper log: download the JSON.

What the admin can and cannot do

cancannot
change parameters inside fixed bounds (pad share only for future coins)move SOL or tokens from any jar, vault or holder
pause new launches and new roundsstop settles, buybacks or claims
propose a new keeper / guardian (live after 48 h)change a round's rules after it opened
write off a round defaulted for 7 days (moves nothing)choose ticket numbers or drawing results

Risks

  • Keeper custody while bridging and on Base (trust point 1), capped as above.
  • Bridge risk (Relay / Mayan) and price moves between the round and the settle.
  • Most tickets lose. Expect about 1 in 4 to win a small prize; the jackpot is Megapot's and very unlikely.
  • Megapot's terms: prizes over $500 need identity checks in Megapot's app; the contract itself pays the NFT owner.
  • Buy chunks: keeper-only for 12 h after a settle, then permissionless; each is capped at 2 % of the venue's SOL to limit sandwiching.
  • If Megapot enters emergency mode, a drawing is recorded as "no drawing" and its tickets are refunded on Base.

FAQ

Do I have to do anything as a holder?

Hold through the drawing. After a paying round, connect a wallet: the Mine panel shows what you can claim.

Who picks the numbers?

Nobody. They come from the coin's last buy signature; the program computes them.

Can the keeper keep winnings?

It attests what came back, and every Base tx is public. A missed deadline makes the round defaulted in public and freezes new rounds.

What if a round wins nothing?

The referral cashback still comes back. Below the minimum payout it goes to the jar for the next round.

About this preview

This preview runs on a local Solana validator with a copy of pump.fun. The Base side runs on an anvil fork of Base mainnet with the real Megapot contract; the fork settles each drawing with Megapot's real Pyth random number read from Base mainnet, so winning numbers match the real draw. Fork transaction hashes and some older seeded ticket ids (from the localnet mock) do not exist on Base mainnet, so their Basescan links do not resolve; they are marked preview. A trade simulator on the box trades the example coins so jars fill. The local test wallet in the wallet picker is funded with test SOL.