In this series of blogs, I am going to show how to create an on-chain and off-chain NFT collection smart contract and create a DApp to mint NFTs.
I am also going to show how to create your own DApp which I designed for fun last year and also to learn about NFTs and DApps.
The idea to create an NFT DApp is inspired by the loot project but I also want to add my own flavors of creativity to it and understand the working of smart contracts in the process.
Before this, I tried out different things like building my own token on the Ethereum test network back in July 2021 when I am new to cryptocurrency space and understanding little things like how merkle tree is used.
It is this time when I learned about remix IDE, MetaMask wallet, different test networks of Ethereum blockchain, deploying smart contracts through remix IDE. I also learned little things like we can deploy the same contract which deployed on Ethereum blockchain on other blockchains like Binance Smart Chain.
I have decided what to build but don’t know how. I began exploring some resources with little knowledge and found this solidity tutorial from a Reddit post.
I have gone through the solidity basics to understand code from verified smart contracts and to develop new ones.
After getting a bit of knowledge on solidity, I began exploring the smart contract of the loot project. It didn’t make much sense but after spending some time with it, I understood the working.
I know ERC-721 standard is used to build NFTs and ERC-20 standard to build our own token on Ethereum blockchain but don’t know what functions exactly we need to define in those standards.
I referred to openzeppelin docs to understand more about the functions in the ERC-721. So, without any further journey lessons, I will jump into smart contract development.
To develop our own NFT smart contract, we require
Ownable Smart contract
[transferOwnership(newOwner)](https://docs.openzeppelin.com/contracts/2.x/api/ownership#Ownable-transferOwnership-address-)
method.[renounceOwnership()](https://docs.openzeppelin.com/contracts/2.x/api/ownership#Ownable-renounceOwnership--)
[onlyOwner()](https://docs.openzeppelin.com/contracts/2.x/api/ownership#Ownable-onlyOwner--)
modifier to let some functions get executed by the only owner like starting the sale, pausing the contract, Give away NFTs from the contract.Enumerable721 Smart contract
ReentrancyGuard Smart Contract
[nonReentrant](https://docs.openzeppelin.com/contracts/4.x/api/security#ReentrancyGuard-nonReentrant--)
modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them.nonReentrant
may not call one another.Pausable Smart Contract
whenNotPaused
and whenPaused
available which can be applied to the functions of your contract.
We can make our main smart contract extend these smart contracts directly by importing these in our code.
The code is found here for Loot Royale Onchain NFT Smart Contract - https://gist.github.com/pranaybathini/52f4ff2da4c3518855264febe7d95739
Let us discuss the functions inside the main smart contract - BattleRoyale.sol
Three functions are important.
Here is what one of my NFTs looks like.
A simple HTML CSS Design inside svg tag with curved border and it also displays the token ID at the top. It took some time for me to realize that we can include html CSS inside svg tag. Initially, I took the HTML CSS code and used this site to convert to SVG but the output svg size is very heavy.
Another problem I faced while storing this data for design was that the max size of a smart contract cannot be more than 24576 bytes. So, I moved the code to another smart contract then to library, just so to reuse it in another contract. This is just one line but took some time since I tried optimizing it first before realizing I can do move this to another contract. Learning++.
Here is the link to SVG Code for the above NFT.
Also, you can see my data in the code which is different from loot project. You should have guessed by now where I gotmy data from. Now let’s see what are on-chain vs off-chain NFTs.
The difference between on-chain and off-chain NFTs as the name suggests we will be storing all the data related to NFTs on the blockchain itself for on-chain NFTs.
In the case of off-chain, I need to provide some external URLs like https://somedomain.com , ipfs://sha256hash/1.png.
In both cases, I need to return the JSON output file following the NFT metadata standard.
A sample IPFS image URL looks like this -
ipfs://QmV3yGkzx2Uw3NHPZV9SAMLA58j7LvCFLFYtyfCMBAvstF/2.jpg
You can open this in brave browser directly - a pin I have drawn on the art flow mobile app a long time back.
If we were to create off-chain NFTs, what would the code look like?
Refer to this github gist link for offchain smart contract.
I will set the IPFS or HTTPS BASE URI in the contract when the sale starts or nowadays, the developers are revealing the NFTs after all NFTs are minted.
It is simple to write a function to set URI variable and call it once all NFTs are minted.
There are two variables
The URI we should set will be like ipfs://QmV3yGkzx2Uw3NHPZV9SAMLA58j7LvCFLFYtyfCMBAvstF/
When we query, our token Id gets appended to it and Open Sea or any other marketplace can find and display it.
Starting steps are to set the contract active, then set the blind URI. Once all NFTs are minted, you can reveal the NFTs minted.
The tokenURI method output will look like
{
"image": "ipfs://QmV3yGkzx2Uw3NHPZV9SAMLA58j7LvCFLFYtyfCMBAvstF/1.png",
"name": "Loot Royale 1",
"description" : "Some description"
}
Now we have our contracts, how do we deploy them to the blockchain network. Many blockchains forked Ethereum with added changes to bring DApp development features. You can deploy to any network that supports solidity.
Let us deploy this on-chain NFT smart contract to Ethereum’s Ropsten test network. But before that, we need
You need to select Injected Web3 as an environment, which will allow us to inject metamask and deploy to the network selected on metamask. You should be able to see your metamask account and balance in the accounts section.
When you click on deploy, you will be prompted twice. First, the CardDesign Library is deployed and then our smart contract.
You will receive two metamask notifications once the contracts are deployed. Click on them, you will be redirected to Ropsten block explorer. You can also view the transactions from the activity tab in metamask.
Congrats, now the On-chain NFT smart contract - loot royale has been deployed.
But how do we interact with it? I will explain in detail how to interact with it from our custom react frontend later. Let’s see how to interact with the contract from the block explorer.
FYI, block explorer is also a DApp.
Now, let us verify the contract on the blockchain explorer and interact with it from the explorer itself.
Now, our contract is verified. It looks like the below image. You should see the functions to read and write to the blockchain.
Navigate to the write contract section and click on connect to web3, you will be prompted to connect to a provider like below.
Click on Metamask, it will prompt you to connect. Click on connect to web3 again and you should be able to connect explorer with Metamask like below.
Now click on mintSingle function, it will an NFT. Enter 0.01 as NFT Price like below.
Congratulations. You have successfully minted an NFT. Now, let’s view the token URI.
You can go to testnets.opensea.io, connect your wallet and you should be able to see your Loot Royale NFTs.
In the next blog, I will show how to design the frontend for lootroyale.xyz to mint the loot royale NFTs since this blog has become lengthy already.
Any feedback is appreciated. In case of any doubts or issues or any new ideas, DM me on Twitter - @pranay_bathini. Let us learn together.
Thanks for reading!!
This article was also published here