Docs How It Works

How It Works

Boom Doom runs a continuous sequence of 30-second prediction rounds on-chain. Each round has a fixed open window, a locked price snapshot, and a final close price that determines winners.

Game Mechanics

At its core, Boom Doom is a binary prediction market: you pick a direction (BOOM for up, DOOM for down), stake SOL, and find out the result 30 seconds later.

Unlike pool-based prediction markets where winnings depend on how many others picked the losing side, Boom Doom uses a fixed payout model. Every winner receives exactly 1.9× their stake — regardless of how many others bet, or which direction they chose. Payouts are backed by the house liquidity in HouseVault (provided by the team).

BOOM = Moon = Up. A BOOM bet wins if the BTC/USD close price is strictly greater than the lock price.
DOOM = Doom = Down. A DOOM bet wins if the BTC/USD close price is strictly less than the lock price.
If close price equals lock price, bets are refunded.

Round Lifecycle

Every round progresses through four phases, each triggered by the Keeper Bot calling executeRound() on-chain.

🕐
NEXT
Waiting to open
🟢
LIVE
Bets accepted
🔒
LOCKED
No new bets · ~30s
SETTLING
Price compared
ENDED
Claim available

Phase 1 — Open (LIVE)

A new round starts with an open betting window. Players can submit betMoon(epoch) or betDoom(epoch) transactions via the UserVault. The round remains open until the keeper calls executeRound() for the first time in that epoch.

Phase 2 — Lock

When the keeper calls executeRound(), the current round is locked. The contract fetches the current BTC/USD price from the Pyth oracle and records it as the lockPrice. No new bets are accepted after this point. Simultaneously, the previous round is ended and settled.

Phase 3 — End & Settle

On the next executeRound() call (~30 seconds later), the contract records the current price as the closePrice for the locked round. It compares closePrice vs lockPrice and sets the round outcome:

ConditionOutcomeWinners
closePrice > lockPrice BOOM wins All Moon bettors receive 1.9× stake
closePrice < lockPrice DOOM wins All Doom bettors receive 1.9× stake
closePrice == lockPrice PUSH All bettors receive their stake back (refund)

Genesis Rounds

When the game first starts (or restarts after being paused), the keeper must call two special functions before the main loop begins:

  1. genesisStartRound() — opens the very first round
  2. genesisLockRound(priceUpdate) — locks the first round with a seed price

After that, the regular executeRound() loop takes over indefinitely.

Price Oracle

Ticker Tok uses the Pyth Network BTC/USD price feed as its on-chain oracle. Pyth provides a pull-based model: rather than the oracle pushing prices on-chain continuously, the caller provides a signed price update (a price attestation) in the transaction itself.

The keeper bot fetches these attestations from the Pyth Hermes WebSocket service and passes them as bytes[] calldata priceUpdate to every executeRound() call. The contract verifies the attestation on-chain before accepting the price.

ParameterValue
FeedBTC/USD (Pyth Insights)
Feed ID 0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43
Max staleness60 seconds
Hermes endpointwss://hermes.pyth.network/ws
Update frequencyUp to 20 Hz
If the Pyth price attestation is older than 60 seconds, the contract will revert and the round will not advance. The keeper bot retries automatically with a fresh price update.

Frontend Price Feed

The frontend independently streams prices for the live chart using a three-tier fallback strategy:

  1. Pyth Hermes WebSocket — real-time feed at up to 20 Hz with EMA smoothing for chart rendering
  2. Pyth REST polling — falls back to polling every 1 second if WebSocket drops
  3. Simulation — synthetic price walk if both feeds are unavailable (useful in dev/Sim Mode)

Payouts & Winnings

Fixed Multiplier Model

Ticker Tok uses a fixed 1.9× multiplier (also written as 19000 basis points in the contract). This differs from pool-based designs where payout depends on how much is on the losing side.

Payout calculation: Your stake = 0.01 SOL Multiplier = 1.9× ───────────────────────────── Payout on win = 0.01 × 1.9 = 0.019 SOL Net profit = 0.019 - 0.01 = +0.009 SOL House edge: Implied win probability for break-even = 1 / 1.9 ≈ 52.6% House edge ≈ 5.3%

Vault-Backed Payouts

When a player wins and calls claim(epoch), the game program sends the payout (stake × 1.9 SOL) to the player's UserVault. When a player loses, their stake is sent to the house vault as house profit.

Player Wins

The player is entitled to stake × 1.9 SOL. The game program sends it to their UserVault when they call claim(epoch); until then the amount stays in the contract.

Player Loses

Player's stake (minus fees) is routed to the house vault as house profit.

Push (Tie)

Player's stake is returned in full. No profit or loss to the vault.

Claiming

Winners must call claim(epoch) to receive their payout. Unclaimed winnings remain in the contract indefinitely.

Betting Limits & Fees

LimitValueNotes
Minimum bet0.001 SOLBet amount only, does not include fees
Maximum betDynamicNo fixed cap. Limit is set by House Vault balance — the more SOL in the vault, the higher the allowed max. The app shows the current max bet (e.g. in the betting card).
Keeper fee0.0005 SOLPaid at bet time, goes to keeper bot
Treasury fee0.001 SOLPaid at bet time, goes to platform
Total fees per bet0.0015 SOLAdded on top of bet amount
One bet per roundYesOne address can only bet once per epoch
Direction changeNoOnce placed, a bet cannot be changed or cancelled