How To make an ERC- 721 NFT Participation Certificate for your event/webinar etc.
Nowadays most of the offline events are happening online, like the guest lectures, an college event or an webinar by an expert. Most of the event organisers issue certificates to the people who have attended the session throughout, They just take the template from internet and paste the names, event name, event heads etc, without knowing that it could be forged easily as they mostly don’t have any identity to prove that certificate is given to this person. So for this, we would make an NFT Certificate of participation which would not just look cool, but would eliminate any chances for forgery of certificates. So lets start.
Pre- requisites-
- preferably An Linux/ macOS installed system
- basic knowledge of smart contracts and ERC-20 protocol
- Metamask installed into chrome browser.
Setting up the environment-
Open terminal and create a new project.
$ mkdir NFTCert&& cd NFTCert
$ npm init -y
You would see something like this..
Then we install OpenZeppelin Contracts 88 which has an implementation of ERC721.
npm install --save-dev @openzeppelin/contracts
Next we install a development tool for deployment, for this tutorial we will use Truffle 70 but we could use any other tools such as Buidler, Remix or OpenZeppelin CLI 28.
npm install truffle
Getting the contract artifacts
We will setup our Solidity project using truffle init
to create a contracts
directory and configuration to connect to a network.
$ npx truffle init
Upon success-full setup, we would see
Unbox successful, sweet!
now we need to copy the artifacts to the build/contracts
directory.
$ mkdir -p build/contracts/
$ cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/
Now go to migrations folder in NFTCert and create an javascript file called 2_deploy.js
using any editor and paste the following there-
// migrations/2_deploy.js
// SPDX-License-Identifier: MIT
const ERC721PresetMinterPauserAutoId = artifacts.require("ERC721PresetMinterPauserAutoId");module.exports = function(deployer) {
deployer.deploy(ERC721PresetMinterPauserAutoId, "My NFT","NFT", "https://my-json-server.typicode.com/taylor2325/NFTCert/tokens");
};
Now the above URL- https://my-json-server.typicode.com/taylor2325/NFTCert/tokens is the URL For the metadata of the NFT we are creating. To create this metadata on my-json-server, follow this link- https://my-json-server.typicode.com
Upon setting up metadata, it would look something like this-
Here-
- “id” is the ID for the NFT you have published, it would be useful in minting the NFT.
- “description” is the description of the NFT, It would be shown as what this NFT is for etc.
- “external_url” points to the website if you want to add.
- “image” is the image an NFT would be showing. pinata is preferred for external image. In this project, our certificate is the image.
- “name” is the name of the NFT you want to give
for adding more NFTs, just copy this 5 things and paste it below id 0, but rename it to id 1 and make the preferred changes in image and name. for image, we are using pinata as it uses ipfs to store the image. To learn how to set up, you can follow the link here- https://www.youtube.com/watch?v=wPWzuGBnLgM
Deploying to the Rinkeby testnet
For deploying to the Testnet, we need following pre-requisites-
- An Infura project ID (or a public node provider of your choice). follow link here to make your new project ID
@truffle/hdwallet-provider
installed (To install, simply write npm install @truffle/hdwallet-provider)- Configure
truffle-config.js
for Rinkeby network - A funded testnet account and mnemonic
To configure truffle-config.js
simply paste the following code WITH YOUR PERSONAL MNEMONIC AND INFURA PROJECTID
const fs = require('fs');const HDWalletProvider = require('@truffle/hdwallet-provider');var mnemonic = ""; // Your personal mnemonicvar projectId = ""; // your Personal projectIDmodule.exports = {networks: {rinkeby: {provider: () => new HDWalletProvider(mnemonic, `https://rinkeby.infura.io/v3/${projectId}`),network_id: 4, // Rinkeby's idgas: 8500000,gasPrice: 1000000000, // 1 gwei (in wei) (default: 100 gwei)confirmations: 2, // # of confs to wait between deployments. (default: 0)timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)skipDryRun: true // Skip dry run before migrations? (default: false for public nets )},},mocha: {// timeout: 100000},compilers: {solc: {// version: "0.5.1", // Fetch exact version from solc-bin (default: truffle's version)// docker: true, // Use "0.5.1" you've installed locally with docker (default: false)// settings: { // See the solidity docs for advice about optimization and evmVersion// optimizer: {// enabled: false,// runs: 200// },// evmVersion: "byzantium"// }}},db: {enabled: false}};
Deploy to Rinkeby
Now after successful setup, we would deploy the smart contract to the testnet
$ npx truffle console --network rinkeby
truffle(rinkeby)> migrateCompiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.Starting migrations...
======================
> Network name: 'rinkeby'
> Network id: 4
> Block gas limit: 10000000 (0x989680)1_initial_migration.js=====================Deploying 'Migrations'---------------------
> transaction hash: 0x9008f27679da63b92289ae4e4eacfbd5558ceed7c7c7fe2a56ef4218a2d11fb5> Blocks: 0 Seconds: 13
> contract address: 0x1CD15A3D13FA90F9607359F0D667C8f3c99D822a
> block number: 8875873
> block timestamp: 1625375314
> account: 0x993E6B1Cf39135Cd6BCdb87Ff9E6bab538035FF3
> balance: 16.035155549
> gas used: 193219 (0x2f2c3)
> gas price: 1 gwei
> value sent: 0 ETH
> total cost: 0.000193219 ETHPausing for 2 confirmations...
------------------------------
> confirmation number: 1 (block: 8875874)
> confirmation number: 2 (block: 8875875)
> Saving migration to chain.
> Saving artifacts-------------------------------------> Total cost: 0.000193219 ETH2_deploy.js===========Deploying 'ERC721PresetMinterPauserAutoId'
------------------------------------------
> transaction hash: 0xece55d4302e9de76195318bdfa14be7ca36f2527a26ef1f2635290cd5f361cbe
> Blocks: 2 Seconds: 21
> contract address: 0xF3255e17dD5d9DD8885C3E25eF72bbdc13974F82
> block number: 8875878
> block timestamp: 1625375389
> account: 0x993E6B1Cf39135Cd6BCdb87Ff9E6bab538035FF3
> balance: 16.032520751
> gas used: 2589060 (0x278184)
> gas price: 1 gwei
> value sent: 0 ETH
> total cost: 0.00258906 ETHPausing for 2 confirmations...------------------------------> confirmation number: 1 (block: 8875879)
> confirmation number: 2 (block: 8875880)> Saving migration to chain.
> Saving artifacts-------------------------------------> Total cost: 0.00258906 ETHSummary=======> Total deployments: 2
> Final cost: 0.002782279 ETH
Minting our new NFT
We can send a transaction to mint tokens to a given account, from an account with the minter role.
truffle(rinkeby)> nft = await ERC721PresetMinterPauserAutoId.deployed()
undefined
In our case we are minting from the account which deployed the token, which is given the minter role.
To see configured accounts run the command accounts
.
truffle(rinkeby)> accounts
['0x993E6B1Cf39135Cd6BCdb87Ff9E6bab538035FF3',
'0xf92827b75548789f90F80bf490Bf00b4DBaACFd1',
'0x2F0dD71a474B35818058723C74D86D941ba94244',
'0x1b79D6b7586aA9a364A297468Ca701aD1425CF70',
'0x74a96ee51b99723DeDE2C389c094E1e193Fa62D8',
'0x0dd3986B3118B33840cC71840b33cA241968b08b',
'0xCeE9fF1eb2eC25A92851949F2DA0eE4510581BB2',
'0xA6dE1B45f9623908060F5654aF99BA5dAFbB80a3',
'0x4C1f6718Cd420eA237e2735B502B4d9613114DA4',
'0x2Ced4bB916f18CA52B3Df957a02fFa4b4cb74B82']
We will mint 1 NFT with token ID 0. Specify the address that you want to be the token holder (0x993E6B1Cf39135Cd6BCdb87Ff9E6bab538035FF3 is one of my test accounts)
We will mint 1 NFT with token ID 0.
truffle(develop)> await nft.mint("0x993E6B1Cf39135Cd6BCdb87Ff9E6bab538035FF3")
Now we have minted our first NFT participation certificate and it is on the address “0x993E6B1Cf39135Cd6BCdb87Ff9E6bab538035FF3”. Now we would open metamask
goto “add token” and add your newly created contract address
you would see your NFTcert here
Now to interact with your NFT, we would have to go to https://testnets.opensea.io/ (this version of opensea is testnet as we are using Rinkeby testnet)
select your metamask account where your NFTCert is located, then you would see the NFTs in your account
Here we can see our certificate of recognisation for Ankur Kumar(which I have made)
Finishing up…
Now the last step is to make an QR Code so that the participant could see the NFT on the opensea.
the link is https://testnets.opensea.io/assets/0x2d53ffed3ac200ff0c7ba7edd85836aa34cba92f/0
After making QR code for above URL, The final certificate which could be given to the participant is-
Last Thoughts…
ERC-721 is an ethereum protocol which distinguishes one token from another, simple ERC-20 Tokens could be exchanged one to one, but ERC-721 tokens could not. These tokens are known as NFT or non-fungible tokens and could be used in variety of ways- making a game character, giving a distinguishable characterstic to any digital thing and many more. This project would help not to make an cool certificate to give to participants, but would also help to reduce counterfeit certificates
The github link for the project is https://github.com/taylor2325/NFTCert
Thanks.