Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.8.7;
- import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
- import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
- // AutomationCompatible.sol imports the functions from both ./AutomationBase.sol and
- // ./interfaces/AutomationCompatibleInterface.sol
- import "@chainlink/contracts/src/v0.8/AutomationCompatible.sol";
- error Raffle__NotEnoughETHEntered();
- error Raffle__TransferFailed();
- error Raffle__NotOpen();
- error Raffle__UpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 raffleState);
- /** @title a sample raffle contract
- * @author tanvircr7
- * @notice this contract creates an untamperable decentralized smart contract
- * @dev this implements Chainlink VRF v2 and Chainlink Keepers
- */
- contract Raffle is VRFConsumerBaseV2, AutomationCompatibleInterface {
- /* Type Declractions */
- enum RaffleState {
- OPEN,
- CALCULATING
- } // uint256 0 = OPEN, 1 = CALCULATING
- /* State Variables */
- uint256 private immutable i_entranceFee;
- address payable[] private s_players;
- VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
- bytes32 private immutable i_gasLane;
- uint64 private immutable i_subscriptionId;
- uint16 private constant REQUEST_CONFIRMATIONS = 3;
- uint32 private immutable i_callbackGasLimit;
- uint32 private constant NUM_WORDS = 1;
- // Lottery Variables
- address private s_recentWinner;
- RaffleState private s_raffleState;
- uint256 private s_lastTimeStamp;
- uint256 immutable i_interval;
- /* Events */
- event RaffleEnter(address indexed player);
- event RequestedRaffleWinner(uint256 indexed requestId);
- event WinnerPicked(address indexed winner);
- /* Functions */
- constructor(
- address vrfCoordinator,
- uint256 entranceFee,
- bytes32 gasLane,
- uint64 subscriptionId,
- uint32 callbackGasLimit,
- uint256 interval
- ) VRFConsumerBaseV2(vrfCoordinator) {
- i_entranceFee = entranceFee;
- i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinator);
- i_gasLane = gasLane;
- i_subscriptionId = subscriptionId;
- i_callbackGasLimit = callbackGasLimit;
- s_raffleState = RaffleState.OPEN;
- s_lastTimeStamp = block.timestamp;
- i_interval = interval;
- // reset the players
- // s_players = new address payable[](0);
- }
- function enterRaffle() public payable {
- // require (msg.value > i_entranceFee, "Not enough ETH!")
- if (msg.value < i_entranceFee) {
- revert Raffle__NotEnoughETHEntered();
- }
- // you can't enter raffle when it isn't OPEN
- if (s_raffleState != RaffleState.OPEN) {
- revert Raffle__NotOpen();
- }
- // payable is used for typecasting
- // recording all the players entering our raffle
- s_players.push(payable(msg.sender));
- emit RaffleEnter(msg.sender);
- }
- /**
- * @dev this is the function that the chainlink keeper nodes call
- * they look for the upkeep to return true
- * the following should be true to return true:
- * 1. Time interval should have passed
- * 2. The lottery should have atleast 1 player, and have some ETH
- * 3. Our subscription is funded with LINK
- * 4. The lottery should be in "OPEN" state
- * this checkdata can even be a function
- */
- function checkUpkeep(
- bytes calldata /* checkData */
- ) public view override returns (bool upkeepNeeded, bytes memory /* performData */) {
- bool isOpen = (RaffleState.OPEN == s_raffleState);
- bool timePassed = ((block.timestamp - s_lastTimeStamp) > i_interval);
- bool hasPlayers = (s_players.length > 0);
- bool hasBalance = address(this).balance > 0;
- upkeepNeeded = (isOpen && timePassed && hasPlayers && hasBalance);
- }
- function performUpkeep(bytes calldata /* performData */) external override {
- (bool upkeepNeeded, ) = checkUpkeep(new bytes(0));
- if (!upkeepNeeded) {
- revert Raffle__UpkeepNotNeeded(
- address(this).balance,
- s_players.length,
- uint256(s_raffleState)
- );
- }
- s_raffleState = RaffleState.CALCULATING;
- //Q. shouldn't this be an override?
- //using the reqRandomWords directly and so The enclosing function can't be an override
- uint256 requestId = i_vrfCoordinator.requestRandomWords(
- i_gasLane, // gasLane
- i_subscriptionId,
- REQUEST_CONFIRMATIONS,
- i_callbackGasLimit,
- NUM_WORDS
- );
- emit RequestedRaffleWinner(requestId);
- }
- function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
- uint256 indexOfWinner = randomWords[0] % s_players.length;
- address payable recentWinner = s_players[indexOfWinner];
- s_recentWinner = recentWinner;
- //Open Raffle again
- s_raffleState = RaffleState.OPEN;
- // reset the array
- s_players = new address payable[](0);
- // reset the time
- s_lastTimeStamp = block.timestamp;
- // send them the money
- // we take all the money in this contract. and pass it no data
- (bool success, ) = recentWinner.call{value: address(this).balance}("");
- if (!success) {
- revert Raffle__TransferFailed();
- }
- // emit recent winner to keep track
- emit WinnerPicked(recentWinner);
- }
- /* View / Pure Functions */
- function getEntranceFee() public view returns (uint256) {
- return i_entranceFee;
- }
- function getPlayer(uint256 index) public view returns (address) {
- return s_players[index];
- }
- function getRecentWinner() public view returns (address) {
- return s_recentWinner;
- }
- function getRaffleState() public view returns (RaffleState) {
- return s_raffleState;
- }
- function getNumWords() public view returns (uint256) {
- return NUM_WORDS;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment