LotterySweepstakes (Weekly VRF Draw)
A ticket-based weekly lottery where VRF picks one winner from a weighted pool — nobody should control when the draw runs.
Overview
LotterySweepstakes is a recurring lottery with proportional-ticket weighting. Players buy tickets at ticketPrice ETH each; more tickets = higher draw weight. On schedule, AutoLoop uses ECVRF to pick one winner proportionally, transfers the prize pool (minus fees), and resets for the next round.
| Property | Value |
|---|---|
| Base contract | AutoLoopVRFCompatible |
| VRF usage | Winner selection |
| Gas per tick | ~75k + 8k per entrant |
| Source | autoloop/src/agents/LotterySweepstakes.sol |
| Tests | 22 passing (unit + fuzz) |
Why AutoLoop + VRF Are Structurally Required
Inverted interest — identical to CrumbleCore but financial. Two structural failures stack:
- Timing manipulation: with a deterministic draw, the trigger holder can compute who wins before calling and time the trigger to a favorable state, or hold it until they've bought a winning position.
- Free-rider failure: if the prize pool is large enough, nobody wants to trigger the draw for free — every player reasons "let someone else pay gas." Everyone reasons identically, so the loop self-stalls. A neutral keeper with a fee incentive is the only structural fix.
Keeper Trust Model
What AutoLoop guarantees: Ticket holders cannot predict the winner or manipulate the draw timing. The keeper's private key is required to produce the VRF proof, so outcomes are unguessable to participants.
What the keeper knows: Each keeper generates its VRF proof off-chain before submitting, so it knows its own output — but the keeper holds no tickets, so it has no stake in who wins.
How collusion resistance works: AutoLoop registers multiple independent controllers per VRF contract. Each controller's VRF output is unique (derived from their individual private key applied to the same seed). They race to submit:
- Any one controller can withhold their output if they dislike it
- Another controller immediately submits with a completely different, independent winner
- The colluding controller cannot prevent this or predict what the alternative outcome will be
- Determining a specific winner requires ALL registered controllers to withhold simultaneously
This is the same trust model as Chainlink VRF: shift trust from participants (who have conflicts of interest) to a decentralized set of keepers (who don't hold tickets). Additional controllers can self-register via registerControllerKey() to raise the collusion bar for high-value rounds.
Mechanics
- Enter:
buyTickets(count)atticketPrice × countETH. Calling again adds more tickets to the same address - shouldProgressLoop: returns true when
entrantCount > 0androundIntervalhas elapsed since last draw - Winner selection: VRF-seeded linear scan through cumulative ticket weights picks one winner
- Settlement: 3% protocol fee;
prize = pool - feetransferred to winner. Round recorded inrounds[roundId] - Reset: all ticket counts and the entrants list are cleared after each draw — fresh start every round
Revenue Model
- 3% protocol fee on each prize pool
- AutoLoop gas fee per draw tick
Deploy
forge create src/agents/LotterySweepstakes.sol:LotterySweepstakes \
--constructor-args 10000000000000000 604800 \
--rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcastArgs: ticketPrice (wei), roundInterval (seconds). A 0.01 ETH ticket price and 7-day interval (604800) is typical.
VRF Key Registration
Register each controller worker's ECVRF public key before the first draw:
lotterySweepstakes.registerControllerKey(controllerAddress, pkX, pkY);The caller must be either the controller address itself or a contract admin. Use register-vrf-keys.js to automate all workers:
NETWORK=sepolia VRF_CONTRACTS=<lotterySweepstakesAddress> node scripts/register-vrf-keys.jsDashboard
View LotterySweepstakes on the AutoLoop Dashboard.