DeclarationError: Undeclared identifier error when using _setBaseURI

Hi, I am trying to implement this for my own project but I am unable to compile my contracts.

Here is my contract:

// SPDX-License-Identifier: MIT

 pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";

/**
 * @dev {ERC721} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *  - token ID and URI autogeneration
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to other accounts.
 */
contract MyNFT is Context, AccessControl, ERC721Burnable {
    using Counters for Counters.Counter;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    Counters.Counter private _tokenIdTracker;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * Token URIs will be autogenerated based on `baseURI` and their token IDs.
     * See {ERC721-tokenURI}.
     */
    constructor(string memory name, string memory symbol, string memory baseURI) public ERC721(name, symbol) {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
 
        _setBaseURI(baseURI);
    }

    /**
     * @dev Creates a new token for `to`. Its token ID will be automatically
     * assigned (and available on the emitted {IERC721-Transfer} event), and the token
     * URI autogenerated based on the base URI passed at construction.
     *
     * See {ERC721-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), "MyNFT: must have minter role to mint");

        // We cannot just use balanceOf to create the new tokenId because tokens
        // can be burned (destroyed), so we need a separate counter.
        _mint(to, _tokenIdTracker.current());
        _tokenIdTracker.increment();
    }
}

And here is my stack trace:

DeclarationError: Undeclared identifier.
  --> /Users/mlunghi/Desktop/protem-v1/contracts/mynft.sol:45:9:
   |
45 |         _setBaseURI(baseURI);
   |         ^^^^^^^^^^^

Thanks!

Hello Matteo, welcome to the forum! What version of Contracts are you using?

ERC721 comes with _setTokenUri now. Check this previous discussion:

1 Like

@Matteo_Lunghi _setBaseURI has been removed from OpenZeppelin Contracts 4.0. Sorry about the current lack of documentation around this. You can read about the reasoning behind this in the announcement for 4.0 in the section about ERC721.

The current way to customize the base URI is to override the function _baseURI() returns (string memory) in your contract. Our recommendation is to return a constant string or an immutable string variable that you set in the constructor. You can take a look at the Contracts Wizard and see the code that gets added when you customize the Base URI field.

1 Like

Thanks guys. On an unrelated note, I am currently passing all my tests except 1 and I don’t understand why. This is the error I get:

Error: Returned error: VM Exception while processing transaction: revert ERC721: token already minted – Reason given: ERC721: token already minted.

What does this mean?

You’re reusing a tokenId that has already been minted:

I see that tokenSupply() is gone from new contracts. I am following this repository: https://github.com/chentschel/nft-marketplace/tree/master/contracts

But I receive the above error. Any ideas? Thanks so much for your help!

If you need totalSuply() you have to inherit ERC721Enumerable. See the section about " ERC721 Enumerability" in OpenZeppelin Contracts 4.0.

1 Like

Was this part of ERC721 previously?

Yes it used to be built in. It’s explained in the announcement I linked above.

I'm importing 721URIStorage, which eliminated my "setTokenURI" error but I am still getting the "undeclared Identifier" error for _setBaseURI, which worked before I started converting the contract to pragma8.

Help please.

Hi @metaverde,

_setBaseURI is no longer available. You can add it back by overriding the _baseURI function like so:

string internal baseURI;

function _baseURI() internal view override returns (string memory) {
    return baseURI;
}

Instead of _setBaseURI you can assign to the variable baseURI.

1 Like

Thank you for your prompt response!

I got that contract to deploy, then noticed that Austin Griffith's Speedrun challenge-0 has been updated to pragma 8, so I cribbed from it to update the Scaf-Eth nft-store-bonding-curve branch and submitted a pr.
:crossed_fingers:t3:Here's hoping I did it correctly.

:honey_pot:
:honeybee::honeybee::honeybee: