You will learn to generate a NFT collection of land and lots, and we will develop the contracts to display them and show them for sale on OpenSea.
In a Blockchain project, a fundamental point is the development of smart contracts regarding business logic. In this case, we are going to talk about the development of smart contracts for NTFs (non-fungible tokens) and their deployment on a particular blockchain.
What is an NFT? An NFT is a non-fungible token. Non-fungible means that it cannot be subdivided or replaced by another.
There are also fungible tokens, these can be replaced by another equal as long as the value they represent is the same. In the case of NFTs, this does not happen: we are interested in one in particular and there is no other token that can replace it and have the same meaning for us.
Let’s suppose the following scenario: we want to launch for sale a collection of NFTs that represent some asset of our interest, particularly lots or land on some platform that we are developing. Clearly, we will go through the process of developing a FrontEnd that leaves us satisfied, some BackEnd microservices necessary to provide certain information, but we must also define and deploy smart contracts that represent our business logic.
That´s why we will try to elucidate how to generate a collection of NFTs to sell to the user.
First of all, we will define the types of non-fungible tokens that we are going to launch. In this case, we will deploy an NFT that represents the land to be sold and another NFT that is a chest or «lootbox» that, when opened, allows us to access new land.
We must consider that:
To develop smart contracts, not only for NFTs but for any other contract, it is necessary to know about certain patterns that serve as development standards based on the type of contract that you want to develop and launch on a blockchain.
The most widely used pattern in the development of fungible tokens is the ERC20, a structure designed to facilitate the implementation of various functionalities on the Ethereum blockchain and thus facilitate the creation work for developers.
However, in the case of non-fungible tokens (NFT), the patterns to be used are the ERC 721 and ERC 1155 standards, defined by an organization dedicated to the generation and propagation of these mechanisms called “OpenZeppelin”. A brief description of these is:
- ERC 721: Basically, each ERC 721 token is unique and represents a single asset. Furthermore, it allows developers to create a new ecosystem of tokens on the Ethereum blockchain. The pattern aims to create tradable tokens. An example of an ERC 721 contract is that of OpenZeppelin, which allows developers to track items in their games.
- ERC 1155: When someone uses an ERC 1155 standard to encode his contract, he is not considering his token as a 100% non-fungible asset, but rather works with a combination between the existence or not of that fungibility. In a single ERC 1155 contract, a developer can define a non-fungible token as a fungible. In addition, it uses mechanisms that allow GAS to be saved in each “mint” operation or minting of a new unit as well as a batch of units.
Most NFT contracts use the ERC 721 standard but there is a growing intention to use ERC 1155 for contracts. Since our project requires that each piece of land be an identifiable and unique unit of interest for the buyer, we will use the ERC 721 standard for this purpose, considering that using an ERC 1155 strategy would be wasting the additional features of the latter.
Finally, once the contracts are deployed, we want them to be available for purchase in the OpenSea marketplace. This leading exchange platform of non-fungible tokens will allow us to observe their characteristics and even acquire them through a crypto assets exchange.
OpenSea has a repository where a developer can access a model project of both ERC 721 and ERC 1155. We will use these facilities to speed up the development process but without losing sight of the details of its implementation.
Let’s start with the development!
First we will clone the OpenSea repository in our preferred directory. To do this we will use the Git version control tool and execute:
git clone https://github.com/ProjectOpenSea/opensea-creatures.git
Next step is to get all the necessary packages from the repository. To do this, we run yarn. If you don’t have it installed, run:
npm install -g yarn
Then:
yarn
Once the repository is downloaded and the packages are available, we look at its structure. The repository has the following files and directories:
- contracts: directory that contains the smart contracts of the project. This is where we will work on the business logic of the project and try to reflect it in ERC 721 contracts.
- migrations: Contains scripts for a Truffle project’s own migrations. Its execution is equivalent to deploying one or more contracts in the chosen blockchain.
- test: the code that is generated in this folder will be executed as a test of the contracts that we make.
- scripts: directory containing other scripts of interest to the project.
- .env: project environment file where we can define global environment variables to be consulted by the project.
If we consult the «contracts» directory, we see that OpenSea proposes the example of creature development for the ERC 721 standard and creatures with more developed characteristics for the ERC 1155 format. Due to the nature of our project, we will take the first ones as a reference and start to analyze its composition.
This is the coding of the «Land.sol» contract that represents the existence of an NFT called «Land» which reflects a piece of land or lot. We note that it inherits the characteristics of an ERC 721 “Tradable” contract. This standard created by OpenSea assumes that our non-fungible token has the characteristics of an asset that can be exchanged with another user of the network as a result of a negotiation. However, we will later observe that the monetary value that an NFT possesses is not configured in the contract but is managed in an «Off Chain» way (outside the Blockchain) by OpenSea and its platform. Therefore, we should not worry about defining any amount at this point.
The contract defines parameters in its constructor that have to do with its name, initials and an address required by OpenSea to display the contract called “proxyRegistryAddress”.
Another fundamental characteristic, not only of this contract but of any NFT, is the existence of a tokenURI. This element allows us to access the characteristics of the NFT and to consult it generally, in the form of a JSON. When consulting this JSON, we will observe all the attributes of that asset and it is the information that the OpenSea platform uses to show the characteristics of the deployed NFT.
For example, in the case of our NFT Land, we could reference the lot’s own characteristics using the tokenURI, such as its ID, soil characteristics, an associated image, among others.
It is not the subject of this article to develop a BackEnd that can be accessed to query this information, but for our current purpose, we use the Interplanetary File System (IPFS) to store the corresponding JSON and be able to target it from code.
Another NFT of interest for this project is a chest that allows the buyer, at a given moment, to open it and mint new land or lots. This contract is called “LandLootBox.sol” and has the following characteristics:
As we can see, it is an ERC 721 Tradable contract just like «Land», but it has certain characteristics: a number of lands that the chest contains, a method to «unpack» the chest and release new Land units and the need to destroy the chest. unit chest once it is opened by the owner. It then has a tokenURI just like any other NFT and query methods.
Once we define the NFT Land and LandLootBox, their general attributes and their tokenURIs, we turn our attention to the development of a “Factory” contract. A contract of this type is used to execute operations to generate units of the NFT from certain predefined options.
For example, we may want a user to access a predefined number of lots in a single purchase or access a chest that they can then “unpack” to access their NFTs. To do this, it is necessary to develop a “Factory” contract that is in charge of dealing with these options. The «LandFactory.sol» contract allows us to manage three options for generating a new NFT:
- The buyer wants a single piece of land or lot.
- The buyer wishes to access four lots.
- The buyer wants to access a chest and by opening it in the future, access three new lots.
The Factory contract not only allows you to «mint» each of these three options but, in the case of our project, it manages the tokenURIs associated with each option in a particular way. Certain methods and structures remain from the original OpenSea Factory contract that allow the platform to manage its operations.
At this point, we have developed all the necessary contracts to manage this sale of NFTs on OpenSea. It should be noted that there are other base contracts in the repository, but they are not addressed in this article since they are inherited from the OpenSea base project and have not been modified.
The next step is to run the project migrations and deploy our contracts to a testnet like Rinkeby. This network is one of several Ethereum test blockchains where a developer can publish their contracts before releasing them to the mainnet. You must make sure you have funds on the Rinkeby testnet, using a «Faucet» or fund generator, like the one found here is possible to solve this problem.
Within the project, we generate an environment variable file called “.env” and add certain parameters to be able to deploy our contracts:
- INFURA_KEY / ALCHEMY_KEY: This parameter represents our Infura or Alchemy key. To obtain it, we create an account on one of these two platforms, create a new project and copy the «kye» of the project to place it in the .env file. If we want to use Alchemy, change the variable name to ALCHEMY_KEY.
- MNEMONIC: Represents the security phrase of our Metamask wallet. To know this phrase, we must have created a wallet in Metamask and access the security phrase in its configuration.
- OWNER_ADDRESS: Address of our Metamask wallet with which we will deploy the contracts.
- NFT_CONTRACT_ADDRESS and FACTORY_CONTRACT_ADDRESS: They represent the addresses of the contracts after we have deployed them. Once we execute the migrations, we must complete these fields with the addresses obtained in the deploy.
- DEPLOY_LANDS_SALE: Its value is 0 because, in this way, the OpenSea project interprets that we are in the presence of simple ERC 721 contracts, and we do not want to add additional features.
- NETWORK: Defines the network in which we deploy the contracts.
Once these parameters are defined, we execute:
yarn truffle deploy — network rinkeby
We note that at the end of this process, all contracts were deployed to the Rinkeby network and corresponding addresses.
Now it’s time to check out our items for sale at OpenSea, who automatically senses the deployment of a new ERC 721 contract and displays it on their platform. To do this, we access the OpenSea test platform (since we deploy our contracts in Rinkeby) and accessing with the same wallet that we use for the deploy we observe:
Now it’s time to check out our items for sale at OpenSea, which automatically senses the deployment of a new ERC 721 contract and displays it on their platform. To do this, we access the OpenSea test platform (since we deploy our contracts in Rinkeby) and accessing with the same wallet that we use for the deploy we observe:
The three options that our Factory contract offers (single unit, four units and a LootBox sale) are now accessible from OpenSea.
We only have to access each of them and stipulate a sale value for each option. Do you remember that we talked about the real monetary value of each option not being something to be defined in the contracts but something “Off Chain” in OpenSea? Well, this is the time to do it. By accessing the «Sell» option of the item, we can define its value and now it can be purchased by other users of the platform. We can also observe the characteristics of each article thanks to the JSON to which the tokenURI corresponding to each asset points and that we define in the contracts.
We have created an NFT project from scratch and are ready to sell it through OpenSea!
▶ The technological ecosystem grows when we share. 💻Visit the public repository of this project.
Written by: Joaquin Perea (Blockchain Developer)