2

This is my BasicNft contract. I deployed an nft contract. Working great. I am trying to understand storage slots. Normally what I found, The first of state variable gets the first slot. But if we have a constructor it seems to be changing.
This is my minting script:

const { ethers, network } = require("hardhat");
const { moveBlocks } = require("../utils/move-blocks");

async function mint() {
  const basicNft = await ethers.getContract("BasicNft");
  console.log("Minting...");
  const mintTx = await basicNft.mintNft();
  const mintTxReceipt = await mintTx.wait(1);
  const tokenId = mintTxReceipt.events[0].args.tokenId;
  console.log(`Token ID: ${tokenId}`);
  console.log(`NFT Address: ${basicNft.address}`);

  if (network.config.chainId == 31337) {
    await moveBlocks(1, (sleepAmount = 1000));
  }

  let slot = 0;
  for (let i = 0; i < 8; i++) {
    slot = await ethers.provider.getStorageAt(basicNft.address, i);
    console.log(`Slot${i} : ${slot}`);
  }
}

mint()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

It's print slots like this:

Slot0 : 0x446f67696500000000000000000000000000000000000000000000000000000a
Slot1 : 0x444f470000000000000000000000000000000000000000000000000000000006
Slot2 : 0x0000000000000000000000000000000000000000000000000000000000000000
Slot3 : 0x0000000000000000000000000000000000000000000000000000000000000000
Slot4 : 0x0000000000000000000000000000000000000000000000000000000000000000
Slot5 : 0x0000000000000000000000000000000000000000000000000000000000000000
Slot6 : 0x0000000000000000000000000000000000000000000000000000000000000006
Slot7 : 0x0000000000000000000000000000000000000000000000000000000000000000

Slot0 is Dogie slot1 is DOG. So it's name and symbol of nft. We have some 0 slots. But how this works? Why is this like that? Why is not slot0 s_tokenCounter ?

Also I deployed contact on rinkeby: 0x3226ED61DE678f0c09B6A5919C0E5c67D0C09f95 BasicNft contract:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract BasicNft is ERC721 {
    uint256 private s_tokenCounter = 0;

    event DogMinted(uint256 indexed tokenId);

    string public constant TOKEN_URI =
        "ipfs://bafybeig37ioir76s7mg5oobetncojcm3c3hxasyd4rvid4jqhy4gkaheg4/?filename=0-PUG.json";

    constructor() ERC721("Dogie", "DOG") {
        s_tokenCounter = 0;
    }

    function mintNft() public returns (uint256) {
        _safeMint(msg.sender, s_tokenCounter);
        emit DogMinted(s_tokenCounter);
        s_tokenCounter++;
        return s_tokenCounter;
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        return TOKEN_URI;
    }

    function getTokenCounter() public view returns (uint256) {
        return s_tokenCounter;
    }
}

1 Answer 1

1

It's the token name and symbol state variables from the inherited OZ ERC721 contract taking precedence over the state variables in the child contract

i.e. 

// Token name
string private _name;

// Token symbol
string private _symbol;

which you've set in the constructor

5
  • So child contract take first spot? What if I have more than one child contract? Why the slots 2,3,4,5 is 0 ? Sep 1, 2022 at 19:12
  • the parent is the one taking the first two slots. Inheritance goes from right to left. The default value of all slots is 0 as there is no concept of null in Solidity. The only other state variable you have in the contracts is s_tokenCounter, which is slot3 and is set to 0 (the default value)
    – sola24
    Sep 2, 2022 at 7:08
  • But I already mint nfts. So s_tokenCounter already 6. Which is that slot6. You can check on rinkeby contract. I just minted another one slot6 is now 7 Sep 2, 2022 at 13:44
  • On OZ er721 contract we have 4 mappings under the name and symbol. How mappings take space on storage? Sep 2, 2022 at 13:53
  • yep. mappings are a special case I guess you could say. I had thought you'd ask about the declared constant next 🙂.I suggest this video to explain better than I can. m.youtube.com./watch?v=Gg6nt3YW74o
    – sola24
    Sep 2, 2022 at 17:05

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.