[Plan] ๐ฏ Advanced Random Airdrop System with Chainlink VRF & Automation
A comprehensive Solidity project that combines Chainlink VRF (Verifiable Random Function) and Chainlink Automation to create a fully automated, fair, and transparent airdrop distribution system.
๐ What Makes This Project Special
This isn't just another airdrop contract. It's a complete automated ecosystem that demonstrates advanced smart contract patterns, Chainlink integrations, and real-world deployment strategies.
- Fully Automated: No manual intervention required after setup
- Provably Fair: Uses Chainlink VRF for verifiable randomness
๐ Learning Objectives
๐ Chainlink VRF Integration
- Requesting and handling verifiable random numbers
- Managing VRF subscriptions and LINK payments
- Implementing callback functions with proper error handling
- Working with request IDs and async responses
๐ค Chainlink Automation (Keepers)
- Setting up automated time-based triggers
- Implementing
checkUpkeep
andperformUpkeep
functions - Managing contract state transitions automatically
- Handling complex automation logic
๐๏ธ Advanced Smart Contract Patterns
- Custom Errors: Gas-efficient error handling
- Events: Comprehensive logging and monitoring
- Enums: Clean state management
- Modifiers: Access control and validation
- CEI Pattern: Checks-Effects-Interactions security
๐งช Professional Testing & Deployment
- Unit tests with Foundry
- Integration tests with forked networks
- Fuzz testing for edge cases
- Mock contracts for local development
- Deployment scripts for multiple networks
- Gas optimization techniques
๐งช Testing Strategy
Unit Tests
forge test --match-test testRegistration
forge test --match-test testVRFCallback
forge test --match-test testAutomation
Integration Tests
forge test --fork-url $SEPOLIA_RPC_URL
Fuzz Tests
forge test --match-test testFuzz_MultipleRegistrations
Gas Analysis
forge test --gas-report
๐ Deployment & Interaction
Local Development
# Start local blockchain
anvil
# Deploy to local
forge script script/DeployAirdrop.s.sol --rpc-url http://localhost:8545 --broadcast
Testnet Deployment
# Deploy to Sepolia
make deploy ARGS="--network sepolia"
# Verify contract
make verify ARGS="--network sepolia"
Interaction Scripts
# Register for airdrop
cast send $CONTRACT_ADDRESS "registerForAirdrop()" --private-key $PRIVATE_KEY
# Check registration status
cast call $CONTRACT_ADDRESS "isRegistered(address)" $YOUR_ADDRESS
๐ Dependencies
This project uses the following libraries:
- Chainlink contracts for VRF (Verifiable Random Function) and Automation
- OpenZeppelin contracts for security and utility functions
- Forge Standard Library for testing
Installing Dependencies
To install all required libraries with Foundry, run:
# Install all dependencies at once
forge install
# Or install each dependency individually
forge install smartcontractkit/chainlink-brownie-contracts --no-commit
forge install foundry-rs/forge-std --no-commit
forge install OpenZeppelin/openzeppelin-contracts --no-commit
Note: The
--no-commit
flag prevents Foundry from committing the changes to your repository.
๐ฏ Project Milestones
Week 1: Foundation
- Project setup and basic contract structure
- Registration system implementation
- Basic VRF integration
- Initial testing framework
Week 1: Automation
- Chainlink Automation integration
- Automated phase transitions
- Winner selection logic
- Integration testing
Week 2: Advanced Features
- Multi-tier prize system (optional)
- Weighted selection algorithm (optional)
- Anti-Sybil protection
- Gas optimization
Week 2: Production Ready
- Comprehensive testing
- Deployment scripts
- Documentation
- Security review
๐ Success Metrics
By the end of this project, you'll have:
- โ A fully functional automated airdrop system
- โ Deep understanding of Chainlink VRF and Automation
- โ Professional-grade testing and deployment skills
- โ Gas-optimized and secure smart contracts
- โ Real-world deployment experience
Contents
Errors
Errors
AirDrop_WrongAmountOfETHSent
error AirDrop_WrongAmountOfETHSent(uint256 msgValue, uint256 i_entranceFee);
AirDrop_NotTheWinner
error AirDrop_NotTheWinner();
AirDrop_NoActiveLottery
error AirDrop_NoActiveLottery();
Events
Events
Registration
Emitted when a user successfully registers for the current lottery
event Registration(address indexed user);
Parameters
Name | Type | Description |
---|---|---|
user | address | The address of the user who registered for the airdrop |
RaffleStarted
Emitted when a raffle is started and ready for winner selection
event RaffleStarted(uint256 amountOfParticipants, uint256 amountOfTokens, uint256 changesToWinPerParticipant);
Parameters
Name | Type | Description |
---|---|---|
amountOfParticipants | uint256 | The total number of participants in the lottery |
amountOfTokens | uint256 | The total amount of ETH collected from all participants |
changesToWinPerParticipant | uint256 | The calculated chances to win per participant (entrance fee divided by total participants) |
winnerSelected
Emitted when a winner has been selected for the lottery
event winnerSelected(address indexed winner);
Parameters
Name | Type | Description |
---|---|---|
winner | address | The address of the selected winner who can claim the prize |
Airdrop
Inherits: VRFConsumerBaseV2Plus, ReentrancyGuard, Errors, Events
State Variables
NUM_WORDS
uint32 private constant NUM_WORDS = 1;
REQUEST_CONFIRMATIONS
uint16 private constant REQUEST_CONFIRMATIONS = 3;
i_entranceFee
uint256 private immutable i_entranceFee;
i_amountOfParticipantsPerLottery
uint256 private immutable i_amountOfParticipantsPerLottery;
i_subId
uint256 private immutable i_subId;
i_keyHash
bytes32 private immutable i_keyHash;
i_callbackGasLimit
uint32 private immutable i_callbackGasLimit;
lotteries
lottery[] private lotteries;
s_currentLotteryId
uint256 private s_currentLotteryId;
Functions
constructor
constructor(
uint256 _entranceFee,
uint256 _amountOfParticipantsPerLottery,
address _vrfCoordinator,
uint256 _subId,
bytes32 _keyHash,
uint32 _callbackGasLimit
) VRFConsumerBaseV2Plus(_vrfCoordinator);
registerForAirdrop
function registerForAirdrop() external payable;
fulfillRandomWords
function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override;
startTheRaffle
function startTheRaffle() public;
claimTheRewards
function claimTheRewards(uint256 _lotteryId) public nonReentrant;
Structs
Participant
struct Participant {
bool active;
uint256 currentLotteryId;
uint256 amountToClaim;
}
lottery
struct lottery {
State state;
Participant[] participants;
uint256 amountOfParticipants;
uint256 amountOfTokens;
uint256 changesToWinPerParticipant;
address theWinner;
uint256 time;
}
Enums
State
enum State {
Registration,
Waiting,
Finished
}