While testing the Raffle contract, I am getting error in the line written
"await network.provider.send("evm_increaseTime", [Number(interval) + 1]);
await network.provider.send("evm_mine", []);"
Here is Raffle.sol contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol";
error Raffle__EntranceFeeNotEnough();
error Raffle__TransferFailed();
error Raffle__NotOpen();
error Raffle_UpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 raffleState);
/**
* @title A sample Raffle Contract
* @author nik_arjun
* @notice This contract is for creating untamperable decentralized smart contract
* @dev This implements Chainlink VRF v2 and Chainlink Keepers
*/
contract Raffle is VRFConsumerBaseV2, AutomationCompatibleInterface {
/* Type Declaration */
enum RaffleState {
OPEN,
CALCULATING
} // Equivalent to uint256 = 0: OPEN, 1:CALCULATING
/* State Variable */
uint256 private i_entranceFee;
address payable[] private s_players;
VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
bytes32 private immutable i_gasLane;
uint64 private immutable i_subscriptionId;
uint32 private immutable i_callbackGasLimit;
uint16 private constant REQUEST_CONFIRMATIONS = 3;
uint32 private constant NUM_WORDS = 1;
/* Lottery Variables */
address private s_recentWinner;
RaffleState private s_raffleState;
uint256 private s_lastTimeStamp;
uint256 private immutable i_interval;
/* Events */
event RaffleEnter(address indexed player);
event RequestedRaffleWinner(uint256 indexed requestId);
event WinnerPicked(address indexed winner);
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; // or RaffleState(0)
s_lastTimeStamp = block.timestamp;
i_interval = interval;
}
function enterRaffle() public payable {
if (msg.value < i_entranceFee) {
revert Raffle__EntranceFeeNotEnough();
}
if (s_raffleState != RaffleState.OPEN) {
revert Raffle__NotOpen();
}
s_players.push(payable(msg.sender));
// Emit a event when we update the dynamic array or mapping
// Named event with function name reversed
emit RaffleEnter(msg.sender);
}
/**
* @dev This is the function that the Chainlink Keeper nodes call
* they look for `upkeepNeeded` to return True.
* the following should be true for this to return true:
* 1. The time interval has passed between raffle runs.
* 2. The lottery is open.
* 3. The contract has atleast 1 player and some ETH.
* 4. Implicity, your subscription is funded with LINK.
*/
function checkUpkeep(
bytes memory /* performData */
) public override returns (bool upkeepNeeded, bytes memory /* performData */) {
bool isOpen = (s_raffleState == RaffleState.OPEN);
bool timePassed = ((block.timestamp - s_lastTimeStamp) > i_interval);
bool hasPlayers = (s_players.length > 0);
bool hasBalance = (address(this).balance > 0);
upkeepNeeded = (isOpen && timePassed && hasPlayers && hasBalance);
}
function performUpkeep(bytes calldata /* performData */) external override {
// Request Random Number
// Once we get it, we will do something
// 2 transaction process
(bool upkeepNeeded, ) = checkUpkeep("");
if (!upkeepNeeded) {
revert Raffle_UpkeepNotNeeded(
address(this).balance,
s_players.length,
uint256(s_raffleState)
);
}
s_raffleState = RaffleState.CALCULATING;
uint256 requestId = i_vrfCoordinator.requestRandomWords(
i_gasLane, // gasLane
i_subscriptionId,
REQUEST_CONFIRMATIONS,
i_callbackGasLimit,
NUM_WORDS
);
emit RequestedRaffleWinner(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;
s_lastTimeStamp = block.timestamp;
s_raffleState = RaffleState.OPEN;
s_players = new address payable[](0);
(bool success, ) = recentWinner.call{value: address(this).balance}("");
if (!success) {
revert Raffle__TransferFailed();
}
emit WinnerPicked(recentWinner);
}
/* 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 getNumberOfPlayers() public view returns (uint256) {
return s_players.length;
}
function getTimeStamp() public view returns (uint256) {
return s_lastTimeStamp;
}
function getInterval() public view returns (uint256) {
return i_interval;
}
function getRequestConfirmations() public pure returns (uint16) {
return REQUEST_CONFIRMATIONS;
}
}
Here is Raffle.test.js
const { network, deployments, ethers, getNamedAccounts, getChainId } = require("hardhat");
const { developementChains, networkConfig } = require("../../helper-hardhat-config");
const { assert, expect } = require("chai");
!developementChains.includes(network.name)
? describe.skip
: describe("Raffle Unit Test", async function () {
let raffle, VRFCoordinatorV2Mock, raffleEntranceFee, deployer, interval;
beforeEach(async function () {
deployer = (await getNamedAccounts()).deployer;
await deployments.fixture(["all"]);
const raffleAddress = (await deployments.get("Raffle")).address;
const vrfCoordinatorV2Address = (await deployments.get("VRFCoordinatorV2Mock")).address;
raffle = await ethers.getContract("Raffle", deployer);
VRFCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock", deployer);
raffleEntranceFee = await networkConfig[await getChainId()]["entranceFee"];
interval = await raffle.getInterval();
});
describe("constructor", function () {
it("Initializes Raffle Correctly", async function () {
const raffleState = await raffle.getRaffleState();
assert.equal(raffleState.toString(), "0");
assert.equal(interval.toString(), networkConfig[await getChainId()]["interval"]);
});
});
describe("Enter Raffle", function () {
it("Reverts if you don't have enough ETH", async function () {
await expect(raffle.enterRaffle()).to.be.revertedWithCustomError(
raffle,
"Raffle__EntranceFeeNotEnough()"
);
});
it("Records player when it enters the Raffle", async function () {
await raffle.enterRaffle({ value: raffleEntranceFee });
const player_zero = await raffle.getPlayer(0);
assert.equal(player_zero, deployer);
});
it("Doesn't allow entrance if Raffle State is close", async function () {
await raffle.enterRaffle({ value: raffleEntranceFee });
await network.provider.send("evm_increaseTime", [Number(interval) + 1]);
await network.provider.send("evm_mine", []);
// Perform upkeep by pretending as a Chainlink keeper
await raffle.performUpkeep([]);
await expect(
raffle.enterRaffle({ value: raffleEntranceFee })
).to.be.revertedWithCustomError(raffle, Raffle__NotOpen);
});
it("Emits an event on entering the raffle", async function () {
await expect(await raffle.enterRaffle({ value: raffleEntranceFee })).to.emit(
raffle,
"RaffleEnter"
);
});
});
});
And this is the error I am getting while running it :
TypeError: invalid BytesLike value (argument="value", value=[ ], code=INVALID_ARGUMENT, version=6.10.0)
at makeError (node_modules/ethers/src.ts/utils/errors.ts:687:21)
at assert (node_modules/ethers/src.ts/utils/errors.ts:715:25)
at assertArgument (node_modules/ethers/src.ts/utils/errors.ts:727:5)
at _getBytes (node_modules/ethers/src.ts/utils/data.ts:44:19)
at getBytesCopy (node_modules/ethers/src.ts/utils/data.ts:66:12)
at BytesCoder.encode (node_modules/ethers/src.ts/abi/coders/bytes.ts:21:29)
at /home/nraj07054/hardhat-fcc/hardhat-smartcontract-lottery-fcc/node_modules/ethers/src.ts/abi/coders/array.ts:55:19
at Array.forEach (<anonymous>)
at pack (node_modules/ethers/src.ts/abi/coders/array.ts:47:12)
at TupleCoder.encode (node_modules/ethers/src.ts/abi/coders/tuple.ts:62:20)
Best Answer
The empty array you're passing "" is not a valid BytesLike value. You need to pass a valid hexadecimal string or an array of bytes.
Try this: