eac
eac

Reputation: 1

Requesting random number on Chainlink Testnet and getting zeroes

I have been working on something that encapsulates chainlink random number on nfts to provide them to users, using a chainlink subscription and adding my smart contract as a comsumer. When working on testnet I am finding some times it gives me zero numbers and not a random one. This behaviour is random. Subscription is funded and smart contract added as a comsumer.

May this happen on mainnet also?

On most cases this kind of errors are only testnet timeouts, or other stuff related to slower infrastructure.

I wish to implement something to prevent shipping the NFT when zeroes are recevied:

I tried to put assert(randomNumber!=[zero]); but I got some errors, as gas stimation functions on wallets can ensure this, so they set highest fee.

Any suggestions to keep this secured?

This is the main testnet smart contract bsc address https://testnet.bscscan.com/address/0x74623BaE2c3AcC39Db224c236229dc4d5aD1F64d#code

is there any warranty the request random number operation finishes succesfully, or how can I take care of it on my code?

I have posted chainlink related functions too, where I slice the numbers to get them one by one in the lottery.

Subscription is funded and smart contract added as a comsumer. geting some times zero numbers and not a random one

these are the two functions

    function closeSaleGetWinner()
        external
        nonReentrant
        onlyRole(OPERATOR_ROLE)
    {
        requestRandomWords();

        require(
            isDrawLive,
            "There's not a live draw neither ticket sale is opened"
        );
        uint256[6] memory numberOfMatches;
        uint256 drawPrice;

        // set the total pool price to BUSD smart contract balance

        drawPrice =
            checkBUSDContractBalance() *
            allDraws[currentDraw].poolPercentage; // use 1 * 10**18 for use the whole pool

        // close ticket sale and get random winner number from s_randomWords

        isDrawLive = false;

        //assert(s_randomWords[0]!=0);


        allDraws[currentDraw].winnerNumber = s_slicedRandomWords;
        //unchecked {
        uint256 j;
        Ticket storage _ticket;
        uint256 _match;
        // check and update matched numbers per ticket on allTickets structure
        for (uint256 i = 0; i < drawToTickets[currentDraw].length; i++) {
            j = drawToTickets[currentDraw][i];
            _ticket = allTickets[j];
            _match = checkWinner(_ticket);
            _ticket.matchedNumbers = _match;
            numberOfMatches[_match] = numberOfMatches[_match] + 1;
        }

        // after storing number of winners with [_match] matches calculate win per group

        // it's time to overwrite reward variable with
        // 1st the part of the price from the total pool for #i number of matches
        // 2nd divide e
        for (uint256 i = 0; i < 5; i++) {
            allDraws[currentDraw].reward[i] =
                allDraws[currentDraw].reward[i] *
                drawPrice;
            if (numberOfMatches[i + 1] > 0) {
                allDraws[currentDraw].reward[i] = SafeMath.div(
                    allDraws[currentDraw].reward[i],
                    numberOfMatches[i + 1]
                );
            } else {
                allDraws[currentDraw].reward[i] = 0;
            }
        }

        // once stored delete random generated number for further checks
        delete (s_randomWords);
        delete (s_slicedRandomWords);
    }

    /*
    compares the ticket number with the winner number of the draw and returns a value
    representing matched number between 0 to 5 (6 values)
    */

    function checkWinner(Ticket storage t) internal view returns (uint256) {
        uint256 _match = 0;

        // we go and compare digit by digit storing number of consecutive matches and stopping when
        // there are no more coincidences

        uint256[5] memory ticketNumber = t.number;
        uint256[5] memory winnerNumber = allDraws[_drawIdCounter.current() - 1]
            .winnerNumber;

        for (uint256 i = 0; i < 5; i++) {
            // If there exists any distinct
            // lastTicketDigit, then return No
            if (ticketNumber[i] == winnerNumber[i]) {
                _match = _match + 1;
            } else return _match;
        }
        return _match;
    }



    function buyRandomTicket() public nonReentrant {
        
        uint256[] storage myTickets = accounts[msg.sender].myTicketsHistory;
        require(isDrawLive, "Sorry there's no live draw by now");

        require(!Address.isContract(msg.sender), "only EOA allowed");

        address user = address(msg.sender);
        uint256 _value = allDraws[currentDraw].ticketPrice;

        // check balance and user allowance

        uint256 busdUserBalance = BUSD.balanceOf(msg.sender);
        require(busdUserBalance >= _value, "Not enough balance");

        uint256 allowance = BUSD.allowance(msg.sender, address(this));
        require(allowance >= _value, "Check the BUSD allowance");

        uint256 devsReward = _value.mul(5).div(100);

        uint256 otherReward = _value.mul(20).div(100);

        // get payment

        BUSD.safeTransferFrom(msg.sender, address(this), _value);

        requestRandomWords();

        BUSD.safeTransfer(w1, devsReward);

        BUSD.safeTransfer(w2, devsReward);

        BUSD.safeTransfer(w3, otherReward);

        /*pay referral*/
        if (accounts[msg.sender].referrer != address(0))
            payReferral(_value, address(msg.sender));

        Ticket memory randomTicket = Ticket(
            user,
            currentDraw,
            _ticketIdCounter.current(),
            s_slicedRandomWords,
            false,
            0
        );
        //require(s_randomWords[0]!=0);

        uint256[] storage drawTickets = drawToTickets[currentDraw];
        // add to the mapping to store tickets sold for a draw
        drawTickets.push(randomTicket.ticketID);
        myTickets.push(randomTicket.ticketID);
        allTickets.push(randomTicket);

        safeMint(user);

        // set to 0 random storage variable for further checks
        delete (s_randomWords);
        delete (s_slicedRandomWords);
    }

/* CHAINLINK FUNCTIONS */

    // Assumes the subscription is funded sufficiently.
    function requestRandomWords() internal {
        // Will revert if subscription is not set and funded.
        s_requestId = COORDINATOR.requestRandomWords(
            keyHash,
            s_subscriptionId,
            requestConfirmations,
            callbackGasLimit,
            numWords
        );
    }

    function fulfillRandomWords(
        uint256, /* requestId */
        uint256[] memory randomWords
    ) internal override {
        uint256 _lastDigit;
        s_randomWords = randomWords;
        uint256 aux = randomWords[0];
        for (uint256 i = 0; i < 5; i++) {
            _lastDigit = aux % 10;
            s_slicedRandomWords[i] = _lastDigit;
            aux = aux / 10;
        }
    }
    ```

Upvotes: 0

Views: 160

Answers (0)

Related Questions