Create Your ERC721 Contract

Install Dependencies

We will build your ERC721 contract based on the Openzeppelin contracts. Let's install Openzeppelin contracts for our foundry project:

forge install openzeppelin/openzeppelin-contracts 

Foundry installs all dependencies as git submodules under the directory of "lib". And to make it easier to import the dependencies, let's create a remappings.txt file with the following contents:


The remapping.txt file should be put in the project root directory (i.e., the directory that contains thefoundry.toml file. )

With the remappings.txt file above, we can import the ERC721 contract from Openzeppelin by the following import statement :

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

The ERC721 Contract

Create a new file named "MyNFT.sol" under the directory of "src". The content in the file is as follows:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
import "openzeppelin-contracts/contracts/access/Ownable.sol";

contract MyNFT is ERC721, Ownable{

    string private _URIBase;

    constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {

    function mint(address to, uint256 tokenId) public onlyOwner {
        _safeMint(to, tokenId);

    function setBaseURI(string memory baseURI_) public onlyOwner {
        _URIBase = baseURI_;

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

In this toy ERC721 contract, we have added some customized logics:

  • The deployer of the contract will be the owner of the contract.

  • Only the owner can mint a new NFT token. However, he can mint the token to another address.

  • Only the owner can change the base URI of the Token URI.

Deploy Your ERC721 Contract

FOUNDRY_PROFILE=kcc_testnet \
    forge create \
    --constructor-args "my-nft" "M" 
    --private-key=XXXXXXXXXXXXXXXXX  \
    --legacy  src/MyNFT.sol:MyNFT

We use --constructor-args to specify the arguments for our constructor.

If everything goes well, forge will print out the address of the deployed contract and the transaction hash for the deployment.

Mint An NFT

We can use cast from foundry to interact with our ERC721 contract. Let's mint an NFT with cast:

FOUNDRY_PROFILE=kcc_testnet cast send  \
    --private-key=XXXXXXXXXXXX  --legacy \
    0xd382De234f8d3f1DB54C856498a9DbC84c \
    'mint(address,uint256)'  \
    0x6Dfc34a4a2FC03Ba5d5ff95566781bD2b39702fc 1337

  • You should replace 0xd382De234f8d3f1DB54C856498a9DbC84c with the address of your ERC721 contract.

  • And 0x6Dfc34a4a2FC03Ba5d5ff95566781bD2b39702fc is the address that receives the newly minted NFT.

  • Finally, 1337 is the id of the newly minted NFT.

We can also verify the owner of this newly minted NFT by using cast again:

FOUNDRY_PROFILE=kcc_testnet \
        cast call  0xd382De234f8d3f1DB54C856498a9DbC84c \
        'ownerOf(uint256)(address)' 1337

Last updated