Game Lifecycle

A QuantumRaffle V2 deployment can run an arbitrary number of sequential games. Each game has its own locked-in configuration, its own pools, its own Power Slots, and its own claim windows. Games never overlap — game N+1 cannot start until game N is over.

The five phases

1. Initialization

  1. Host deploys the contract with an initial configuration.
  2. gameId starts at 0 (no active game).
  3. Host sends ETH to start game 1. The constructor's config is locked into game 1, the host's deposit counts as the seeding entry, and a GameStarted event is emitted with the locked-in depositFeeBps and minTicketsBeforeEnd.

2. Active game (entries)

Players enter by sending ETH. There are two entry paths:

Path Calldata Prizes go to
receive() empty msg.sender (default behavior)
fallback() exactly 20 bytes the address encoded in calldata (cold-wallet override)

Each entry updates:

  • entrantCount[gameId]
  • entrants[gameId][entrantId] — the address recorded for ticket ownership
  • prizeRecipient[gameId][entrantId] — set only when fallback() was used
  • prizePool[gameId] and adoptionBonusPrizePool[gameId][cohort]
  • prizePerWinner[gameId]
  • lastTimestamp[gameId] — resets the inactivity countdown

A GameEntered event fires per transaction.

3. Game over

The game ends when:

block.timestamp > lastTimestamp[gameId] + deadline
AND
entrantCount[gameId] >= minTicketsBeforeEnd

If minTicketsBeforeEnd is non-zero and the floor has not yet been reached, the inactivity countdown is paused regardless of how much wall time has elapsed. New entries continue to be accepted until the floor is met. Once the floor is hit, the deadline behaves normally and is reset by every subsequent entry. See Minimum Tickets Before End.

When the game is over, no new entries are accepted and claim functions unlock.

4. Claiming

Action Function Who
Claim grand prize claimPrize(gameId, entrantId) each Power Slot holder
Claim adoption bonus (default path) batchClaimAdoptionBonusPrize(gameId, identifications) each eligible entrant
Claim adoption bonus (heavy-receive fallback) claimAdoptionBonusPrize(gameId, entrantId, cohortId) each eligible entrant
Sweep the last cohort's pool clearLeftoverAdoptionBonus(gameId) host
Withdraw accrued fees (any time) withdrawDepositFees() host

Both grand-prize and adoption-bonus payouts route through getPrizeRecipient, so a cold-wallet override set with fallback() at entry time is honored.

See Adoption Bonus & Cohorts for how cohorts unlock and which pools each cohort can claim from. See Cold-Wallet Prize Routing for the override mechanism.

5. Next game

  1. (Optional) Host updates the next game's parameters via setNextGameConfig(...). This is the only way to change depositFeeBps, minTicketsBeforeEnd, the log bases, the proportions, the entry amount, or the deadline. The change takes effect when the next game starts.
  2. Host sends ETH to start the next game. The current nextGameConfig is snapshotted into gameConfigRecord[newGameId].
  3. Cycle repeats.

What a participant sees per game

A participant who sends k * entryAmount wei in a single deposit:

  1. Receives k sequential entrant IDs (the post-deposit entrantCount minus k - 1 through the post-deposit entrantCount itself).
  2. Has msg.value % entryAmount of dust refunded.
  3. Has effectiveValue * depositFeeBps / 10000 skimmed off into accruedDepositFees (host revenue), where effectiveValue = k * entryAmount.
  4. Has the remainder split between the grand-prize pool and the current-cohort adoption-bonus pool per the locked proportions.

The fee/floor lock guarantee

Every parameter — entryAmount, deadline, both log bases, both proportions, depositFeeBps, and minTicketsBeforeEnd — is captured into gameConfigRecord[gameId] at the moment gameId starts. The host cannot mutate the active game's config; setNextGameConfig only writes to nextGameConfig. This is a deliberate guarantee for participants: the fee, floor, and rules they see when they enter are the rules that apply for the entire raffle.

results matching ""

    No results matching ""