I am tackling this problem for couple of days now, I've tried everything but it just doesn't seem to work. Im having problem when I test the 01 deploy, the "doesnt allow entrance when raffle is calculating". Anyone any knowledge what to do.
Here is my raffle file
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/AutomationCompatible.sol";
error Raffle_NotEnoughEthEntered();
error Raffle_TransferFailed();
error Raffle_NotOpen();
error Raffle_UpkeepNotNeeded(uint256 curentBalance, uint256 numPlayers, uint256 raffleState);
/** @title A sample Raffle Contract
* @author Patrick Collins
* @notice THis contract is for creating an untamperable decentralized smart contract
* @dev This implemens Chainling VRF v2 and Chainlink Keepers
*
*/
contract Raffle is VRFConsumerBaseV2, AutomationCompatibleInterface {
/* Type declarations */
enum RaffleState {
OPEN,
CALCULATING
} //uint256 0 = OPEN, 1 = CALCULATING
/* State Variables */
uint256 private immutable i_entranceFee;
address payable[] private s_players;
// needs to be payable because we will have to pay them
uint256 private s_lastTimeStamp;
VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
bytes32 private immutable i_gasLane;
uint64 private immutable i_subscriptionId;
uint16 private constant REQUEST_CONFIRMATIONS = 3; // For constants use caps lock
uint32 private immutable i_callbackGasLimit;
uint32 private constant NUM_WORDS = 1;
uint256 private immutable i_interval;
// Lottery Variables
address private s_recentWinner;
// bool private s_isOpen; // to true, false
RaffleState private s_raffleState;
/* Events */
event RaffleEnter(address indexed player);
event RequestedRaffleWinner(uint256 indexed requestId);
event WinnerPicked(address indexed winner);
constructor(
address vrfCoordinatorV2, // contract
uint256 entranceFee,
uint64 subscriptionId,
bytes32 gasLane,
uint32 callbackGasLimit,
uint256 interval
) VRFConsumerBaseV2(vrfCoordinatorV2) {
i_entranceFee = entranceFee;
i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
i_gasLane = gasLane;
i_subscriptionId = subscriptionId;
i_callbackGasLimit = callbackGasLimit;
s_raffleState = RaffleState.OPEN;
s_lastTimeStamp = block.timestamp;
i_interval = interval;
}
function enterRaffle() public payable {
if (msg.value < i_entranceFee) {
revert Raffle_NotEnoughEthEntered();
}
if (s_raffleState != RaffleState.OPEN) {
revert Raffle_NotOpen();
}
s_players.push(payable(msg.sender));
// Events
emit RaffleEnter(msg.sender);
}
/**
* @dev This is the function that the Chainlink Keeper nodes call
* they look for the `upkeepNeeded` to return true
* The following should be true in order to return true:
* 1. Our time interval should have passed
* 2. The lottery should have at least 1 player, and have some ETH
* 3. Our subscription is funded with link
* 4. The lottery should be in an "open" state
*/
function checkUpkeep(
bytes memory /*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;
bool upkeepNeeded = (isOpen && timePassed && hasPlayers && hasBalance);
return (upkeepNeeded, "0x0");
}
function performUpkeep(bytes calldata /* performData */) external override {
(bool upkeepNeed, ) = checkUpkeep("");
if (!upkeepNeed) {
revert Raffle_UpkeepNotNeeded(
address(this).balance,
s_players.length,
uint256(s_raffleState)
);
}
s_raffleState = RaffleState.CALCULATING;
uint256 requestId = i_vrfCoordinator.requestRandomWords(
i_gasLane, //gasLane, maximum price you are going to pay in gwei
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; // % = undividable part
address payable recentWinner = s_players[indexOfWinner];
s_recentWinner = recentWinner;
s_raffleState = RaffleState.OPEN; // Reset the raffle state
s_players = new address payable[](0); // Reset the raffle address
s_lastTimeStamp = block.timestamp;
(bool success, ) = recentWinner.call{value: address(this).balance}("");
if (!success) {
revert Raffle_TransferFailed();
}
emit WinnerPicked(recentWinner);
}
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 (uint256) {
return i_entranceFee;
}
function getRaffleState() public view returns (RaffleState) {
return s_raffleState;
}
function getNumWords() public view returns (uint256) {
return NUM_WORDS;
}
function getNumberOfPlayers() public view returns (uint256) {
return s_players.length;
}
function getLatestTimeStamp() public view returns (uint256) {
return s_lastTimeStamp;
}
function getRequestConfirmations() public pure returns (uint256) {
return REQUEST_CONFIRMATIONS;
}
function getInterval() public view returns (uint256) {
return i_interval;
}
}
I am tackling this problem for couple of days now, I've tried everything but it just doesn't seem to work. Im having problem when I test the 01 deploy, the "doesnt allow entrance when raffle is calculating". Anyone any knowledge what to do.
Here is my raffle file
And my deploy file
And raffle.test.js file