Cyfrin / foundry-smart-contract-lottery-cu

47 stars 38 forks source link

Error: No arguments passed to the base constructor. Specify the arguments or mark "Raffle" as abstract. #49

Closed Fausi89 closed 4 months ago

Fausi89 commented 4 months ago

Hey,

I did not have this issue before, but suddenly today I get this error when I try to run (forge build), I don't get it why I have to mark the contract as abstract. It seems it has to do with importing VRFConsumerBaseV2, because it is an abstract contract.

Error: Compiler run failed: Error (3415): No arguments passed to the base constructor. Specify the arguments or mark "Raffle" as abstract. --> src/Raffle.sol:34:1: 34 contract Raffle is VRFConsumerBaseV2 { ^ (Relevant source part starts here and spans across multiple lines). Note: Base constructor parameters: --> lib/chainlink-brownie-contracts/contracts/src/v0.8/VRFConsumerBaseV2.sol:104:14:
104 constructor(address _vrfCoordinator) {

This is the code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {VRFCoordinatorV2Interface} from "lib/chainlink-brownie-contracts/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import {VRFConsumerBaseV2} from "lib/chainlink-brownie-contracts/contracts/src/v0.8/VRFConsumerBaseV2.sol";

/**
 * @title A sample Raffle Contract
 * @author Fouzi Matar
 * @notice This contract is for creating a sample raffle
 * @dev Implements Chainlink VRF v2.0 
*/
contract Raffle is VRFConsumerBaseV2 {
    error Raffle__NotEnoughEthSent(); // 2 underscores -- custom error
    error Raffle__TransferFailed();
    error Raffle__RaffleNotOpen();

    /** Type Declaration */
    enum RaffleState {
        OPEN,  // 0
        CALCULATING // 1
    }

    /** State Variables */
    uint16 private constant REQUEST_CONFIRMATIONS = 3; // all upper case because it is a constant
    uint256 private constant CALLBACK_GAS_LIMIT = 200000;
    uint32 private constant NUM_WORDS = 1;

    uint256 private immutable i_entranceFee;
    uint256 private immutable i_interval; // @dev interval is the duration of the raffle in seconds
    VRFCoordinatorV2Interface private immutable i_vrfCoordinator; // Chainlink VRF Coordinator
    bytes32 private immutable i_keyHash;
    uint64 private immutable i_subscriptionId;
    uint32 private immutable i_callbackGasLimit;

    address payable[] private s_players; // storage variable because it is going to change over time
    uint256 private s_lastTimeStamp;
    address private s_recentWinner;
    RaffleState private s_raffleState;

    /** Events */
    event EnteredRaffle(address indexed player);
    event PickedWinner(address indexed winner);

    // we use a dynamic array to keep track of all players

    constructor(uint256 entranceFee, uint256 interval, address vrfCoordinator, bytes32 keyHash, uint64 subscriptionId, uint32 callbackGasLimit) {
        i_entranceFee = entranceFee;
        i_interval = interval;
        i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinator);
        i_keyHash = keyHash;
        i_subscriptionId = subscriptionId;
        i_callbackGasLimit = callbackGasLimit;

        s_raffleState = RaffleState.OPEN;
        s_lastTimeStamp = block.timestamp; // here we set the starting time at the moment we launch the contract

    }

    function enterRaffle() external payable {
       // require(msg.value >= i_entranceFee, "Not enough ETH to enter the raffle");  using custom error with if statement is gas efficient
       if(msg.value < i_entranceFee) {
           revert Raffle__NotEnoughEthSent();
       }
       if (s_raffleState != RaffleState.OPEN) {
           revert Raffle__RaffleNotOpen();
       }

       s_players.push(payable(msg.sender));
       // whenever we update storage we need to emit an event
       // 1. makes migration easier  2. makes front end indexing easier
       emit EnteredRaffle(msg.sender);
    }

    // 1. Get a random number
    // 2. use the random number to pick a winner
    // 3. be automatically called when the raffle is over
    function pickWinner() external {
        // check to see if enough time has passed
       if ((block.timestamp - s_lastTimeStamp) < i_interval) {
            revert();
       }
        s_raffleState = RaffleState.CALCULATING;
        // how to get a random number from chainlink VRF
        // 1. Request the RNG
        // 2. Get the random number
        // Will revert if subscription is not set and funded.
        uint256 requestId = i_vrfCoordinator.requestRandomWords(
            i_keyHash, // gas lane
            i_subscriptionId,
            REQUEST_CONFIRMATIONS,
            i_callbackGasLimit,
            NUM_WORDS
        );
    }

     function fulfillRandomWords(
        uint256 _requestId,
        uint256[] memory randomWords
    ) internal override {
        //we will use modular arithmetic to get a random index
        uint256 indexOfWinner = randomWords[0] % s_players.length;
        address payable winner = s_players[indexOfWinner];
        s_recentWinner = winner;
        s_raffleState = RaffleState.OPEN; // then we have to reset the array
        s_players = new address payable[](0); // reset the array
        s_lastTimeStamp = block.timestamp; // reset the timestamp    
        (bool success,) = winner.call{value: address(this).balance}("");
        if (!success) {
            revert Raffle__TransferFailed();
        }
        emit PickedWinner(winner);
    }

    /** Getter Function */
    function getEntranceFee() external view returns(uint256) {
        return i_entranceFee;
    }
}  

Thanks

PatrickAlphaC commented 4 months ago

Check out this line, it looks like you're missing it!

https://github.com/Cyfrin/foundry-smart-contract-lottery-f23/blob/bb1469a7534ebcf0c3b7ea2f5574f40e4ef851ec/src/Raffle.sol#L81