Luckotto

Sell Luckotto tickets, make a fortune.

Luckotto lets partner sites sell Luckotto tickets through an iframe. Players request numbers, confirmed payments allocate non-overlapping claims, and each round pays from the sum of allocated weighted claim prices.

GameWeighted 1-100 picks
Claims6-number atoms
PrizeSum of orders
How the game works

Players buy priced claim sets, not reserved lucky numbers

The player-facing action is intentionally simple: choose between 6 and 25 unique numbers from 1-100, then pay a quoted Bitcoin amount. Those requested numbers are a hint and a budget target. They are not a reservation, because reserving unpaid claims would let abandoned checkouts block the round for everyone else.

After payment confirmation, the allocator finalizes one actual ticket for the current open round. A ticket is a set of numbers, but mathematically it represents every six-number subset inside that set. A six-number ticket contains one atomic claim; a 25-number ticket contains 177,100 internal atomic claims, out of 1,192,052,400 possible six-number claims in the full pool. The database stores the allocated numbers and uses the rule conflict(A, B) = size(intersection(A, B)) >= 6 to prevent two tickets from owning the same six-number outcome.

claim_count(S) = choose(size(S), 6)
price(S) + explicit_fee(S) <= paid_amount
conflict(A, B) = size(intersection(A, B)) >= 6
Allocation rule

Confirmed money creates claims. Hints guide the allocator, but only finalized non-overlapping tickets enter the prize pool.

This separation keeps the player experience familiar while keeping the ledger precise. The prize pool is the sum of allocated weighted claim prices only. The explicit partner fee and any unused paid budget are not hidden inside the odds and do not increase the prize pool.

Odds and price

Number N is N times as likely as number 1

Every Luckotto number has a draw rate equal to its face value: rate(n) = n. The total rate across the 1-100 pool is 5,050, so the first-draw probability for number N is N / 5,050. If number 73 and number 1 are both still available for the next draw, 73 is exactly 73 times as likely as 1 to be selected at that point.

1
1x
10
10x
25
25x
50
50x
75
75x
100
100x
110255075100

A raw draw is six weighted draws without replacement. Once a number is drawn, its rate leaves the denominator. For an ordered draw [d1..d6], the probability is:

P([d1..d6]) =
  d1 / R
  * d2 / (R - d1)
  * d3 / (R - d1 - d2)
  * ...
  * d6 / (R - d1 - ... - d5)

Claims are unordered, so the probability of a six-number claim is the sum over every ordering of those six numbers. Larger tickets are evaluated by asking whether the first six drawn numbers all fall inside the allocated ticket. The quote engine uses that standalone claim value to price the ticket's prize-pool contribution:

R = sum(rate(n) for n in 1..100)

function probability(ticket):
  states = { empty_mask: { p: 1, used_rate: 0 } }

  repeat 6 times:
    next = {}
    for mask, state in states:
      remaining = R - state.used_rate
      for each selected number n not in mask:
        next_mask = mask with n included
        next[next_mask].p += state.p * rate(n) / remaining
        next[next_mask].used_rate = state.used_rate + rate(n)
    states = next

  return sum(state.p for state in states)

Pricing is deliberately proportional. The coldest atomic claim is assigned 1 sat. Every other ticket scales from that base by its calculated weighted probability, so a claim that is 10x as likely contributes 10x as much before the explicit partner fee. The race-to-six settlement odds also depend on which other tickets were sold in the same round, because the round stops at the first sold claim to complete.

Coldest atomBase claim
Probability3.1582e-171 in 3.166e+16
Relative1xvs coldest claim
Weighted price0.00000001 BTC (~<$0.01 USD)
Random Atom
Probability1.5596e-91 in 641,191,896
Relative4.938e+7xvs coldest claim
Weighted price0.4938259 BTC (~$36,543 USD)
Hottest atomHighest six
Probability5.0314e-81 in 19,875,203
Relative1.593e+9xvs coldest claim
Weighted price15.93126727 BTC (~$1.2M USD)
Drawing process

Settlement is deterministic from the closing block hash

Settlement turns the closing block hash into a full weighted draw order containing every number from 1-100. Number weights still apply at every step: while both numbers are undrawn, number 73 remains 73 times as likely as number 1 to be the next number selected.

The process is: close the round at its configured ending block, record the closing block hash, generate and store the full draw order, then scan sold tickets until at least one ticket has six drawn numbers. If several tickets complete on the same drawn number, compare their six hit positions. The ticket whose earliest hit is earliest wins; if those are equal, compare the second-earliest hit, then the third-earliest, until one claim is ahead.

closing_height = round.end_block_height
seed = closing_block_hash(closing_height)
tickets = allocated tickets where price_sats > 0

draw_order = weighted_order_without_replacement(seed, 1..100)
store draw_order on the round

hits = map(ticket.id => [])

for position, number in draw_order:
  completed = []
  for ticket in tickets:
    if number not in ticket.numbers:
      continue
    hits[ticket.id].append({ number, position })
    if hits[ticket.id].length == 6:
      completed.append(ticket.id)

  if completed is not empty:
    winner = ticket whose six hit positions are earliest
    claim = winner's six hit numbers
    stop

store winner.id and claim on the round
function uniform(seed, label, total):
  limit = 2^256 - (2^256 mod total)
  for counter in 0..999:
    value = SHA256(seed + ":" + label + ":" + counter)
    if value < limit:
      return value mod total

The deterministic random values use domain-separated SHA-256 labels such as draw:0 and draw:1. Rejection sampling avoids modulo bias by discarding hash values outside the largest exact multiple of the requested range.

For example, suppose ticket A owns and ticket B owns . With draw order [1, 7, 2, 3, 4, 5, 6], both complete when 6 is drawn. A wins because its earliest hit was drawn at position 1, earlier than B's earliest hit at position 2.

draw order: 1, 7, 2, 3, 4, 5, 6

A = [1, 2, 3, 4, 5, 6]
A positions = [1, 3, 4, 5, 6, 7]

B = [2, 3, 4, 5, 6, 7]
B positions = [2, 3, 4, 5, 6, 7]

Both complete when 6 is drawn.
A wins because its earliest hit is position 1,
which is earlier than B's earliest hit at position 2.
Live shared round

Current round state

View round
Current roundRound 5Blocks 116001 to 117000
Prize pool120.17179073 BTC (~$8.9M USD)Allocated weighted claim prices only.
Allocated tickets3030 confirmed orders.
Public record

Every settled round stays available for review

View all rounds