I'm completing the freecodecamp solidity tutorial for the advanced NFT and when deploying to a rinkeby testnet it returns:
ValueError: Gas estimation failed: 'execution reverted'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually.
When I use the fund_with_link token my contract is funded yet I'm unable to call the create_collectible function without being returned an error message. I do have enough link in my metamask account.
Here is the contract code:
pragma solidity ^0.7.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@chainlink/contracts/src/v0.7/VRFConsumerbase.sol";
contract AdvancedCollectible is ERC721, VRFConsumerBase {
uint256 public tokenCounter;
bytes32 public keyhash;
uint256 public fee;
enum Breed {
PUG,
SHIBA_INU,
ST_BERNARD
}
mapping(uint256 => Breed) public tokenIdToBreed;
mapping(bytes32 => address) requestIdToSender;
event requestedCollectible(bytes32 indexed requestId, address requester);
event breedAssigned(uint256 indexed tokenId, Breed breed);
constructor(
address _vrfCoordinator,
address _linkToken,
bytes32 _keyhash,
uint256 _fee
)
public
VRFConsumerBase(_vrfCoordinator, _linkToken)
ERC721("Dogie", "DOG")
{
tokenCounter = 0;
keyhash = _keyhash;
fee = _fee;
}
function createCollectible(string memory tokenURI)
public
returns (bytes32)
{
bytes32 requestId = requestRandomness(keyhash, fee);
requestIdToSender[requestId] = msg.sender;
emit requestedCollectible(requestId, msg.sender);
}
function fulfillRandomness(bytes32 requestId, uint256 randomNumber)
internal
override
{
Breed breed = Breed(randomNumber % 3);
uint256 newTokenId = tokenCounter;
tokenIdToBreed[newTokenId] = breed;
emit breedAssigned(newTokenId, breed);
address owner = requestIdToSender[requestId];
_safeMint(owner, newTokenId);
tokenCounter = tokenCounter + 1;
}
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
//need tokenId for pug, shiba-inu and st-bernard
//making sure that only the owner of the tokenId can update the tokenURI
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: is not owner, not approved"
);
}
}
Here is the deploy script:
from scripts.helpful_scripts import (
get_account,
OPENSEA_URL,
get_contract,
fund_with_link,
)
from brownie import AdvancedCollectible, config, network
from web3 import Web3
from time import sleep
sample_token_uri = "https://ipfs.io/ipfs/Qmd9MCGtdVz2miNumBHDbvj8bigSgTwnr4SbyH6DNnpWdt?filename=0-PUG.json"
def deploy_and_create():
account = get_account()
advanced_collectible = AdvancedCollectible.deploy(
get_contract("vrf_coordinator"),
get_contract("link_token"),
config["networks"][network.show_active()]["keyhash"],
config["networks"][network.show_active()]["fee"],
{"from": account},
)
fund_with_link(advanced_collectible.address)
create_collectible = advanced_collectible.createCollectible(
sample_token_uri, {"from": account}
)
def main():
deploy_and_create()
Here is the helpful scripts:
from brownie import network, config, accounts, LinkToken, VRFCoordinatorMock, Contract
import dotenv
from web3 import Web3
OPENSEA_URL = "https://testnets.opensea.io/assets/{}/{}"
LOCAL_BLOCKCHAIN_ENVIRONMENTS = ["hardhat", "development", "ganache", "mainnet-fork"]
def get_account(index=None, id=None):
if index:
return accounts[index]
if network.show_active() in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
return accounts[0]
if id:
return accounts.load(id)
return accounts.add(config["wallets"]["from_key"])
contract_to_mock = {"link_token": LinkToken, "vrf_coordinator": VRFCoordinatorMock}
def get_contract(contract_name):
"""
This function will either:
- Get an address from the config
- Or deploy a Mock to use for a network that doesn't have the contract
Args:
contract_name (string): This is the name of the contract that we will get
from the config or deploy
Returns:
brownie.network.contract.ProjectContract: This is the most recently deployed
Contract of the type specified by a dictionary. This could either be a mock
or a 'real' contract on a live network.
"""
# link_token
# LinkToken
contract_type = contract_to_mock[contract_name]
if network.show_active() in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
if len(contract_type) <= 0:
deploy_mocks()
contract = contract_type[-1]
else:
contract_address = config["networks"][network.show_active()][contract_name]
contract = Contract.from_abi(
contract_type._name, contract_address, contract_type.abi
)
return contract
def deploy_mocks():
"""
Use this script if you want to deploy mocks to a testnet
"""
print(f"The active network is {network.show_active()}")
print("Deploying mocks...")
account = get_account()
print("Deploying Mock LinkToken...")
link_token = LinkToken.deploy({"from": account})
print(f"Link Token deployed to {link_token.address}")
print("Deploying Mock VRF Coordinator...")
vrf_coordinator = VRFCoordinatorMock.deploy(link_token.address, {"from": account})
print(f"VRFCoordinator deployed to {vrf_coordinator.address}")
print("All done!")
def fund_with_link(
contract_address, account=None, link_token=None, amount=Web3.toWei(2, "ether")
):
account = account if account else get_account()
link_token = link_token if link_token else get_contract("link_token")
funding_tx = link_token.transfer(contract_address, amount, {"from": account})
funding_tx.wait(1)
print(f"Funded {contract_address}")
return funding_tx
Here is the brownie-config.yaml:
dotenv: .env
dependencies:
- OpenZeppelin/[email protected]
- smartcontractkit/[email protected]
compiler:
solc:
remappings:
- '@openzeppelin=OpenZeppelin/[email protected]'
- '@chainlink=smartcontractkit/[email protected]'
wallets:
from_key: ${PRIVATE_KEY}
networks:
development:
keyhash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc"
fee: 100000000000000000
rinkeby:
vrf_coordinator: "0x6168499c0cFfCaCD319c818142124B7A15E857ab"
link_token: "0x01BE23585060835E02B77ef475b0Cc51aA1e0709"
keyhash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc"
fee: 10000000000000000
Any help would be appreciated 🙂
Best Answer
For rinkeby network these are the address for the following parameters. vrf_coordinator: "0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B"
link_token: "0x01BE23585060835E02B77ef475b0Cc51aA1e0709"
keyhash: "0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311"
fee: 100000000000000000