1

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 :)

1
  • Hey, I found a solution and it was just me being stupid - not surprising. I just wrote the wrong amount of zeros for the fee in the brownie-config.yaml file. Mar 3, 2022 at 19:15

3 Answers 3

1

For rinkeby network these are the address for the following parameters. vrf_coordinator: "0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B"

link_token: "0x01BE23585060835E02B77ef475b0Cc51aA1e0709"

keyhash: "0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311"

fee: 100000000000000000

0

I found a solution and it was just me being stupid - not surprising. I just wrote the wrong amount of zeros for the fee in the brownie-config.yaml file. Also I had the wrong eth address for the keyhash.

1
  • Hi Daniel, Seems like I have run into the same issue. Could you post the coorect keyHash so I can verify mine?
    – Ayush
    Mar 24, 2022 at 1:42
0

You need to use the addresses from Chainlink VRF v1 NOT v2 in your .yaml, remember to re-deploy your contract with these newly updated addresses. Please see the link below for the addresses:

https://docs.chain.link/docs/vrf/v1/supported-networks/

https://stackoverflow.com/questions/71194882/execution-reverted-during-call-this-transaction-will-likely-revert-if-you-wish

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.