Skip to content
This repository was archived by the owner on May 17, 2024. It is now read-only.

Getting error TypeError: Cannot read properties of undefined (reading '0') in Lesson 9 #182

Open
haaarshit opened this issue Aug 10, 2023 · 6 comments

Comments

@haaarshit
Copy link

haaarshit commented Aug 10, 2023

Getting error in Lesson 9 Error: ERROR processing /root/hardhat-fcc/hardhat-smartcontract-lottery-fcc/deploy/01-deploy-raffle.js: TypeError: Cannot read properties of undefined (reading '0')

**Error occurring at line 23 **
Code at line 23 > subscriptionId = transactionReceipt.events[0].args.subId

My 01-deploy-raffle.js file

const { network, ethers } = require("hardhat")
const { networkConfig, developmenChain } = require("../helper-hardhat-conifg")
const {verify} = require("../utils/verify")

const VRF_SUB_FUND_AMOUNT = ethers.parseEther("30")

module.exports = async function ({ getNamedAccounts, deployments }) {
    const { deployer } = await getNamedAccounts()
    const { deploy, log } = deployments
    const chainId = network.config.chainId
    let vrfCoordinatorV2Address, subscriptionId

    if (developmenChain.includes(network.name)) {
        log("local network detected: deploying mocks....")

        const VRF2CordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
        vrfCoordinatorV2Address = VRF2CordinatorV2Mock.runner.address

        // console.log(VRF2CordinatorV2Mock)
        const transactionResponse = await VRF2CordinatorV2Mock.createSubscription()
        const transactionReceipt = await transactionResponse.wait(1)
        subscriptionId = transactionReceipt.events[0].args.subId
        // Fund subscription
        // Usually you had need the link token on a real network
        // on local network -> fund the subscrition without link token
        await VRF2CordinatorV2Mock.fundSubscription(subscriptionId, VRF_SUB_FUND_AMOUNT)
    } else {
        vrfCoordinatorV2Address = networkConfig[chainId]["vrfCoordinator"]
        subscriptionId = networkConfig[chainId]["subscriptionid"]
    }

    const entranceFee = networkConfig[chainId]["entranceFee"]
    const gasLane = networkConfig[chainId]["gasLane"]
    const gasLimit = networkConfig[chainId]["callbackGasLimit"]
    const intervel = networkConfig[chainId]["intervel"]


    const args = [vrfCoordinatorV2Address, entranceFee, gasLane, subscriptionId, gasLimit, intervel]
    const raffle = await deploy("Raffle", {
        from: deployer,
        args: args,
        log: true,
        waitConfirmations: network.config.blockConfirmations || 1,
    })

    if(!developmenChain.includes(network.name) && process.env.ETHERSCAN_API){
        log("Verifying.....")
        verify(raffle.address,args)
        log("-----------------------------------------")
    }
}

module.exports.tags = ["all","raffle"]
@Plycedes
Copy link

I have the same issue. Have you found a solution??

@haaarshit
Copy link
Author

I have the same issue. Have you found a solution??

Well half of the problem get solved

we can use this syntax to extract subscriptionId

 subscriptionId = transactionReceipt.logs[0].args.subId

instead of this syntax

subscriptionId = transactionReceipt.events[0].args.subId 

but still getting this error

 Error: Transaction reverted: function call to a non-contract account
    at Raffle.performUpkeep (contracts/Raffle.sol:128)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1840:23)
    at HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:517:16)
    at EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1532:18)
    at HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:123:18)
    at HardhatEthersSigner.sendTransaction (node_modules/@nomicfoundation/hardhat-ethers/src/signers.ts:125:18)
    at send (node_modules/ethers/src.ts/contract/contract.ts:299:20)
  

@haaarshit
Copy link
Author

I have the same issue. Have you found a solution??

I have got the solution visit -> solution

You can visit the github repo for the code repo

@dustinstacy
Copy link

dustinstacy commented Aug 22, 2023

I have got the solution visit ->
solution

You can visit the github repo for the code
repo

@coderharsx1122! has provided a solution for this issue if you are working with ethers v5. (see
quote or comment above)

