How to create a Burnable Soulbound NFT

How to create a Burnable Soulbound NFT

We use NFTs to track the ownership of digital art and that is why NFTs are designed to be transferred between blockchain wallets. But Soulbound NFTs are special kinds of NFT which is designed to be owned by a specific blockchain address without the ability to transfer between blockchain wallets.

image.png

Soulbound tokens/NFTs can represent certain information about the holder. It can be some kind of access, passport, documents or even driver’s license. There are other security use cases that can be some kind of login credential or some other blockchain signatures and information.

By making sure about the ownership of a particular SoulBound token, a user can define about the certain attributes they can hold. For example, it can be some on chain credential that displays one’s professional certification or experience and they can use this when applying for jobs or during interviews.

image.png

But SoulBound Tokens/NFTs are still in their very early stages, but we can still implement some special attributes. Let’s say we want to give someone a SoulBound token which they can hold temporarily and after some time it will be burned.

Getting Started

In this tutorial, we will be shipping a Burnable SoulBound Token/NFT.

We will learn how to:

  • Create a burnable SoulBound NFT with ERC721
  • Host NFT metadata on Arweave
  • Deploy it on Polygon Mumbai Testnet
  • Mint and display the NFT on Opensea
  • Burn the NFT from the Wallet

Let’s get to building something cool.

Writing Our Smart Contract

To write our smart contract we need to implement some logic at the top of the NFT smart contract. But before that let’s start with a basic ERC721 smart contract. We need to head over to the open zeppelin wizard, it will give you a simple playground where you can select your desired contract standard along with some features.

Screenshot_20220816_035627.png

We will be naming our contract and putting our own symbol, it’s not mandatory so you can skip that if you want. But we will be selecting some features. We will be selecting Mintable, Auto increment Ids, Burnable and URI Storage.

Once that’s done, then let’s open the base contract on remix by clicking Open in Remix.

Customizing Our Code

Now that we are on remix, we should start customizing our code.

We should have the following code for now.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

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

contract MeowBurn is ERC721, ERC721URIStorage, ERC721Burnable, Ownable {
    using Counters for Counters.Counter;

    Counters.Counter private _tokenIdCounter;

    constructor() ERC721("MeowBurn", "MWO") {}

    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    // The following functions are overrides required by Solidity.

    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);
    }
}


Now it’s time for us to add some additional functionalities. We want to add the following code.

function _beforeTokenTransfer(
    address from, 
    address to, 
    uint256 tokenId
    ) internal override virtual {
    require(from == address(0)|| to == address(0), "Meow cant transfer, meow"); 
    super._beforeTokenTransfer(from, to, tokenId);  
    }

For our SoulBound token we need to implement non-transferable and burnable functionalities. To implement the non-transferable functionalities there are multiple ways. Sometimes people consider deleting the whole transfer function but there are other transfer function that exist as transfer, batch transfer and safe transfer. Which makes your SoulBound token available for transfer even after you delete the transfer function.

But all of them have the same _beforeTokenTransfer function so if we can override that then we can block the transferable ability of the token.

from == address(0)|| to == address(0) the first part of the code from == address(0) means the token is being minted and staying there which means not being transferred. Now the second part of this to == address(0) . So what happens is that it requires to come from the address 0 that means when you mint it comes from 0. And when you burn it goes back to 0 as well.

Deploying The Smart Contract

Screenshot_20220809_004534.png

To compile our smart contract let’s go ahead to the side bar and select solidity compiler. Before compiling our contract, we have to make sure that the compiler version is the same as the one mentioned within our smart contract. When you click Compile MeowBurn.sol , it should compile our smart contract. When you see the green check mark ✅ on the side, that means the contract is successfully compiled.

Now we are should head over to deploy the contract.

image.png

Let’s head over to “Deploy & Run Transactions”, we have to make sure that we are selecting “Injected Provider - MetaMask” then have to make sure that we are selecting our contract to deploy.

Screenshot_20220816_123214.png

Finally it’s time for us to deploy our smart contract. We will deploy our contract on Polygon Mumbai Testnet.

But first we will need to add Polygon Mumbai Testnet network on our wallet. Lets head over to chainlist and select to add the network to the wallet get some Testnet.

Details on adding the network and getting some testnet

Screenshot_20220816_124121.png

To add the Polygon Mumbai network head over to the Chainlist and connect your wallet. Then toggle the testnet button and search for Mumbai. You will see the testnet network with chainID 80001 and add it to the wallet.

Note: Always make sure to use a spare wallet with no money for these tutorials.

Getting Some Testnet

Testnet is an experimental network with sandbox environment where developers can test, create and modify functionalities, monitor the blockchain network performance, fix bugs and other network failures without having to use the real crypto coins or worrying about breaking the main chain.

The cost of operation on mainnet is higher. As every operation performed on the blockchain requires a fee so we can use testnet for testing purposes.

