A decentralized lottery (raffle) smart contract built with Solidity using Chainlink VRF v2.5 for verifiable randomness and Chainlink Automation for automated winner selection.
The Raffle contract allows users to enter a lottery by paying an entrance fee. After a predefined interval:
- Chainlink Automation checks whether upkeep is needed.
- A verifiable random number is requested from Chainlink VRF.
- A random winner is selected automatically.
- The winner receives the entire contract balance.
This contract demonstrates secure and decentralized randomness for on-chain games and lotteries.
- Fully decentralized lottery system
- Automated execution with Chainlink Automation
- Provably fair randomness using Chainlink VRF v2.5
- Gas-efficient custom errors
- Secure payout mechanism
- Immutable configuration variables
- Follows CEI (Checks-Effects-Interactions) security pattern
- Solidity
^0.8.18 - Chainlink VRF v2.5
- Chainlink Automation (Keepers)
- Ethereum-compatible blockchain
| Component | Description |
|---|---|
enterRaffle() |
Allows players to join the raffle |
checkUpkeep() |
Checks whether winner selection conditions are met |
performUpkeep() |
Requests a random number from Chainlink VRF |
fulfillRandomWords() |
Selects and pays the winner |
| Getter Functions | Exposes contract state variables |
Players enter the raffle by calling:
enterRaffle()Requirements:
- Must send at least the entrance fee
- Raffle must be open
Example:
raffle.enterRaffle{value: entranceFee}();Chainlink Automation periodically calls:
checkUpkeep()The raffle proceeds only if:
- The configured time interval has passed
- The raffle is open
- There are players
- The contract contains ETH
If upkeep is needed:
performUpkeep()is executed which:
- Changes raffle state to
CALCULATING - Requests a random number from Chainlink VRF
Chainlink VRF calls:
fulfillRandomWords()The contract:
- Selects a random player
- Resets the raffle
- Sends the prize pool to the winner
enum RaffleState {
OPEN,
CALCULATING
}| State | Description |
|---|---|
OPEN |
Users can enter the raffle |
CALCULATING |
Winner selection in progress |
Emitted when a player enters the raffle.
event RaffleEntered(address indexed player);Emitted when randomness is requested.
event RequestedRaffleWinner(uint256 indexed requestId);Emitted after a winner is selected.
event winnerPicked(address indexed winner);The contract uses custom errors to reduce gas costs.
| Error | Description |
|---|---|
Raffle__NotEnoughEthToEnterRaffle |
Insufficient ETH sent |
Raffle__TransferFailed |
ETH transfer failed |
Raffle__RaffleNotOpen |
Raffle is not accepting entries |
Raffle__UpKeepNotNeeded |
Conditions for upkeep were not met |
| Parameter | Description |
|---|---|
entranceFee |
Minimum ETH required to enter |
interval |
Time interval between winner selections |
vrfCoordinator |
Chainlink VRF Coordinator address |
gasLane |
Chainlink gas lane key hash |
subscriptionId |
VRF subscription ID |
callBackGasLimit |
Gas limit for VRF callback |
| Function | Returns |
|---|---|
getEntranceFee() |
Entrance fee |
getRaffleState() |
Current raffle state |
getPlayer(index) |
Player address |
getLastTimeStamp() |
Last raffle timestamp |
getRecentWinner() |
Most recent winner |
The contract follows the Checks-Effects-Interactions pattern:
- Validate conditions
- Update state
- Interact with external addresses
Winner selection uses Chainlink VRF, preventing:
- Manipulation
- Predictable randomness
- Miner influence
Chainlink Automation ensures:
- Trustless operation
- No manual winner selection
- Reliable scheduling
- Deploy contract with Chainlink VRF configuration
- Fund Chainlink subscription
- Register contract with Chainlink Automation
- Users enter raffle
- Automation triggers winner selection automatically
Player Enters Raffle
↓
checkUpkeep() returns true
↓
performUpkeep() requests randomness
↓
Chainlink VRF responds
↓
Winner selected
↓
Prize transferred
- Multiple winners
- ERC20 token support
- Frontend integration
- NFT-based raffle tickets
- Emergency withdrawal
- Pausable contract
- Admin controls
- Entry limits per wallet
This project is licensed under the MIT License.
// SPDX-License-Identifier: MITChimezie Obi
This contract is provided for educational and demonstration purposes. Audit and extensive testing are recommended before deploying to production.