2

I'm working on an app that allows the user to create NFTs and list them on a market place. When I try to create the token on the UI using metamask, a createToken function is being called. The resolved promise of createToken is an object for which I expect an events key with 2 events (I'm able to confirm this by running npx hardhat test. However I don't actually see these events emitted to the UI... I need these events to get the tokenId. If someone knows an alternative way to get the tokenId I'm open to that as well.

createToken:

contract NFT is ERC721URIStorage {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;
    address contractAddress;

    constructor(address marketplaceAddress) ERC721("Metaverse", "METT") {
        contractAddress = marketplaceAddress;
    }

    function createToken(string memory tokenURI) public returns (uint256) {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();

        _mint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);
        // Not emitting this event to the UI but it works in the test
        setApprovalForAll(contractAddress, true);
        return newItemId;
    }
}

The function on the UI looks like below where createSale creates a listing on the marketplace:

  async function createSale(url) {
    const web3Modal = new Web3Modal();
    const connection = await web3Modal.connect();
    const provider = new ethers.providers.Web3Provider(connection);
    const signer = provider.getSigner();

    /* next, create the item */
    let contract = new ethers.Contract(nftAddress, NFT.abi, signer);
    let transaction = await contract.createToken(url);
    let tx = await transaction.wait();

    // Seeing a successful transaction
    console.log("tx ==> ", tx);
    let event = tx.events[0];
    // Breaks here sine event[0] is `undefined`
    let value = event.args[2];
    let tokenId = value.toNumber();

    const price = ethers.utils.parseUnits(formInput.price, "ether");

    /* then list the item for sale on the marketplace */
    contract = new ethers.Contract(nftMarketAddress, Market.abi, signer);
    let listingPrice = await contract.getListingPrice();
    listingPrice = listingPrice.toString();

    transaction = await contract.createMarketItem(nftAddress, tokenId, price, {
      value: listingPrice,
    });
    await transaction.wait();
    router.push("/");
  }

Below is a screenshot of the resolved promise with the empty events array: enter image description here

insivika
  • 576
  • 2
  • 10
  • 21

2 Answers2

1

The nftAddress is empty - it doesn't hold the NFT contract.

The blockNumber property has value 1, which means this transaction was mined in the first block. Hardhat network automines by default - creates a new block for each transaction. Which makes the attached transaction the first one on this network instance, and rules out any possible previous transactions deploying the contract (to this network instance).

When you send a valid transaction to an empty address, it passes through as there's no contract to revert it - but also there's no contract to emit event logs. So it results in an empty events array - just like on the attached screenshot.


I expect an events key with 2 events (I'm able to confirm this by running npx hardhat test

When you run a hardhat test, it creates a network instance, deploys the contracts, runs the test scripts, and then destroys this network instance.

Same goes for when you run npx hardhat node - it creates a new network instance, and when you stop running the node, it destroys its data (along with deployed contracts).

Hardhat network doesn't seem to have a way to save its state and load it later. (Anyone please correct me if I'm mistaken - I just couldn't find anything related in the docs). So you'll might have to redeploy the contract each time you run npx hardhat node. Or to use a different network that supports this feature (e.g. Ganache and its Workspaces) - you'll still be able to use the Hardhat library for the tests, it will just connect to this other network instead of the default Hardhat network.

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
0

I had this exact same issue. I solved mine by using the ropsten test network instead.