We could follow an already published nice Counters.sol
so we will deploy and mint NFT without such contracts in this article.
Also, there are significant modifications in the contract and configuration files. In the end, the tutorial assists you in minting your NFTs on the RSK mainnet. Everything is mentioned stepwise so even if you have a non-technical background, you are also expected to create your NFTs on the Rootstock network. Here, I have picked a couple of royalty-free images of my idol Nikola Tesla for testing purposes.
After a whole journey, I hope you’d say, “Ah-ha! I could build real NFTs in Rootstock mainnet too.”
Alright, before starting the development process, let’s have a look at the prerequisites.
Requirements
Please kindly have an idea about basic knowledge of the following programming languages and tools to proceed with the tutorials.
- Ideas about code functionalities of JavaScript and Solidity
- A free account on
Pinata IPFS for storing and sharing contents securely. - Configured Hardhat development environment to connect to the RSK Testnet(Prefer this
guide ). - Ethers.js JavaScript library
- Node.js
- The Test Smart Bitcoin (tRBTC)
- MetaMask Wallet
Now, let’s create a project folder; let’s say Nikola NFT
. After that, your project directory has to follow the following format. Don’t worry, you don’t need all the files and folders now shown in the following directory; they come stepwise.
Log in to your Pinata account, and upload two images. Here, I have uploaded two images of Nikola Tesla(NikolaT1.jpg
and NikolaT2.jpg
). You can upload your desired one like your own art. Please note the CIDs of each image which are required in metadata.
Create NFT metadata in JSON files for each image as follows:
For the first NikolaT1.jpg
, the JSON file is nikola1.json
{
"attributes": [
{
"trait_type": "Occupation",
"value": "Inventor"
},
{
"trait_type": "Known For",
"value": "AC Power"
}
],
"description": "Nikola T1. Renowned inventor known for AC Power.",
"image": "ipfs://QmbzK6GPksM4SiQTXurV4eYoEdTZwDdhG5rko2dXwaDq8P",
"name": "Nikola T1"
}
For the first NikolaT2.jpg
, the JSON file is nikola2.json
{
"attributes": [
{
"trait_type": "Occupation",
"value": "Inventor"
},
{
"trait_type": "Known For",
"value": "AC Power"
}
],
"description": "Nikola T2. Renowned inventor known for AC Power.",
"image": "ipfs://QmXuvshQJ7jAKy1TeHwFjbs4mfwDerighf45JcnfRhbtet",
"name": "Nikola T2"
}
Please feel free to add your image attributes for your NFT metadata in the above JSON codes. Upload the two .json
files in Pinata following the same procedures as uploading two images.
Download the MetaMask browser extension, create a new wallet, note down the secret phrases, and create .secret.json
file in the project’s root directory Nikola NFT.
{
"mnemonic": "idiot flatter systematic rose phone fluse pest physics open comb annual pot"
}
Please note the secret phrases have to be kept safely. You have to add your phrases to the .json
file.
You need to have some tRBTC in your MetaMask wallet address. Go to the RSK faucet site to get it. Once you’re done, you should have 0.05 tRBTC in your wallet, check it via the Rootstock testnet explorer by pasting your wallet address.
Create a contract deployment script (scripts/deploy.js
) in your project’s root directory.
async function main() {
const nftContractFactory = await ethers.getContractFactory('NikolaTesla');
const nftContract = await nftContractFactory.deploy();
await nftContract.deployed();
console.log(`Nikola Tesla NFT deployed to: ${nftContract.address}`);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Now, you need to configure the Hardhat with the file hardhat.config.js
.The script sets up Hardhat to deploy and mint our NFTs on the RSK Testnet. Here, I have arranged the code to import the necessary modules and load the mnemonic from .secret.json
file. The code defines tasks to deploy the NikolaTesla NFT
contract and mint new NFTs using IPFS CIDs sequentially.
/* eslint-disable no-undef */
require('@nomiclabs/hardhat-waffle');
const { mnemonic } = require('./.secret.json');
task('deploy', 'Deploys smart contract to a blockchain').setAction(async () => {
const [deployer] = await ethers.getSigners();
const nikolaTeslaContractFactory = await ethers.getContractFactory('NikolaTesla');
const nikolaTeslaNft = await nikolaTeslaContractFactory.deploy(deployer.address);
await nikolaTeslaNft.deployed();
console.log(
`NikolaTesla NFT deployed to: ${nikolaTeslaNft.address}\nCopy this address and paste to the 'mint' task in 'hardhat.config.js'`,
);
});
task('mint', 'Mint new NFT collectibles').setAction(async () => {
const deployedAddress = '0xD04c326B3c1E6C2dDc28cAedCd52AFe17Ff4330b'; // Update this to the correct address after deployment
const newCIDsToMint = [
'QmbX6jmxLAq62rFkGPvAkLpihuyhT63SWxegEaSPoaUw7A',
'Qmd9pWgVUywEhki1BpXc1FxYdjgBnoSebMVrDr4K9onZqP',
];
const api = (await ethers.getContractFactory('NikolaTesla')).interface;
const [signer] = await ethers.getSigners();
const nikolaTeslaNft = new ethers.Contract(deployedAddress, api, signer);
async function mintSequentially() {
const cid = newCIDsToMint.shift();
if (cid) {
const tx = await nikolaTeslaNft.mintNFT(signer.address, `ipfs://${cid}`);
const receipt = await tx.wait();
console.log(receipt.events); // Add this line to debug events
if (receipt.events && receipt.events.length > 0) {
const { tokenId } = receipt.events[0].args;
console.log(`Minted NFT ${deployedAddress} #${tokenId}`);
await mintSequentially();
} else {
console.log('No events found in receipt');
}
}
}
await mintSequentially();
});
module.exports = {
solidity: '0.8.20',
defaultNetwork: 'rsktestnet',
networks: {
hardhat: {},
rsktestnet: {
chainId: 31,
url: 'https://public-node.testnet.rsk.co/',
accounts: {
mnemonic,
path: "m/44'/60'/0'/0",
},
},
},
};
Here are two CIDs under const newCIDsToMint = [
, are from .json
files uploaded on Pinata not the CIDs of your images. If you add CIDs of images, you will get the blank NFTs at the end.
For now, you need not necessarily change the wallet address 0xD04c326B3c1E6C2dDc28cAedCd52AFe17Ff4330b
in the code; you are doing this later. Please remember this step! For a more detailed code breakdown, please care to follow this guide.
Create a contracts
folder in the root directory, and create a solidity file entitled NikolaTesla.sol
in it.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract NikolaTesla is ERC721URIStorage, Ownable {
uint256 private _tokenIds;
constructor(address initialOwner) ERC721("NikolaTesla", "NT") Ownable(initialOwner) {}
function mintNFT(address recipient, string memory tokenURI) public onlyOwner returns (uint256) {
_tokenIds++;
uint256 newItemId = _tokenIds;
_mint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
In the code, we have used the OpenZeppelin contracts library so you are expected to install it by running the following command in the terminal.
npm install @openzeppelin/contracts
Please note that the recent OpenZeppelin contracts library doesn’t contain the counters.sol
file mentioned in the contract example of the project’s guide. So, I’ve made a significant modification to this NikolaTesla.sol
file to get in tune with the recent updates from OpenZeppelin. It doesn’t need counters.sol
to deploy and mint my NFTs.
If you prefer to have it, you might manually add it from here to the node_modules
directory. Here, we are just importing two contracts ERC721URIStorage.sol
and Ownable.sol
from OpenZeppelin.
It’s time to deploy our NFTs on the Rootstock. First, open the terminal from your project’s directory, and run the following command.
npx hardhat compile
After the code execution, you will see the following messages in the terminal.
Deploy the NikolaTesla NFT by running the following command in the terminal.
npx hardhat deploy --network rsktestnet
Once you succeed in executing the code in the terminal. you will see something like this.
Now, do you catch it? I asked you to remember the step earlier 😊. Copy the deployed address, and replace the address in hardhat.config.js
configuration file and update it.
After that, mint your NFTs. Run the following command in the terminal.
npx hardhat mint --network rsktestnet
If everything is ok, you will be able to locate contract addresses and token IDs for two NFTs followed by #
like as shown in the figure. In our case, we have two IDs #1
and #2
for the token’s contract address 0xD04c326B3c1E6C2dDc28cAedCd52AFe17Ff4330b
So, how to see your NFTs? Well, this can be your genuine question because you may not see your NFTs in your MetaMask wallet yet. Let’s follow the following steps:
On your MetaMask wallet, go to Select Network>Add network>Custom RPC, and then enter the following information.
- Network Name
RSK Testnet
- New RPC URL
https://public-node.testnet.rsk.co
- ChainID (optional)
31
- Symbol (optional)
tRBTC
Select the recently added network navigate the NFTs section, and select Import NFT. Fill in the Address and Token ID displayed on the terminal.
Finally, you can see your NFTs in the Rootstock testnet as follows:
Wow, we have just made NFTs live on Rootstock’s testnet. It was the objective approach to deploy and mint NFTs on testnet. The procedures are almost the same to deploy and mint NFTs on Rootstock’s mainnet as well. You just need to make minor changes and adjustments in the codes.
Steps you can prefer to deploy and mint NFTs on Rootstock's Mainnet:
The article attempted to offer the best possible tutorials by keeping security in mind but nothing is 100% perfect; I recommend you make sure your smart contract code is robust and free from vulnerabilities. Also prefer project’s documentation for the deeper insights.
- Check and review the smart contract:
- Please care to verify all imports and dependencies are up-to-date and compatible.
- Configure your MetaMask wallet to point to Rootstock mainnet and switch into it.
Remember, you need to have RBTC in your wallet to cover the transaction fees.
- Update configuration:
Modify your hardhat.config.js
to point to the Rootstock mainnet. Update the networks section as follows:
module.exports = {
solidity: '0.8.20',
defaultNetwork: 'rskmainnet',
networks: {
hardhat: {},
rskmainnet: {
chainId: 30,
url: 'https://public-node.rsk.co/',
accounts: {
mnemonic,
path: "m/44'/60'/0'/0",
},
},
},
};
- Deploy smart contract to mainnet:
The process to execute the deploy task to deploy your contract to the mainnet is as follows:
npx hardhat deploy --network rskmainnet
- Mint NFTs on mainnet:
Update the deployedAddress
with the mainnet contract address in your configuration file hardhat.config.js
and run the mint task:
npx hardhat mint --network rskmainnet
- Verify deployment:
In the same way, you have to import your NFTs on MetaMask to check if they are available on the RSK mainnet. You can also use blockchain RSK Explorer to verify the contract deployment and minted NFTs.
Done! Now, you are also able to create NFTs on Rootstock’s mainnet. It is the practical approach that you can convert your paintings, famous photos, and rarest photos with undisputable ownership of your digital properties on the blockchain network. It can also unlock earning opportunities with the help of decentralized blockchain technology.
If you have any issues please let me know in the comment section below, I try my best to help 🙏
Conclusion
We have tested NFTs on the RSK testnet first to make sure it is error-free and no vulnerabilities are present in them. Also, it helps us to have a secure, efficient, and bug-free deployment on the mainnet. In this tutorial, we first tried to test codes, compiled the codes, and then headed towards the testing phase on the RSK testnet. NFTs have had a great impact on the digital world by revolutionizing ownership of digital assets or properties, monetization, and distribution of digital content. Both users and creators can get benefits from NFTs in so many ways.
The tutorial has attempted to offer easy-to-understand instructions for any sort of user in simple language. It is quite challenging to break down complex technical concepts in understandable languages but we attempted it in this tutorial. Overall, it is a practical way to create your NFTs and mint on the blockchain network.