So i am following this tutorial on youtube and in this tutorial, he uses VRFv1 and that also works fine for me. But as we have VRFv2 now, so i wanted to give that a try.
But it seems that fulfillRandomWords is not getting called thus not making any state changes.
Here is my code;
My contract;
// An NFT contract
// where the tokenURI can be one of the 3 dogs
// Randomly selected
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
import "./VRFConsumerBaseV2.sol";
contract AdvancedCollectable is ERC721URIStorage, VRFConsumerBaseV2 {
uint256 public tokenCounter;
bytes32 public keyhash;
uint256 public fee;
uint64 public s_subscriptionId;
uint32 public callbackGasLimit = 2500000;
uint16 public requestConfirmations = 3;
uint32 public numWords = 2;
VRFCoordinatorV2Interface public COORDINATOR;
LinkTokenInterface public LINKTOKEN;
// testing vars
uint256[] public rnl;
uint256 public testInt;
uint256 public rid;
enum Breed {
PUG,
SHIBA_INU,
ST_BERNARD
}
mapping(uint256 => Breed) public tokenIdToBreed;
mapping(uint256 => address) public requestIdToSender;
event requestedCollectable(uint256 indexed requestId, address requester);
event breedAssigned(uint256 indexed tokenId, Breed breed);
constructor(
address _vrfcoordinator,
address _linktoken,
bytes32 _keyhash,
uint256 _fee
) public VRFConsumerBaseV2(_vrfcoordinator) ERC721("Dogie", "DOG") {
tokenCounter = 0;
keyhash = _keyhash;
fee = _fee;
COORDINATOR = VRFCoordinatorV2Interface(_vrfcoordinator);
LINKTOKEN = LinkTokenInterface(_linktoken);
createNewSubscription();
}
function createCollectable() public returns (uint256) {
uint256 requestId = COORDINATOR.requestRandomWords(
keyhash,
s_subscriptionId,
requestConfirmations,
callbackGasLimit,
numWords
);
rid = requestId;
requestIdToSender[requestId] = msg.sender;
emit requestedCollectable(requestId, msg.sender);
}
function fulfillRandomWords(
uint256 requestId,
uint256[] memory randomNumbers
) internal override {
testInt = 1;
rnl = randomNumbers;
Breed breed = Breed(randomNumbers[0] % 3);
uint256 newTokenId = tokenCounter;
tokenIdToBreed[newTokenId] = breed;
emit breedAssigned(newTokenId, breed);
address owner = requestIdToSender[requestId];
_safeMint(owner, newTokenId);
tokenCounter = tokenCounter + 1;
}
// Create a new subscription when the contract is initially deployed.
function createNewSubscription() private {
s_subscriptionId = COORDINATOR.createSubscription();
// Add this contract as a consumer of its own subscription.
COORDINATOR.addConsumer(s_subscriptionId, address(this));
}
// Assumes this contract owns link.
// 1000000000000000000 = 1 LINK
function topUpSubscription(uint256 amount) external {
LINKTOKEN.transferAndCall(
address(COORDINATOR),
amount,
abi.encode(s_subscriptionId)
);
}
function addConsumer(address consumerAddress) external {
// Add a consumer contract to the subscription.
COORDINATOR.addConsumer(s_subscriptionId, consumerAddress);
}
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
// pug, shiba inu, st bernanrd
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: caller is not owner or approved."
);
_setTokenURI(tokenId, _tokenURI);
}
}
Then i use brownie to deploy this contract and to create some Collectables. Here is the code;
import time
from scripts.helpful_scripts import fund_with_link, get_account
from brownie import AdvancedCollectable, config, network
from web3 import Web3
CONFIG = config["networks"][network.show_active()]
AMOUNT = Web3.toWei(3, "ether")
amt = Web3.toWei(1, 'ether')
def main():
account = get_account()
advanced_collectable = AdvancedCollectable.deploy(
CONFIG["vrf_coordinator"],
CONFIG["link_token"],
CONFIG["keyhash"],
CONFIG["fee"],
{"from": account},
publish_source=True,
)
tx1 = fund_with_link(advanced_collectable.address, account, AMOUNT)
tx1.wait(1)
txn = advanced_collectable.topUpSubscription(amt, {"from": account})
txn.wait(1)
tx = advanced_collectable.createCollectable(
{"from": account},
)
tx.wait(1)
time.sleep(300)
print("New token has been created!")
This doesn't give any error, but if it ran successfully, then the variable tokenCounter in the contract should be incremented, but it shows no change as i am trying to get that in another file which is as;
from brownie import AdvancedCollectable, network
from metadata.sample_metadata import metadata_template
from scripts.helpful_scripts import get_breed
from pathlib import Path
def main():
advanced_collectable = AdvancedCollectable[-1]
print(advanced_collectable)
number_of_advanced_collectables = advanced_collectable.tokenCounter()
print(f"You have created {number_of_advanced_collectables} Collectables")
It gives 0 as result which actually should be 1.
appreciate any help!!!