# Basic ERC721 Contract

Below is the code for a very simple ERC721 contract that is compatible with Campfire.&#x20;

{% hint style="info" %}
**Heads up!**

This contract does not include any kind of on-chain randomization or psuedo-randomization.&#x20;

That means that you need to make sure that your metadata is not visible pre-mint by using a centralized gateway.

In other words, if you just post your metadata directly on IPFS, **it will be publicly discoverable with this contract.**
{% endhint %}

```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyNFT is ERC721URIStorage, Ownable {
  using Counters for Counters.Counter;
  Counters.Counter private _tokenIds;

  uint256 private _price;
  uint256 private _maxMintable;
  string private _customBaseURI;
  uint256 private _royaltyAmount;
  uint256 private _maxMintPerTx;

  bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;

  bool private _mintActive;

  constructor() ERC721("My NFT Collection", "MYNFT") {
    _customBaseURI = 'https://my-nft-api.com/nfts/';
    _price = 1 ether; // 1 AVAX mint price 
    _maxMintable = 10000; // 10k max supply
    _royaltyAmount = 700; // 7% royalties
    _mintActive = false; // start paused
  }

  function setBaseURI(string memory customBaseURI_) public onlyOwner {
    _customBaseURI = customBaseURI_;
  }

  function setMintActive(bool status) public onlyOwner {
    _mintActive = status;
  }

  function mint(uint256 quantity) public payable {
    require(_mintActive, "Minting is not active.");
    require(quantity <= _maxMintPerTx, "Cannot mint that many at once.");
    require(msg.value >= (_price * quantity), "Not enough AVAX sent.");

    payable(owner()).transfer(msg.value);

    for(uint i = 0; i < quantity; i++) {
      _privateMint(msg.sender);
    }
  }

  function totalSupply() public view returns (uint256) {
    return _tokenIds.current();
  }

  function _privateMint(address recipient) private {
    _tokenIds.increment();
    require(_tokenIds.current() <= _maxMintable, "Project is finished minting.");

    uint256 newItemId = _tokenIds.current();
    _mint(recipient, newItemId);
  }

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

  function royaltyInfo(
    uint256 _tokenId, 
    uint256 _salePrice
  ) external view returns (address receiver, uint256 royaltyAmount) {
    return (owner(), ((_salePrice * _royaltyAmount) / 10000));
  }

  function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) {
    if (interfaceId == _INTERFACE_ID_ERC2981) {
      return true;
    }
    return super.supportsInterface(interfaceId);
  } 

}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.campfire.exchange/use-cases/minting-contracts/basic-erc721-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
