Mint an NFT on zkSync 2.0
Tags: zksync, nft, hardhat, ethereum
Published: 2022-07-10 09:41:57

As we now live in a [rollup-centric world](https://www.youtube.com/watch?v=XoQUc3rnKPM), minting an NFT on  Ethereum Mainnet (L1) is getting less and less relevant. [zkSync 2.0](https://blog.matter-labs.io/zksync-2-0-public-testnet-is-live-de870ba9632a) public testnet went live in February 2022, so let's just give it a try! 

Please note that zkSync 2.0 _Mainnet_ is not available yet, but the whole community is waiting for the announcement. When it's out, you'll be ready to deploy your NFT contract. 

We'll work with this Github repository, you can go ahead and clone or fork it: 

[https://github.com/julienbrg/zksync-minter](https://github.com/julienbrg/zksync-minter)

I mainly used [zkSync 2.0 quickstart](https://v2-docs.zksync.io/api/hardhat/getting-started.html).

### Prerequisites

Please make sure you have the two following tools in place: 

- [Yarn](https://classic.yarnpkg.com/lang/en/docs/install)
- [Docker](https://www.docker.com/get-started/)

## Add your own keys

Rename the `.env.example` to `.env`. To run the app, you need these three keys to be valid. 

### Web3 Storage

As you might know, Web3 Storage uses IPFS and Filecoin. We'll use that to store the metadata of our NFT in a rather persistent way. 

### Infura

You can signup and get a project ID directly on Infura's website: [https://infura.io/](https://infura.io/) 

### Wallet private key

From your ArgentX browser wallet, you can export one of your accounts' private key. Make sure you have a handful of Goerli ETH on this wallet. 

Now you can

```shell
yarn
```

## Edit the NFT smart contract

In case if your new, an NFT is just a unique digital object. Wether it's a gaming asset, a ticket to a party or an artwork, it most often can be transferred, that's the main feature of an NFT.

I used the [Contracts Wizard](https://wizard.openzeppelin.com/#erc721) provided by the all mighty OpenZeppelin team.

It's a very basic ERC-721 contract. In the constructor, you attach the NFT metadata, mint the ID 1, transfer it to yourself and then revoke the ownership of the contract so that absolutely nobody can mint another NFT with this contract (including yourself).

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

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

contract Thistle is ERC721, ERC721URIStorage, ERC721Burnable, Ownable {
    
    constructor(string memory uri) ERC721("Thistle", "THISTLE") {
        safeMint(msg.sender, 1, uri);
        renounceOwnership();
    }

    function _baseURI() internal pure override returns (string memory) {
        return "https://ipfs.io/ipfs/";
    }

    function safeMint(
        address to,
        uint256 tokenId,
        string memory uri
    ) public onlyOwner {
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    function _burn(uint256 tokenId)
        internal
        override(ERC721, ERC721URIStorage)
    {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }
}
```

You can change the name of the contract (`Thistle`), and also the name and symbol of the NFT in `ERC721("Thistle", "THISTLE")`. 

Once you've done that, your contract is ready. 

You can: 

```shell
yarn hardhat compile
```

## Edit the NFT metadata

In the `nft` directory, open the `metadata.json` file and edit this file exactly like you want. You can use [Web3.Storage](https://web3.storage/account/) to store an image and paste the url as the value of `image`.

## Deploy

```shell
yarn hardhat deploy-zksync
```

You should get something like this: 

![deployment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3u8kdgxplij7hb7s6g38.png)

Now you can copy the address of your contract and paste in the search bar of the [zkSync 2.0 explorer](https://zksync2-testnet.zkscan.io/). Here's my deployment transaction: 

[https://zksync2-testnet.zkscan.io/tx/0x567037335a70bb01c02bb5f5f6ee2a777f37fc3a3b0c13bae62165e1dbc24c92/token-transfers](https://zksync2-testnet.zkscan.io/tx/0x567037335a70bb01c02bb5f5f6ee2a777f37fc3a3b0c13bae62165e1dbc24c92/token-transfers)

![tx screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2q2uzk9xyjsprhiccfon.png)

You have deployed your NFT contract to zkSync 2.0 testnet and minted 1 NFT! 🎉

**[View this NFT on Āto](https://ato.network/ZkSync/0xccA0521D453cA8C84Cb0b56936A4B764992b2F12/1)**

You now hold this NFT in your wallet. The tx was confirmed within 3 seconds. If we were on Mainnet it would have costed less than 0.02 USD equivalent.

When the time's right, you'll be able to:

- move your NFT to Ethereum Mainnet (L1)
- move it to another L2
- build an interface to sell it using the [zkSync development toolbox](https://v2-docs.zksync.io/dev/guide/hello-world.html)
- add a personalized IP license using [Āto](https://ato.network/license)
- store it safely using [Argent](https://www.argent.xyz/)

If you have any question, feel free to [call me](https://meetings-eu1.hubspot.com/julien-beranger) or [file an issue](https://github.com/julienbrg/zksync-minter/issues). 

Thanks for reading! 

Photo by [Jay Mantri](https://unsplash.com/@jaymantri?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)