Recently, I was studying the ERC721 smart contract and came across something which I coult not understand.

Look at the following code -

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";

It depicts the tokenURI() method implementation in the ERC721 token.

Also, look at the _baseURI implementation written inside ERC721-

    function _baseURI() internal view virtual returns (string memory) {
        return "";

Now, in the tokenURI() method, the _baseURI() returns "" and hence setting the variable baseURI to "".
If we do bytes(baseURI).length for baseURI="", we get 0 and hence the condition bytes(baseURI).length > 0 always evaluates to false and in turn tokenURI(tokenId) for any tokenId always returns ""

Also, check out this - trial

Now my doubt is how the tokenURI which is the concatenation of baseURI and tokenId is set and returned.

Please let me where am I understanding it wrong. Thanks in advance!

1 Answer 1


That's because the _baseURI() function is virtual and is supposed to be overridden from a derived contract and actually return a string value that the developer that overrides it considers.

For example:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";

contract MyERC721 is ERC721("Abc", "ABC") {

    function doSomething(uint256 tokenId) public view returns(string memory) {
        return tokenURI(tokenId);

    function _baseURI() internal view override returns (string memory) {
        return "myBaseUrl";

    // more logic


Notice how I inherited from ERC721 contract.

I overrode the _baseURI() function. Then, on the doSomething function I call tokenURI, which in turn will call _baseURI(), but not the _baseURI() with the empty string in it, but the _baseURI() function that I overrode with the "myBaseUrl" string.

So, the ERC721 is providing you with a base functionality so you override any virtual function that you need to add your desired logic/data.

  • 1
    Thanks for the answer! Understood it well! Sep 21, 2022 at 6:04

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.