1

I was following along with a Patrick Collins tutorial when I came across an error while trying to view the subscriptionId from inside transactionReceipt.

This is my code:

    const { network, ethers } = require("hardhat");
    const { deploymentChains, networkConfig } = require("../helper-hardhat-config");
    const { verify } = require("../utils/verify");
    require("dotenv").config();

    module.exports = async function ({ deployments, getNamedAccounts }) {
        const { deployer } = await getNamedAccounts();
        const { deploy, log } = deployments;
        let VRFCoordinatorV2Address, subscriptionId;
        const chainId = network.config.chainId;
        const VRF_SUB_AMOUNT = ethers.parseEther("2");
        const entranceFee = networkConfig[chainId]["entranceFee"];
        const gasLane = networkConfig[chainId]["gasLane"];
        const callbackGasLimit = networkConfig[chainId]["callbackGasLimit"];
        const interval = networkConfig[chainId]["interval"];

        if (deploymentChains.includes(network.name)) {
            const VRFCoordinator = await ethers.getContract("VRFCoordinatorV2Mock");
            VRFCoordinatorV2Address = VRFCoordinator.address;
            const transactionResponse = await VRFCoordinator.createSubscription();
            const transactionReceipt = await transactionResponse.wait(1);
            subscriptionId = transactionReceipt.events[0].args.subId;
            await VRFCoordinator.fundSubscription(subscriptionId, VRF_SUB_AMOUNT);
        } else {
            VRFCoordinatorV2Address = networkConfig[chainId]["VRFCoordinatorAddress"];
            subscriptionId = networkConfig[chainId]["subscriptionId"];
        }

        const args = [
            VRFCoordinatorV2Address,
            entranceFee,
            gasLane,
            subscriptionId,
            callbackGasLimit,
            interval,
        ];
        const raffle = await deploy("Raffle", {
            from: deployer,
            log: true,
            args: args,
            waitConfirmations: network.config.blockConfirmations,
        });
        if (!deploymentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) {
            await verify(raffle.address, args);
        }
        log("----------------------------------------------");
    };

    module.exports.tags = ["all", "raffle"];

This is the error I'm getting:

this is the error im getting

I've noticed that the error is coming from the line subscriptionId = transactionReceipt.events[0].args.subId;, can anyone tell me why this is happening?

This is the smart contract code:

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

    import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
    import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
    import "@chainlink/contracts/src/v0.8/AutomationCompatible.sol";

    /*errors*/
    error Raffle__NotEnoughETHentered();
    error Raffle__TransferFailed();
    error Raffle__NotOpen();
    error Raffle__upKeepNotNeeded(uint256 balance, uint256 numPlayers, uint256 raffleState);

    contract Raffle is VRFConsumerBaseV2, AutomationCompatibleInterface {
        enum RaffleState {
        OPEN,
        CALCULATING
        }

        uint256 private immutable i_entranceFee;
        address payable[] private s_players;
        uint256 private s_requestId;
        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;
        VRFCoordinatorV2Interface private immutable i_vrfcoordinator;

        /*lottery variables*/
        address private s_recentWinner;
        RaffleState private s_raffleState;
        uint256 private s_lastTimeStamp;
        uint256 private immutable i_interval;

        /*Events*/
        event RaffleEnter(address payable indexed player);
        event RequestedRaffleWinner(uint256 requestId);
        event WinnerPicked(address indexed Winner);

        /*Functions*/
        constructor(
            address VRFCoordinatorV2,
            uint256 entranceFee,
            bytes32 gasLane,
            uint64 subscriptionId,
            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));
            emit RaffleEnter(payable(msg.sender));
        }

        function checkUpkeep(
        bytes memory /*checkData*/
    ) public override returns (bool upkeepNeeded, bytes memory /*performData*/) {
            bool isOpen = (RaffleState.OPEN == s_raffleState);
            bool timePassed = (block.timestamp - s_lastTimeStamp > i_interval);
            bool hasBalance = (address(this).balance > 0);
            bool hasPlayers = (s_players.length > 0);
            upkeepNeeded = (isOpen && timePassed && hasBalance && hasPlayers);
        }

        function performUpkeep(bytes calldata /*performData*/) external override {
            (bool upkeepNeeded, ) = checkUpkeep("");
            if (!upkeepNeeded) {
                revert Raffle__upKeepNotNeeded(
                    address(this).balance,
                    s_players.length,
                    uint256(s_raffleState)
                );
            }
            s_raffleState = RaffleState.CALCULATING;
            s_requestId = i_vrfcoordinator.requestRandomWords(
                i_gasLane,
                i_subscriptionId,
                REQUEST_CONFIRMATIONS,
                i_callbackGasLimit,
                NUM_WORDS
            );
            emit RequestedRaffleWinner(s_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;
            (bool success, ) = recentWinner.call{value: address(this).balance}("");
            s_players = new address payable[](0);
            s_lastTimeStamp = block.timestamp;
            if (!success) {
                revert Raffle__TransferFailed();
            }
            emit WinnerPicked(recentWinner);
            s_raffleState = RaffleState.OPEN;
        }

        /*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 pure returns (uint32) {
            return NUM_WORDS;
        } 

        function getNumOfPlayers() public view returns (uint256) {
            return s_players.length;
        }

        function getLatestTimeStamp() public view returns (uint256) {
            return s_lastTimeStamp;
        }

        function getRequestConfirmations() public pure returns (uint16) {
            return REQUEST_CONFIRMATIONS;
        }
    }
2
  • There may be no error in the subscription part. Can you provide the smart contract code, and constructor part, as you may pass arguments in incorrect order?
    – Al-Qa'qa'
    Sep 11, 2023 at 14:11
  • hey i've added the smart contract code. can u check it. thank you! @ Al-Qa'qa'
    – Gautam
    Sep 11, 2023 at 15:04

1 Answer 1

0

The error is coming from the 0 inside of subscriptionId = transactionReceipt.events[0].args.subId;, which probably means that the events object is not returning the expected value, to see what is being returned try adding a console.log(transactionReceipt) and then a console.log(transactionReceipt.events) object.

If the second console.log doesn't return an object with the variables that were emitted in the event, try console.log(transactionReceipt.logs). If you see the expected values here, take it a step further by trying to access the variable directly:

subscriptionId = BigInt(transactionReceipt.logs[0].topics[1])

The change in syntax might be due to varying ethers versions since ethers v6 seems to have introduced a massive amount of changes from the previous version.

3
  • 1
    yea it worked for me . I found the subId variable in {console.log(transactionReceipt.logs[0].args)} and further by doing {transactionReceipt.logs[0].args.subId} i got it solved. and yeah its also working the other way ie. {transactionReceipt.logs[0].topics[1]}. Thanks alot! . [update in deploy code]: i was getting another error with the line {VRFCoordinatorV2Address = VRFCoordinator.address;} so, i changed it to {VRFCoordinatorV2Address = VRFCoordinator.target;} and its working.
    – Gautam
    Sep 12, 2023 at 6:40
  • @Gautam no problem glad to help! Make sure to mark the answer as solved whenever you get a chance!
    – Rohan Nero
    Sep 12, 2023 at 15:14
  • could u also plz check this out ethereum.stackexchange.com/questions/154542/…
    – Gautam
    Sep 16, 2023 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.