We get testnets from faucets. Faucets are websites which dips small amount of testnets on addresses and sometimes they require completion of small tasks before dipping some testnet on the wallets.

Note: Testnet and mainnet are separate networks. You can not send money from testnet to mainnet.

To get some testnet let’s head over to this website.

Screenshot_20220816_125549.png

If you complete the required tasks that was asked, you can get testnets that are not limited to one kind of testnet.


Now it’s time for us to deploy the contract. When you click the “Deploy” button, you will be asked to confirm the transaction on your wallet.

Screenshot_20220816_130121.png

After confirming on our wallet we will have to wait a bit for our contract to be deployed.

ArDrive and Arweave : Metadata and Image Asset

When the contract will be deployed successfully, we will be minting our Burnable Soulbound NFT as our next step. But to get there at first we need to host our image and metadata on Arweave through ArDrive.

Arweave is a decentralized protocol where we can store our data by paying once, without any renewal fee or anything. It’s more of “Pay Once, Store Forever” method with Arweave. This decentralized storage protocol works in a really interesting way. It connects people who needs to store data on the permanent storage and people who has extra hard drive space to host those data. You can read more information about how Arweave Technology works from here.

To host the metadata and image asset on Arweave through ArDrive, you will need the ArConnect wallet as well as some AR token.

Here’s the steps you need to follow:

Screenshot_20220816_165025.png

  • You need to go to the Arweave Faucet Website
  • Follow the steps that was mentioned on the website
  • After following the steps you should have ArConnect wallet and 0.02 AR test token.

Now we will head over to ArDrive and we will see something like this.

Screenshot_20220816_161444.png

You can use your ArConnect wallet to sign in there. Once you are there, you will notice the NEW button and if you click onto that you will have the option to Upload file(s) by selecting that you can upload the image then the JSON metadata. For Arweave you need to pay to upload the file on the decentralized storage. You will have enough AR token to upload both of the files if you followed the steps that was mentioned earlier.

For our Burnable Soulbound NFT we will use this image.

meowburn.png

Now let’s go ahead and create our JSON metadata based on Opensea Metadata Standard. I already created one but if you want to customize you can go ahead and do that.

{
    "attributes" : [ {
      "trait_type" : "NFT",
      "value" : "Soulbound"
    }, {
      "trait_type" : "Cat",
      "value" : "Non-transferable and Burnable Cat Burning All"
    }, {
        "trait_type" : "Meow",
        "value" : "Minting Meow Burnable Soulbound Token"
      }, {
        "trait_type" : "Meowing",
        "value" : "Meow buring all"
      }   ],
    "description" : "This is a BURNABLE soulbound token mint",
    "image" : "https://arweave.net/IMAGE_DATA_TX_ID",
    "name" : "Soul Burn"
}

For our image we have to add it on the JSON file. On the URL https://arweave.net/IMAGE_DATA_TX_ID where it says IMAGE_DATA_TX_ID add the ID for the image which you copied from ArDrive.

Screenshot_20220816_170816.png

Now we have to upload the JSON file on ArDrive also. Go ahead and upload it on ArDrive. You need to get the DATA_TX_ID of the JSON file also. Now put the whole URL together by putting the JSON_DATA_TX_ID after https:// arweave.net/ and it will look something like this https:/ /arweave.net/JSON_DATA_TX_ID . We will need this Metadata URL to mint our NFT.

Minting the Burnable Soulbound NFT

image.png

Let’s go back to remix and expand “Deployed Contracts”. You will find safeMint over there. After you expand that you will have option to put your wallet address and the URL. For the URL paste the Metadata URL from earlier and click transact then confirm the transaction.

Now we will head over to Opensea Testnet to view our Burnable SoulBound NFT.

Screenshot_20220809_013052.png

To check if our NFT is truly SoulBound, let’s try to transfer the NFT to another address.

Screenshot_20220809_013235.png

Whenever we try to transfer we will be facing an error as all of our transfer function is blocked. Which confirms that our NFT is SoulBound and tied to this one address which owns the NFT.

Now let’s go ahead and burn the NFT through Remix IDE.

Screenshot_20220809_013956.png

To burn our NFT we will need to put the tokenId of the NFT and click to transact. In this way our NFT will be gone from our wallet and from the Opensea as well.

Now if you head over to OpeanSea and check your wallet, you won’t be able to find the NFT.

Congrats! We have finally deployed and burnt our Burnable Soulbound NFT on Polygon Mumbai Testnet.

Final Code Repository

You can find the code for this project on this repository.

github.com/meowyx/soulburn-contract

What’s Next

  • As you have learned about how to create Burnable SoulBound NFT, you can explore some more fun ideas. How about a SoulBound NFT that burns after certain period of time or how about a token gated platform that gives users temporary access through this Burnable Soulbound NFT.
  • Follow me on twitter at @me256ow and drop â€œđŸ±đŸš€â€ or find me on Voice-Chat-5 from Developer DAO discord.

image.png

Â