Tutorial: Building an ERC1155 SoulBound Token
What does SoulBound mean?
According to Vitalik’s writings here:
A soulbound item, once picked up, cannot be transferred or sold to another player.
In this article, he also mentions bringing this property to NFTs where once you acquire (mint or airdropped) this token, you can’t transfer it. This means you won’t be able to sell it in any marketplace.
One of the clear use cases of this property is in POAP. As Vitalik writes:
Perhaps the best example of a project trying to do this is POAP, the "proof of attendance protocol". POAP is a standard by which projects can send NFTs that represent the idea that the recipient personally participated in some event.
This is a pretty interesting concept to me so I wanted to implement it myself for one of my projects (more on that in future posts). Therefore I am also sharing a quick tutorial to write a very simple ERC-1155 contract with this property.
Prerequisites
Basic knowledge of smart contracts
Basic knowledge about Solidity and ERC-1155
Foundry installed - You can also use hardhat if you are more familiar with it, but this tutorial assumes you are using Foundry
Steps
Create a new project using
forge init soulbound
This will create a new project with a sample smart contract Counter and your project structure should look like this
You can either create a new contract under the
src
directory or work with the existing Counter.solWe will be using the OpenZepplin contracts library for implementing our token so we need to install that. Foundry uses git submodules for importing libraries. The below command will help you with this installation
forge install OpenZeppelin/openzeppelin-contracts
Once installed you are ready to write your smart contract. The next step is to import your dependencies into your contract. You can use the below command to import the ERC1155 library you just installed
import "openzeppelin-contracts/contracts/token/ERC1155/ERC1155.sol";
Since we are focused on soulbound tokens in this tutorial, we will just see how to make your contract behave like one. The rest of the code remains the same as what a normal ERC-1155 contract would look like. ERC-1155 has a method called _beforeTokenTransfer which is a Hook that will be called before any transfer of token is done. We will override this method so that it behaves like a soulbound token
function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) pure override internal { require(from == address(0) || to == address(0), "This a Soulbound token. It cannot be transferred. It can only be burned by the token owner."); }
Let me explain the most important piece of code
from == address(0) || to == address(0)
. The first condition says that if the token is minted (minted token originates from 0 address) and the second condition says if the token is burned (tokens get burned to 0 address). So only if the token is minted or burned, this method will execute the transfer otherwise it will fail in thisrequire
condition. One line of code and you can make it a soulbound token. Pretty impressive.You can now deploy your contract using forge create command and after you mint a token if you try to transfer that it won’t allow you to transfer. The only thing you can do with this token is to burn it.
If you want to look at the full example you can take a look here. I hope this was useful. Please subscribe to my newsletter if you want my writings directly in your inbox.
If you enjoyed reading this you may be interested in following me on Twitter and Medium.