How can I use the chainlink VRF to randomly get 4 numbers by calling the dealCards function?

46 Views Asked by At

I created the dealCards function to randomly select 4 numbers which will then passed to fulfillRandomWords to select 4 cards from the deck based on the 4 randomly selected numbers. When I call dealCards, I get an error that says

transact to Blackjack.dealCards errored: Error occured: revert.

revert
    The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.

I thought it was because I had to make the function payable but that doesn't seem to work either. Here is my code:

pragma solidity ^0.8.19;

import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "forge-std/console.sol";

contract Blackjack is VRFConsumerBaseV2 {
    error Blackjack__IncorrectRequestId(uint256);
    error Blackjack__RandomCardsNotYetGenerated();
    error Blackjack__NoWinnersYet();
    error Blackjack__NeedToSetNumCardsToOne();
    error Blackjack__NotPlayerTurn(bool);
    error Blackjack__MustSendBidFee(uint128);
    error MustStartGameFirst();

    VRFCoordinatorV2Interface immutable COORDINATOR;
    LinkTokenInterface immutable LINKTOKEN;
    // create variables of all 52 cards
    enum Rank {
        Ace,
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        Eight,
        Nine,
        Ten,
        Jack,
        Queen,
        King
    }
    enum Suit {
        Spades,
        Clubs,
        Hearts,
        Diamonds
    }

    struct Card {
        Rank rank;
        Suit suit;
        uint8 cardValue;
    }

    bool gameStarted;
    bool playerTurn;
    bool dealerTurn;

    bytes32 private immutable i_gasLane =
        0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c;
    
    uint64 private immutable i_subscriptionId = 7200;

    uint8 internal s_numCards = 4;
    uint8 s_playerValue;
    uint8 s_dealerValue;

    uint16 private constant REQUEST_CONFIRMATIONS = 3;
    uint32 constant callbackGasLimit = 2500000;

    // uint128 constant BID_FEE = 0.001 ether;

    Card[] s_randomResult;
    uint256 internal desiredRange = 52;
    uint256 public s_requestId;

    address s_owner;

    Card[] public deck;

    event Blackjack__RandomWordsRequested(uint256 indexed requestId);
    event Blackjack__ReturnedRandomness(Card[]);
    event Blackjack__PlayerWins();
    event Blackjack__Push();
    event Blackjack__DealerWins();
    event Blackjack__CardValue(uint8 cardValue);

    modifier onlyOwner() {
        require(msg.sender == s_owner);
        _;
    }

    constructor()
        VRFConsumerBaseV2(0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625)
    {
        COORDINATOR = VRFCoordinatorV2Interface(
            0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625
        );
        LINKTOKEN = LinkTokenInterface(
            0x779877A7B0D9E8603169DdbD7836e478b4624789
        );
        s_owner = msg.sender;

        for (uint256 i = 0; i < 52; i++) {
            // Calculate rank and suit based on index
            Rank cardRank = Rank(i % 13); // 13 ranks
            Suit cardSuit = Suit(i / 13); // 4 suits

            // Convert enum to uint for comparison
            uint8 rankValue = uint8(cardRank);
            // check for aces and assign value of 1
            // Initialize card for each index of the deck array
            if (rankValue == 0) {
                deck.push(Card(cardRank, cardSuit, 1)) ;
            } else if (rankValue >= 1 && rankValue <= 8) {
                deck.push(Card(cardRank, cardSuit, rankValue + 1)) ;
            } else {
                deck.push(Card(cardRank, cardSuit, 10)) ;
            }
        }
    }

    // create function to start game
    function startGame() public {
        if (s_numCards != 4) {
            s_numCards = 4;
        }
        // dealCards();
        gameStarted = true;
        playerTurn = true;
    }

    function dealCards() public returns (uint256) {
         
        if (!gameStarted) {
            revert MustStartGameFirst();
        }
        
            s_requestId = COORDINATOR.requestRandomWords(
            i_gasLane, // keyHash
            i_subscriptionId,
            REQUEST_CONFIRMATIONS,
            callbackGasLimit,
            s_numCards
            );
        emit Blackjack__RandomWordsRequested(s_requestId);
        return s_requestId;
    }

    // implement the VRF to randomly select cards from the deck
    function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords)
        internal
        override
    {
        if (requestId != s_requestId) {
            revert Blackjack__IncorrectRequestId(requestId);
        }
        uint256 cardIndex;
        // Process each random number received
        for (uint256 i = 0; i < randomWords.length; i++) {
            // Ensure the random number is within the desired range (0-51)
            cardIndex = randomWords[i] % desiredRange;   
            s_randomResult.push(deck[cardIndex]);
        }
      
        emit Blackjack__ReturnedRandomness(s_randomResult);
    }
}
0

There are 0 best solutions below