Lesson 14: "NftMinted" event not thrown in the unit tests. #1211
-
I was running the unit test for RandomIpfsNft.sol, and found out that my NftMinted event is never thrown. Here are my files, RandomIpfsNft.sol function requestNft() public payable returns (uint256 requestId) {
if (msg.value < i_mintFee) {
revert RandomIpfsNft__NeedMoreEthSent();
}
requestId = i_vrfCoordinator.requestRandomWords(
i_gasLane,
i_subscriptionId,
REQUEST_CONFIRMATIONS,
i_callbackGasLimit,
NUM_WORDS
);
s_requestIdToSender[requestId] = msg.sender;
emit NftRequested(requestId, msg.sender);
}
// this function is called by chainlink nodes to use the random words for generating results
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords)
internal
override
{
// now if we do the same _mint(msg.sender, token) : this will assign the nft to the chainlink node
// but we want our request function caller to be the owner
address dogOwner = s_requestIdToSender[requestId]; // here we explicitly specifies that the dog owner is req initiator
uint256 newTokenId = s_tokenCounter;
// what does this token look like?
uint256 moddedRng = randomWords[0] % MAX_CHANCE_VALUE; // it will generate 0-99 and depending on the range values get assigned
Breed dogBreed = getBreedFromModdedRng(moddedRng);
s_tokenCounter = s_tokenCounter + 1;
_safeMint(dogOwner, newTokenId);
_setTokenURI(newTokenId, s_dogTokenUris[uint256(dogBreed)]);
emit NftMinted(dogBreed, dogOwner);
} Test.js file describe("fulfillRandomWords", () => {
it("mints NFT after random number is returned", async function () {
await new Promise(async (resolve, reject) => {
// setTimeout(resolve, 60000);
randomIpfsNft.once("NftMinted", async () => {
try {
console.log("yeah we got it---------------------");
const tokenUri = await randomIpfsNft.tokenURI("0");
const tokenCounter = await randomIpfsNft.getTokenCounter();
assert.equal(tokenUri.toString().includes("ipfs://"), true);
assert.equal(tokenCounter.toString(), "1");
resolve();
} catch (e) {
console.log(e);
reject(e);
}
});
try {
const fee = await randomIpfsNft.getMintFee();
console.log(fee.toString());
const requestNftResponse = await randomIpfsNft.requestNft({
value: fee.toString(),
});
const requestNftReceipt = await requestNftResponse.wait(1);
console.log(requestNftReceipt.events[1].args.requestId.toString());
console.log(randomIpfsNft.address);
await vrfCoordinatorV2Mock.fulfillRandomWords(
requestNftReceipt.events[1].args.requestId.toString(),
randomIpfsNft.address
);
} catch (e) {
console.log(e);
reject(e);
}
});
});
}); I tried debugging by using console.log and came to a conclusion that when we enter I don't understand what is wrong here. Can someone help? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 10 replies
-
Can you share your contract file or upload the whole repo to Github and make it public? |
Beta Was this translation helpful? Give feedback.
-
Copy my code and refactor variables as per your choice, and let me know if it works. // SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "hardhat/console.sol";
error AlreadyInitialized();
error NeedMoreETHSent();
error RangeOutOfBounds();
contract RandomIpfsNft is ERC721URIStorage, VRFConsumerBaseV2, Ownable {
// Types
enum Breed {
PUG,
SHIBA_INU,
ST_BERNARD
}
// Chainlink VRF Variables
VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
uint64 private immutable i_subscriptionId;
bytes32 private immutable i_gasLane;
uint32 private immutable i_callbackGasLimit;
uint16 private constant REQUEST_CONFIRMATIONS = 3;
uint32 private constant NUM_WORDS = 1;
// NFT Variables
uint256 private i_mintFee;
uint256 public s_tokenCounter;
mapping(uint256 => Breed) private s_tokenIdToBreed;
uint256 internal constant MAX_CHANCE_VALUE = 100;
string[] internal s_dogTokenUris;
bool private s_initialized;
// VRF Helpers
mapping(uint256 => address) public s_requestIdToSender;
// Events
event NftRequested(uint256 indexed requestId, address requester);
event NftMinted(Breed breed, address minter);
constructor(
address vrfCoordinatorV2,
uint64 subscriptionId,
bytes32 gasLane, // keyHash
uint256 mintFee,
uint32 callbackGasLimit,
string[3] memory dogTokenUris
) VRFConsumerBaseV2(vrfCoordinatorV2) ERC721("Random IPFS NFT", "RIN") {
i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
i_gasLane = gasLane;
i_subscriptionId = subscriptionId;
i_mintFee = mintFee;
i_callbackGasLimit = callbackGasLimit;
_initializeContract(dogTokenUris);
}
function requestNft() public payable returns (uint256 requestId) {
if (msg.value < i_mintFee) {
revert NeedMoreETHSent();
}
requestId = i_vrfCoordinator.requestRandomWords(
i_gasLane,
i_subscriptionId,
REQUEST_CONFIRMATIONS,
i_callbackGasLimit,
NUM_WORDS
);
s_requestIdToSender[requestId] = msg.sender;
emit NftRequested(requestId, msg.sender);
}
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
address dogOwner = s_requestIdToSender[requestId];
uint256 newItemId = s_tokenCounter;
s_tokenCounter = s_tokenCounter + 1;
uint256 moddedRng = randomWords[0] % MAX_CHANCE_VALUE;
Breed dogBreed = getBreedFromModdedRng(moddedRng);
_safeMint(dogOwner, newItemId);
_setTokenURI(newItemId, s_dogTokenUris[uint256(dogBreed)]);
emit NftMinted(dogBreed, dogOwner);
}
function getChanceArray() public pure returns (uint256[3] memory) {
return [10, 30, MAX_CHANCE_VALUE];
}
function _initializeContract(string[3] memory dogTokenUris) private {
if (s_initialized) {
revert AlreadyInitialized();
}
s_dogTokenUris = dogTokenUris;
s_initialized = true;
}
function getBreedFromModdedRng(uint256 moddedRng) public pure returns (Breed) {
uint256 cumulativeSum = 0;
uint256[3] memory chanceArray = getChanceArray();
for (uint256 i = 0; i < chanceArray.length; i++) {
// if (moddedRng >= cumulativeSum && moddedRng < cumulativeSum + chanceArray[i]) {
if (moddedRng >= cumulativeSum && moddedRng < chanceArray[i]) {
return Breed(i);
}
// cumulativeSum = cumulativeSum + chanceArray[i];
cumulativeSum = chanceArray[i];
}
revert RangeOutOfBounds();
}
function withdraw() public onlyOwner {
uint256 amount = address(this).balance;
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success, "Transfer failed");
}
function getMintFee() public view returns (uint256) {
return i_mintFee;
}
function getDogTokenUris(uint256 index) public view returns (string memory) {
return s_dogTokenUris[index];
}
function getInitialized() public view returns (bool) {
return s_initialized;
}
function getTokenCounter() public view returns (uint256) {
return s_tokenCounter;
}
} |
Beta Was this translation helpful? Give feedback.
-
Not sure if it will work but try requesting for the nft first. Just before |
Beta Was this translation helpful? Give feedback.
-
@Rishi860 : Kindly close this discussion as answered, as it is been resolved! ThankYou |
Beta Was this translation helpful? Give feedback.
@Rishi860 : Kindly close this discussion as a…