Error Received:
Error: ERROR processing /Users/ty/blockchainLearning/Lottery-Smart-Contract/deploy/01-deploy-raffle.ts:
Error: No Contract deployed with name VRFCoordinatorV2Mock
at Object.getContract (/Users/ty/blockchainLearning/Lottery-Smart-Contract/node_modules/@nomiclabs/hardhat-ethers/src/internal/helpers.ts:447:11)
My hunch is that Mocks is not being deployed properly in 00-deploy-mocks.ts. When I deploy the the mocks and and raffle.ts file, they run perfectly fine however when I run yarn hardhat deploy –network rinkeby I run into this error.
My 00-deploy-mocks.ts:
import { getNamedAccounts, deployments, network, ethers } from "hardhat"
import { DeployFunction } from "hardhat-deploy/types"
import { HardhatRuntimeEnvironment } from "hardhat/types"
const BASE_FEE = "250000000000000000" // 0.25 is this the premium in LINK?
const GAS_PRICE_LINK = 1e9 // link per gas, is this the gas lane? // 0.000000001 LINK per gas
const deployMocks: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, network } = hre
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
const chainId = network.config.chainId
// If we are on a local development network, we need to deploy mocks!
if (chainId == 31337) {
log("Local network detected! Deploying mocks...")
await deploy("VRFCoordinatorV2Mock", {
from: deployer,
log: true,
args: [BASE_FEE, GAS_PRICE_LINK],
})
log("Mocks Deployed!")
log("----------------------------------")
log("You are deploying to a local network, you'll need a local network running to interact")
log(
"Please run `yarn hardhat console --network localhost` to interact with the deployed smart contracts!"
)
log("----------------------------------")
}
}
export default deployMocks
deployMocks.tags = ["all", "mocks"]
My 01-deploy-raffle.ts:
import { LogDescription } from "@ethersproject/abi"
import { ethers, network } from "hardhat"
import { DeployFunction } from "hardhat-deploy/dist/types"
import { HardhatRuntimeEnvironment } from "hardhat/types"
import {
developmentChains,
networkConfig,
VERIFICATION_BLOCK_CONFIRMATIONS,
} from "../helper-hardhat-config"
import verify from "../utils/verify"
const VRF_SUB_FUND_AMOUNT = "1000000000000000000000"
const deployRaffle: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, network, ethers } = hre
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
// const chainID = network.config.chainId
const chainID = 31337
let vrfCoordinatorV2Address, subscriptionID
// if on developement chain
if (chainID == 31337) {
const vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
vrfCoordinatorV2Address = vrfCoordinatorV2Mock.address
const txnResponse = await vrfCoordinatorV2Mock.createSubscription()
const txnReceipt = await txnResponse.wait()
subscriptionID = txnReceipt.events[0].args.subId
// Fund the subscription
await vrfCoordinatorV2Mock.fundSubscription(subscriptionID, VRF_SUB_FUND_AMOUNT)
} else {
// else if not on local network
vrfCoordinatorV2Address = networkConfig[network.config.chainId!]["vrfCoordinatorV2"]
subscriptionID = networkConfig[network.config.chainId!]["subscriptionId"]
}
const waitBlockConfirmations = developmentChains.includes(network.name)
? 1
: VERIFICATION_BLOCK_CONFIRMATIONS
log("----------------------------------------------------")
const entranceFee = networkConfig[network.config.chainId!]["entranceFee"]
const gasLane = networkConfig[network.config.chainId!]["gasLane"]
const callbackGasLimit = networkConfig[network.config.chainId!]["callbackGasLimit"]
const interval = networkConfig[network.config.chainId!]["interval"]
const args = [
vrfCoordinatorV2Address,
entranceFee,
gasLane,
subscriptionID,
callbackGasLimit,
interval,
]
const raffle = await deploy("Raffle", {
from: deployer,
args: args,
log: true,
waitConfirmations: waitBlockConfirmations,
})
if (!developmentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) {
log("Verifying...")
await verify(raffle.address, args)
}
log("------------------------------------------")
}
export default deployRaffle
deployRaffle.tags = ["all", "raffle"]
My Raffle.test.ts
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"
import { assert, expect } from "chai"
import { BigNumber, Contract } from "ethers"
import { deployments, ethers, getNamedAccounts, network } from "hardhat"
import { developmentChains, networkConfig } from "../../helper-hardhat-config"
// This runs only on a local network
!developmentChains.includes(network.name)
? describe.skip
: describe("Raffle", async function () {
let raffle: Contract
let vrfCoordinatorV2Mock: Contract
let entranceFee: BigNumber
let player: SignerWithAddress
let accounts: SignerWithAddress[]
let raffleContract: Contract
let interval: number
const chainId = network.config.chainId
beforeEach(async function () {
accounts = await ethers.getSigners()
player = accounts[1] // can't use accounts[0] because that is a deployer
await deployments.fixture(["all"])
vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
raffleContract = await ethers.getContract("Raffle")
raffle = raffleContract.connect(player)
entranceFee = await raffle.getEntranceFee()
interval = (await raffle.getInterval()).toNumber()
})
describe("constructor", function () {
it("initalizes the raffle correctly", async () => {
console.log(`Network chainId: ${network.config.chainId}`)
const raffleState = (await raffle.getRaffleState()).toString()
assert.equal(raffleState, "0")
assert.equal(interval.toString(), networkConfig[chainId!]["interval"])
})
})
describe("enterRaffle", () => {
it("reverts when you don't pay enough", async () => {
await expect(raffle.enterRaffle()).to.be.revertedWith(
"Raffle__NotEnoughETHEntered"
)
})
it("records player when they enter", async () => {
await raffle.enterRaffle({ value: entranceFee })
const contractPlayer = await raffle.getPlayer(0)
assert.equal(player.address, contractPlayer)
})
it("emits event on enter", async () => {
await expect(raffle.enterRaffle({ value: entranceFee })).to.emit(
raffle,
"RaffleEnter"
)
})
it("doesn't allow entrance when raffle is calculating", async () => {
await raffle.enterRaffle({ value: entranceFee })
// Force some time to pass
await network.provider.send("evm_increaseTime", [interval + 1])
await network.provider.request({ method: "evm_mine", params: [] })
// pretending to be a chainlink keeper and put raffleState in CALCULATING mode
await raffle.performUpkeep([])
await expect(raffle.enterRaffle({ value: entranceFee })).to.be.revertedWith(
"Raffle_NotOpen"
)
})
})
describe("checkUpKeep", () => {
it("returns false if people haven't sent any ETH", async () => {
await network.provider.send("evm_increaseTime", [interval + 1])
await network.provider.request({ method: "evm_mine", params: [] })
// Simulate calling checkUpKeep()
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x")
// upkeepNeeded should be false because we didn't send any ETH
assert(!upkeepNeeded)
})
it("returns false if raffle isn't open", async () => {
await raffle.enterRaffle({ value: entranceFee })
await network.provider.send("evm_increaseTime", [interval + 1])
await network.provider.request({ method: "evm_mine", params: [] })
// Calling this func manke raffleState go to CALCULATING
await raffle.performUpkeep([])
const raffleState = await raffle.getRaffleState()
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x")
assert.equal(raffleState.toString() == "1", upkeepNeeded == false)
})
it("returns false if enough time hasn't passed", async () => {
await raffle.enterRaffle({ value: entranceFee })
// Enough time hasn't passed - this leads to returned false
await network.provider.send("evm_increaseTime", [interval - 1])
await network.provider.request({ method: "evm_mine", params: [] })
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x")
assert(!upkeepNeeded)
})
it("returns true if enough time has passed, has players, eth, and is open", async () => {
await raffle.enterRaffle({ value: entranceFee })
await network.provider.send("evm_increaseTime", [interval + 1])
await network.provider.request({ method: "evm_mine", params: [] })
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x")
assert(upkeepNeeded)
})
})
describe("performUpKeep", () => {
it("can only run if checkupkeep is true", async () => {
await raffle.enterRaffle({ value: entranceFee })
await network.provider.send("evm_increaseTime", [interval + 1])
await network.provider.request({ method: "evm_mine", params: [] })
const tx = await raffle.performUpkeep("0x")
assert(tx)
})
it("reverts when checkupkeep is false", async () => {
await expect(raffle.performUpkeep("0x")).to.be.revertedWith(
"Raffle__UpkeepNotNeeded"
)
})
it("updates the raffle state and emits a requestId", async () => {
await raffle.enterRaffle({ value: entranceFee })
await network.provider.send("evm_increaseTime", [interval + 1])
await network.provider.request({ method: "evm_mine", params: [] })
// Make call to performUpKeep
const txnResponse = await raffle.performUpkeep("0x")
const txnReceipt = await txnResponse.wait(1)
// Get raffle state
const raffleState = await raffle.getRaffleState()
// Get requestId
const requestId = txnReceipt!.events![1].args!.requestId
// Check if reqestIf is emmited
assert(requestId.toNumber() > 0)
// Check if raffe state is updated
assert(raffleState == 1)
})
})
describe("fulfilRandomWords", () => {
beforeEach(async () => {
await raffle.enterRaffle({ value: entranceFee })
await network.provider.send("evm_increaseTime", [interval + 1])
await network.provider.request({ method: "evm_mine", params: [] })
})
it("picks a winner, resets, and sends money", async () => {
const additionalEntrances = 3
const startingIndex = 2
for (let i = startingIndex; i < startingIndex + additionalEntrances; i++) {
raffle = raffleContract.connect(accounts[i])
await raffle.enterRaffle({ value: entranceFee })
}
const startingTimeStamp = await raffle.getLastTimeStamp()
await new Promise<void>(async (resolve, reject) => {
// Subscribe once to event calling listener when the event occurs.
raffle.once("WinnerPicked", async () => {
console.log("WinnerPicked even fired!")
try {
const recentWinner = await raffle.getRecentWinner()
const raffleState = await raffle.getRaffleState()
const winnerBalance = await accounts[2].getBalance()
const endingTimeStamp = await raffle.getLastTimeStamp()
await expect(raffle.getPlayer(0)).to.be.reverted
assert.equal(recentWinner.toString(), accounts[2].address)
assert.equal(raffleState.toString(), "0")
assert(endingTimeStamp > startingTimeStamp)
assert.equal(
winnerBalance.toString(),
startingBalance
.add(entranceFee.mul(additionalEntrances).add(entranceFee))
.toString()
)
resolve()
} catch (e) {
reject(e)
}
})
const tx = await raffle.performUpkeep("0x")
const txReceipt = await tx.wait(1)
const startingBalance = await accounts[2].getBalance()
await vrfCoordinatorV2Mock.fulfillRandomWords(
txReceipt!.events![1].args!.requestId,
raffle.address
)
})
})
})
})
I am following Patrick's solidity+Typescript course on YouTube. So, id this works for you let me know. 😉
Best Answer
In your 00-deploy-mocks.ts you are only deploying Mocks if it is a local network:
which makes sense.
You hardcoded the chainID to be 31337 however, so the 01-deploy-raffle script tries to get the Mock contract. Uncomment the following line:
And that should fix your woes :) Hope that helps!