PatrickAlphaC / hardhat-smartcontract-lottery-fcc

MIT License
117 stars 183 forks source link

Lesson 9: Staging test error `Error: cannot estimate gas` #205

Open ilkinm03 opened 3 months ago

ilkinm03 commented 3 months ago

I deployed my contract. But forgot to add

mocha: {
     timeout: 500000
}

So I get a timeout error as expeced. Then I added the timeout option and ran the test command hh test --network sepolia again. But now it throws another error.

Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (reason="execution reverted", method="estimateGas", transaction={"from":"0xa39c478295F192A11ce9b6bFBF64240f0f0b3843","to":"0xAd170C5ca3091862c1f0C90FA0Ae4D46e7EB4D01","value":{"type":"BigNumber","hex":"0x2386f26fc10000"},"data":"0xc1af5785","accessList":null}, error={"name":"ProviderError","_stack":"ProviderError: execution reverted\n at HttpProvider.request (decentralized-lottery/node_modules/hardhat/src/internal/core/providers/http.ts:90:21)\n at processTicksAndRejections (node:internal/process/task_queues:95:5)\n at EthersProviderWrapper.send (decentralized-lottery/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)","code":3,"_isProviderError":true,"data":"0xe76be6fc"}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.7.2)

Here's my staging test source code:

 const { assert, expect, ...chai } = require("chai");
const { solidity } = require("ethereum-waffle");
const { getNamedAccounts, ethers, network } = require("hardhat");
const { DEVELOPMENT_CHAINS } = require("../../helper-hardhat.config");

chai.use(solidity);

DEVELOPMENT_CHAINS.includes(network.name)
    ? describe.skip
    : describe("Lottery Staging", () => {
        let lottery, lotteryEntranceFee, deployer;

        beforeEach(async () => {
            deployer = (await getNamedAccounts()).deployer;
            lottery = await ethers.getContract("Lottery", deployer);
            lotteryEntranceFee = await lottery.getEntranceFee();
        });

        describe("fulfillRandomWords", () => {
            it("should work with live ChainLink Keepers and VRF and get a random winner", async () => {
                console.log("Setting up test...")
                let winnerStartingBalance;
                const startingTs = await lottery.getLatestTimestamp();
                const [deployerAccount] = await ethers.getSigners();
                console.log("Setting up Listener...")
                await new Promise(async (resolve, reject) => {
                    lottery.once("WinnerPicked", async () => {
                        console.log("WinnerPicked event triggered!");
                        try {
                            const recentWinner = await lottery.getRecentWinner();
                            const lotteryState = await lottery.getLotteryState();
                            const winnerEndingBalance = await deployerAccount.getBalance();
                            const endingTs = await lottery.getLatestTimestamp();
                            await expect(lottery.getPlayer(0)).to.be.reverted;
                            assert.equal(recentWinner.toString(), deployerAccount.address);
                            assert.equal(lotteryState, 0);
                            assert.equal(
                                winnerEndingBalance.toString(),
                                winnerStartingBalance
                                    .add(lotteryEntranceFee)
                                    .toString(),
                            );
                            assert(endingTs > startingTs);
                            resolve();
                        } catch (error) {
                            console.error(error);
                            reject(error);
                        }
                    });
                    try {
                        console.log("Entering Lottery...")
                        const tx = await lottery.enterLottery({ value: lotteryEntranceFee });
                        await tx.wait(1);
                        console.log("Ok, time to wait...")
                        winnerStartingBalance = await deployerAccount.getBalance();
                    } catch (error) {
                        console.error(error);
                        reject(error);
                    }
                });
            });
        });
    });

And here's hardhat.config.js file:

require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-etherscan");
require("hardhat-deploy");
require("hardhat-gas-reporter");
require("hardhat-contract-sizer");
require("solidity-coverage");
require("dotenv").config();
const { vars } = require("hardhat/config");

const { REPORT_GAS_FEATURE } = process.env;

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
    solidity: "0.8.24",
    defaultNetwork: "hardhat",
    networks: {
        hardhat: {
            chainId: 31377,
            blockConfirmations: 1,
        },
        sepolia: {
            chainId: 11155111,
            blockConfirmations: 6,
            url: vars.get("SEPOLIA_RPC_URL"),
            accounts: [vars.get("PRIVATE_KEY")],
            saveDeployments: true,
        },
    },
    etherscan: {
        apiKey: vars.get("ETHERSCAN_API_KEY"),
    },
    gasReporter: {
        enabled: REPORT_GAS_FEATURE === "true",
        currency: "USD",
        noColors: true,
        outputFile: "gas-report.txt",
        coinmarketcap: vars.get("COINMARKETCAP_API_KEY"),
    },
    namedAccounts: {
        deployer: {
            default: 0,
            1: 0,
        },
        player: {
            default: 1,
        },
    },
    mocha: {
        timeout: 500000,
    },
};
PatrickAlphaC commented 3 months ago

hmm... yes it's having a hard time estimating the gas costs... This might be a good one to skip the staging test on. A lot of the chainlink VRF stuff is really tricky on a testnet. Testnets aren't very reliable for running staging tests sadly.