A decentralized, verifiable, and automated lottery (raffle) smart contract system built with Foundry and Chainlink VRF v2.5. This project demonstrates how to create a secure, fair, and upgradeable raffle contract using modern Solidity best practices and robust testing.
- Decentralised Raffle: Anyone can enter by paying the entrance fee.
- Chainlink VRF Integration: Uses verifiable randomness for winner selection.
- Chainlink Automation (Upkeep): Supports time-based automated raffle execution.
- Comprehensive Testing: Includes unit and integration tests using Foundry cheatcodes and mocks.
|-- src/
│ |-- Raffle.sol # Main Raffle contract
|-- script/
│ |-- DeployRaffle.s.sol # Deployment script
│ |-- HelperConfig.s.sol # Network config helper
│ |-- Interactions.s.sol # Interaction scripts
|-- test/
│ |-- unit/ # Unit tests
│ │ |-- RaffleTest.t.sol
│ |-- integration/ # Integration tests
│ |-- mocks/ # Mock contracts (e.g., LinkToken)
|-- lib/ # External dependencies (Chainlink, Forge Std, etc.)
|-- foundry.toml # Foundry config
|-- Makefile # make commands
|-- README.md # Project documentation
git clone https://github.com/YOUR_GITHUB_USERNAME/foundry-chainlink-raffle.git
cd foundry-chainlink-raffle
forge installforge testforge script script/DeployRaffle.s.sol --broadcast-
Set up your
.envwithSEPOLIA_RPC_URL. -
Make sure your signing wallet has sufficient Sepolia ETH and Sepolia LINK tokens to pay for the deployment and Chainlink subscription costs. You may obtain Sepolia ETH and Sepolia LINK tokens from the Chainlink Faucet.
-
Set your funded wallet address in the
accountproperty of theHelperConfig.s.sol. This wallet will be signing all the deployment transactions. -
Run:
forge script script/DeployRaffle.s.sol --rpc-url $SEPOLIA_RPC_URL --broadcast # A more secure way to do this is by storing your private key in a local keystore by using the `cast wallet import` command and then using the keystore name in the above command this way: forge script script/DeployRaffle.s.sol --rpc-url $SEPOLIA_RPC_URL --account your_keystore_name --broadcast
- Users enter the raffle by calling the
enterRaffle()function with the requiredentranceFeein ETH, defined in HelperConfig.s.sol. - After a set interval, defined in Chainlink Automation settings, the winner selection can be triggered.
- It starts with the Chainlink Automation process calling the
checkUpkeepfunction. If that returnstrue, then theperformUpkeepfunction is called. - The performUpkeep function requests a random number from Chainlink VRF via the VRF Coordinator Contract's
requestRandomWordsfunction. - Chainlink Nodes generate a Random number off-chain and submit the random value and proof back to the VRF Coordinator contract on-chain.
- The VRF Coordinator contract
verifies the cryptographic proofto ensure the randomness is valid. - If valid, the Coordinator calls the consumer contract’s
fulfillRandomWordsfunction, which is the callback function that must be implemented in the Consumer contract to receive the random number.
- Uses Chainlink VRF for provable randomness.
- Follows Checks-Effects-Interactions pattern.
- Includes custom errors and revert conditions.
-
You may choose to Create a Chainlink subscription manually using the website and mention it in HelperConfig.s.sol
ORlet it be created and get funded automatically by the DeployRaffle.s.sol script at runtime.Note: Each of these steps:
Subscription creation,Subscription funding, andAdding the Raffle Contract as a consumerare all done automatically by theDeployRafflescript, however,createSubscriptionUsingConfig,fundSubscriptionUsingConfigandaddConsumerUsingConfigfunctions defined in Interactions.s.sol can also be executed using theforge scriptcommand. If doing it all manually, make sure to deploy the Raffle contract and use it's address as the Consumer Contract address in Chainlink. -
Next is automating the raffle execution, for this register a new Time based Upkeep and mention the Raffle Contract's address and ABI in the registration form.
-
You may call the
enterRafflefunction from multiple wallets having the required Sepolia ETH, to make them enter the raffle. After the defined interval in the Upkeep the raffle is triggered and a winner is picked. The history of this triggering operation can be viewed on Chainlink's Automation dashboard.
MIT