> For the complete documentation index, see [llms.txt](https://docs.kcc.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kcc.io/developers/deploy-nfts/create-your-erc721-contract.md).

# Create Your ERC721 Contract

<figure><img src="/files/F1Z4rGNP2vjEp2XmWJIu" alt=""><figcaption></figcaption></figure>

### Install Dependencies&#x20;

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

```bash
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:&#x20;

```
openzeppelin-contracts=lib/openzeppelin-contracts
```

{% hint style="info" %}
The `remapping.txt` file should be put in the project root directory (i.e., the directory that contains the`foundry.toml` file. )
{% endhint %}

With the `remappings.txt` file above, we can import the ERC721 contract from Openzeppelin by the following `import statement` :&#x20;

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

### The ERC721 Contract&#x20;

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

```solidity
// 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_) {
        _transferOwnership(msg.sender);
    }

    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;
    }
}
```

{% hint style="info" %}
In this toy ERC721 contract, we have added some customized logics:

* The deployer of the contract will be the owner of the contract.&#x20;
* Only the owner can mint a new NFT token. However, he can mint the token to another address.&#x20;
* Only the owner can change the base URI of the Token URI.&#x20;
  {% endhint %}

### Deploy Your ERC721 Contract&#x20;

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

{% hint style="info" %}
We use `--constructor-args` to specify the arguments for our constructor.
{% endhint %}

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

### Mint An NFT&#x20;

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

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

{% hint style="info" %}

* You should replace `0xd382De234f8d3f1DB54C856498a9DbC84c` with the address of your ERC721 contract.&#x20;
* And `0x6Dfc34a4a2FC03Ba5d5ff95566781bD2b39702fc` is the address that receives the newly minted NFT.&#x20;
* Finally, `1337` is the id of the newly minted NFT.&#x20;
  {% endhint %}

We can also verify the owner of this newly minted NFT by using `cast` again:&#x20;

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