# Write & Deploy an NFT

With NFTs bringing blockchain into the public eye, now is an excellent opportunity to understand the hype yourself by publishing your own NFT contract (ERC-721 Token) on the Asset Chain blockchain!.

In this tutorial, we will walk through creating and deploying an ERC-721 smart contract on the Asset Chain test network using [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), and [Hardhat](https://hardhat.org/),

### STEP 1: CREATE AN ASSET CHAIN ACCOUNT (ADDRESS) <a href="#connect-to-ethereum" id="connect-to-ethereum"></a>

We need an Asset Chain account to send and receive transactions. For this tutorial, we’ll use MetaMask, a virtual wallet in the browser used to manage your Asset chain account address.

You can download and create a MetaMask account for free [here](https://metamask.io/download.html). When you are creating an account, or if you already have an account, make sure to switch over to the “[Asset Chain Testnet](https://docs.assetchain.org/general-info/add-asset-chain#testnet)”

<figure><img src="https://285329334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmuBv3mR5xhQRl9pMrnhC%2Fuploads%2Fgit-blob-d2a3f31ecc6dbb767b704a66deffa9bacbddadec%2Fimage%20(1).png?alt=media" alt=""><figcaption></figcaption></figure>

### STEP 2: ADD RWA FROM A FAUCET <a href="#step-4-add-ether-from-a-faucet" id="step-4-add-ether-from-a-faucet"></a>

In order to deploy our smart contract to the test network, we’ll need some fake RWA. To get RWA you can go to the [$RWA Faucet](https://faucet.assetchain.org/), enter your account address, click “start mining”. You should see RWA in your MetaMask account soon after!

<figure><img src="https://285329334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmuBv3mR5xhQRl9pMrnhC%2Fuploads%2Fgit-blob-125253aedd143694a9112ff40041e9d22c6f7863%2Fimage%20(2).png?alt=media" alt=""><figcaption></figcaption></figure>

### STEP 3: FORK AND CLONE THIS STARTER KITS <a href="#connect-to-ethereum" id="connect-to-ethereum"></a>

{% embed url="<https://github.com/xendfinance/Write-Deploy-an-NFT/>" %}

go to your terminal , navigate to the folder and install neccssary dependencies using `yarn install`.

### STEP 4: WRITE OUR CONTRACT <a href="#write-contract" id="write-contract"></a>

Now that our environment is set up, on to more exciting stuff: *writing our smart contract code!*

Open up the my-nft project in your favorite editor (we like [VSCode](https://code.visualstudio.com/)). Smart contracts are written in a language called Solidity which is what we will use to write our NFT.sol smart contract.‌

1. Navigate to the `contracts` folder and create a new file called NFT.sol
2. Below is our NFT smart contract code, which we based on the [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc721) library’s ERC-721 implementation. Copy and paste the contents below into your NFT.sol file.

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

import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract NFT is ERC721URIStorage {
	uint256 private _nextTokenId;

    constructor() ERC721("MyNFT", "ATM") {}
     function mintNft(address  recipient, string memory tokenURI)
        public
        returns (uint256)
    {
        uint256 tokenId = _nextTokenId++;
        _mint(recipient, tokenId);
        _setTokenURI(tokenId, tokenURI);

        return tokenId;
    }
}


```

So, what does this code *do* exactly? Let’s break it down, line-by-line.

At the top of our smart contract, we import three [OpenZeppelin](https://openzeppelin.com/) smart contract classes:

* The [`ERC721URIStorage`](https://docs.openzeppelin.com/contracts/5.x/api/token/ERC721#ERC721URIStorage) contract is an implementation of ERC721 that includes the metadata standard extensions ([`IERC721Metadata`](https://docs.openzeppelin.com/contracts/5.x/api/token/ERC721#IERC721Metadata)) as well as a mechanism for per-token metadata. That’s where the [`_setTokenURI`](https://docs.openzeppelin.com/contracts/5.x/api/token/ERC721#ERC721-_setTokenURI-uint256-string-) method comes from: we use it to store an item’s metadata.
* @openzeppelin/contracts/access/Ownable.sol sets up [access control](https://docs.openzeppelin.com/contracts/3.x/access-control) on our smart contract, so only the owner of the smart contract (you) can mint NFTs. (Note, including access control is entirely a preference. If you'd like anyone to be able to mint an NFT using your smart contract, remove the word Ownable on line 10 and onlyOwner on line 17.)

After our import statements, we have our custom NFT smart contract, which is surprisingly short — it only contains a counter, a constructor, and single function! This is thanks to our inherited OpenZeppelin contracts, which implement most of the methods we need to create an NFT, such as `ownerOf` which returns the owner of the NFT, and `transferFrom`, which transfers ownership of the NFT from one account to another.

In our ERC-721 constructor, you’ll notice we pass 2 strings, “MyNFT” and “NFT.” The first variable is the smart contract’s name, and the second is its symbol. You can name each of these variables whatever you wish!

Finally, we have our function `mintNFT(address recipient, string memory tokenURI)` that allows us to mint an NFT! You'll notice this function takes in two variables:

* `address recipient` specifies the address that will receive your freshly minted NFT
* `string memory tokenURI` is a string that should resolve to a JSON document that describes the NFT's metadata. An NFT's metadata is really what brings it to life, allowing it to have configurable properties, such as a name, description, image, and other attributes. In part 2 of this tutorial, we will describe how to configure this metadata.

`mintNFT` calls some methods from the inherited ERC-721 library, and ultimately returns a number that represents the ID of the freshly minted NFT.

### STEP 5: CONNECT METAMASK TO YOUR PROJECT <a href="#connect-metamask-and-alchemy" id="connect-metamask-and-alchemy"></a>

Now that we’ve created a MetaMask wallet and written our smart contract, it’s time to connect the two.

Every transaction sent from your virtual wallet requires a signature using your unique private key. To provide our program with this permission, we can safely store our private key in an environment file.

create a `.env` file in the root directory of our project, and add your MetaMask private key

* Follow [these instructions](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) to export your private key from MetaMask

Your `.env` should now look like this:

```
DEPLOYER_PRIVATE_KEY="your-metamask-private-key"
```

### STEP 6: UPDATE OUR DEPLOYMENT SCRIPTS <a href="#compile-contract" id="compile-contract"></a>

Now that our contract is written and our configuration file is good to go, it’s time to write our contract deploy script.

Navigate to the `deploy/00_deploy_your_contract.ts` folder , adding the following contents to it:

```

import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

/**
 * Deploys a contract named "YourContract" using the deployer account and
 * constructor arguments set to the deployer address
 *
 * @param hre HardhatRuntimeEnvironment object.
 */
const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
  /*

    When deploying to live networks (e.g `yarn deploy --network assetchain_testnet`), the deployer account
    should have sufficient balance to pay for the gas fees for contract creation.

    You can generate a random account with `yarn generate` which will fill DEPLOYER_PRIVATE_KEY
    with a random private key in the .env file (then used on hardhat.config.ts)
    You can run the `yarn account` command to check your balance in every network.
  */
  const { deployer } = await hre.getNamedAccounts();
  const { deploy } = hre.deployments;

  const myNft = await deploy("NFT", {
    from: deployer,
    log: true,
    // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
    // automatically mining the contract deployment transaction. There is no effect on live networks.
    autoMine: true,
  });


  console.log("👋 NFT Contract Address:", myNft.address);
};

export default deployYourContract;

// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags NFT
deployYourContract.tags = ["NFT"];


```

### STEP 16: DEPLOY OUR CONTRACT <a href="#deploy-contract" id="deploy-contract"></a>

We’re finally ready to deploy our smart contract! Navigate back to the root of your project directory, and in the command line run:

```
yarn deploy --network assetchain_testnet
```

You should then see something like:

```
👋 NFT Contract Address: 0x342E4f63a50D2328fe127fbC5cfdFD5a16e047eA
```

{% hint style="success" %}
Congratulations! Your contract is successfully depolyed on Asset Chain Blockchain.
{% endhint %}

If we go to the [Asset Chain explorer ](https://testnet.assetchain.org/)and search for our contract address we should be able to see that it has been deployed successfully.

See the Completed Code Below 👇

{% embed url="<https://github.com/xendfinance/Write-Deploy-an-NFT/tree/updated>" %}

If you have questions, join our [Telegram](https://t.me/XendFinanceDevs) and say hello 👋. We're Active!