If you happen to be stubborn like myself and want to migrate the project to ethers v6 with Typescript, I have found
a solution for this as well.

  1. First step is to add 'get' to the line where you destructure deployments
    const { deploy, log, get } = deployments
  1. Next, since we dont have access to ethers.getContract we need to attack this a different way.
    Inside your if statement will start like this:
    const vrfCoordinatorV2MockDeployment = await get('VRFCoordinatorV2Mock')
    vrfCoordinatorV2Address = vrfCoordinatorV2MockDeployment.address
    const vrfCoordinatorV2Mock = await ethers.getContractAt(
        'VRFCoordinatorV2Mock',
        vrfCoordinatorV2Address
    )

Here, we use the get() function to obtain the VRFCoordinatorV2Mock deployment. After that we use
the deployment to obtain the address. Now that we have the address, we can go ahead and call the
ethers v6 method of getContractAt() which requires an address.

  1. With our contract stored in vrdCoordinatorV2Mock we can now go ahead and continue with the
    transaction variables same way as we did before:
    const transactionResponse = await vrfCoordinatorV2Mock.createSubscription()
    const transactionReceipt = await transactionResponse.wait()
  1. Finally we get to the line where the original error occurs. This error was a result of Typescript complaining to us that property events does not exist on type ContractTransactionReceipt:
    subscriptionId = transactionReceipt.events[0].args.subId 

Instead we are going to access the topics array inside the logs array. Following with Patrick's
logic while discussing events, we find the the createSubscription() function does indeed emit an
event, where the _subId is indexed. Which again following along would get stored in topics.
Looking inside transactionReceipt.log[0] we do see a topics array:

EventLog {
...
  transactionHash: '0x88aa88df59f71d37e77fbaee3a34467d7191d4c7d2450e85b5cffe5d87edd4af',
  blockHash: '0x5c623a4e5f6bd31976133b0fa9d40ce83260b9683e579387906e0d9b5f7a77db',
  blockNumber: 2,
  removed: undefined,
  address: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
  data: '0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  topics: [
    '0x464722b4166576d3dcbba877b999bc35cf911f4eaf434b7eba68fa113951d0bf',
    '0x0000000000000000000000000000000000000000000000000000000000000001'
  ],
...
}

I've since found out that the first index, [0], of the topics array will always be the event signature hash. What's important though is the next index, [1], is the indexed parameter of the event which is our subscriptionId!

So let's go ahead a put in the last two lines of code as follows:

        subscriptionId = transactionReceipt!.logs[0].topics[1]
        await vrfCoordinatorV2Mock.fundSubscription(subscriptionId, VRF_SUB_FUND_AMOUNT)

_A cheat code for this it to just set subscriptionId = to any number in string form i.e. '1', '11', '34235', etc., but where's the fun in that?

Here is the completed if statement for reference:

    if (devChains.includes(network.name)) {
        const vrfCoordinatorV2MockDeployment = await get('VRFCoordinatorV2Mock')
        vrfCoordinatorV2Address = vrfCoordinatorV2MockDeployment.address
        const vrfCoordinatorV2Mock = await ethers.getContractAt(
            'VRFCoordinatorV2Mock',
            vrfCoordinatorV2Address
        )
        const transactionResponse = await vrfCoordinatorV2Mock.createSubscription()
        const transactionReceipt = await transactionResponse.wait()
        subscriptionId = transactionReceipt!.logs[0].topics[1]
        await vrfCoordinatorV2Mock.fundSubscription(subscriptionId, VRF_SUB_FUND_AMOUNT)
    } else {
    ...
    }

Interested to hear anybody else's results utilizing this change. I'll keep this updated if this triggers any further issues down the line (as they usually do). e (as they usually do).

Also, would love to connect with anyone else looking to work through this tutorial with the updated ethers library and TS as I'm sure there are plenty of opportunities to troubleshoot.

@praisezee
Copy link

praisezee commented Sep 17, 2023

Found a solution. I added the gasLane value to the hardhat chainId in the hardhat-helper-config.js then I hard coded the subscriptionId value to 1

@danielvichinyan
Copy link

Use this:
subscriptionId = txReceipt.logs[0].topics[1];
instead of this:
subscriptionId = transactionReceipt.events[0].args.subId;

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants