In this article, we will delve deeper into our Metaverse Gym Outfits Marketplace proof-of-concept (built on top of Ethereum blockchain), outlining the challenges we faced during the development and discussing the technologies and tools we used to overcome them.
Introduction
In our previous article, we reviewed the concepts of blockchain and smart contracts. We also showcased a Metaverse Gym Outfits Marketplace proof-of-concept (PoC) built on top of the Metaverse Gym PoC. The marketplace allows users to buy and sell outfits that can be used in the Metaverse Gym application. Built using the Ethereum blockchain, it also allows users to sell their outfits on open marketplaces such as OpenSea.
In this article, we will go deeper into our marketplace application, giving readers an inside look at the development process and helping them understand the thought process behind it. We will also provide more videos and details on the marketplace functionalities.
Storing Outfits Ownership and Information
To enable decentralization and interoperability, we decided to use blockchain to store the ownership information of our outfits. There are many blockchains available that enable us to develop this feature, including private chains like Linux Foundation’s Hyperledger Fabric and open chains like Ethereum. As the intention is to enable users to own, even sell or transfer outfits on other platforms, we decided to use Ethereum.
Ethereum is one of the most used blockchains for decentralized and open applications. Many Metaverse open projects such as Decentraland and Sandbox run on Ethereum.
The language used to develop smart contracts that enable decentralized applications to interact with the Ethereum blockchain is called Solidity. It has similarities with other programming languages like JavaScript, so if you have programming experience, it’s not that complicated to start developing simple contracts.
Blockchain Development Tools
There are many tools available to facilitate the development of applications using Ethereum. For this PoC, we used Truffle, one of the most popular Ethereum-based application development frameworks. Truffle provides a set of tools that enable you to compile, test, deploy, and interact with smart contracts. It also provides tools like Ganache that enables you to set up a local test blockchain where you can deploy and test your smart contracts before deploying them to the main network.
Another interesting tool for Ethereum development is Remix. Remix is an online IDE that enables you to develop smart contracts from your web browser without the need to set up an environment. Like Truffle, it also enables you to deploy the contracts to a local test network and provides an interface to call and test the contract's methods.
Token Standards
The first thing we had to do was decide which token standard to use. Several token standards are available, and their main purpose is to enable compatibility with other decentralized applications facilitating exchanges. Some token standards are:
- ERC-20: Also called the fungible token standard, is a token standard used for virtual coins, where each token of a specific type has the same value.
- ERC-721: Also called the non-fungible token (NFT) standard, is the token used, for example, for digital art. According to this standard, each token has a unique identifier that differs it from other tokens (each “contract address” + “token id” pair is unique in the network).
- ERC-1155: It is a more recent standard that provides a single contract interface enabling the creation of multiple token types. Using this standard, it is possible to create ERC-20 and ERC-721 on the same smart contract. It also enables the creation of semi-fungible tokens that can have multiple tokens for a specific identifier. ERC-1155 also brought efficiency improvements like bulk transfers.
On our PoC, we provide a defined quantity of tokens for each outfit. For this reason, we decided to use the ERC-1155 standard.
What Information Should Be Stored on the Blockchain?
Another key factor when developing applications using blockchain is deciding what information to store on the blockchain. This is important because storing information has a cost. When you request to store data on the blockchain, you must pay a fee (called ‘gas’ on Ethereum) and this is paid in Ether (Ethereum currency). There are other relevant concerns such as sensitive information, as all information on the blockchain is public and speed. Depending on the network traffic, transactions can take a long time to complete. Therefore, most token implementations do not store the actual token data (image or properties such as name and description) on the blockchain. What is usually stored is the ownership information and the token URI. URI stands for Universal Resource Identifier; it is a string that identifies a logical or physical resource. The most common type of URI is the Uniform Resource Locator (URL), which we use to access resources over the Internet. Thus, the token URI points to the location where the token metadata is stored.
Many tokens sold over the Internet use common storage services such as Amazon S3 to store token metadata. Although this provides low latency and great availability, the concern about this approach is that the owner of the storage resources can change the information. That is why, InterPlanetary File System (IPFS) is often used as an alternative for storing immutable metadata. Like the blockchain, IPFS is a distributed system, meaning anyone can set up an IPFS node. Although, IPFS uses peer-to-peer protocols for addressing, routing, and transferring content data over the network instead of replicating all data on every node. Information on the IPFS network is immutable because the IPFS protocol is content-based, unlike the address-based HTTPS and HTTP protocols. When you upload a file on the IPFS network, a hash is generated based on the content of that file and this hash becomes the identifier to search for the content on the IPFS network. That way, if you edit the file and upload it again, a new hash identifier will be generated that points to the new file. The previous hash code continues to point to the first uploaded file.
On our PoC, we decided to use IPFS to store our token Metadata.
Smart Contracts and IPFS Data Structures
We developed two smart contracts for our PoC: EncoraGymNFT and EncoraGymMarketPlace.
EncoraGymNFT is the contract for our outfit tokens. There are companies that provide open-source smart contracts built on token standards, such as OpenSea (Ethereum Open Market Place) and OpenZeppelin (crypto cybersecurity technology and services company). On our PoC, we used the ERC1155 smart contract from OpenZeppelin. As Solidity allows inheritance, we can use this to facilitate the development process. This contract holds information about our tokens:
- Tokens identifications
- Tokens currency for each account
- Tokens URIs
- Approved operators (details below)
The operator is an important concept, especially when dealing with marketplaces. An operator is an account or smart contract that can transfer tokens on behalf of the owner. When you list tokens for sale on a marketplace, you must concede the marketplace’s smart contract permission to transfer your tokens, otherwise it will not be able to transfer the token to the buyer when they make the purchase.
The other contract, EncoraGymMarketPlace, controls operations for our marketplace. This contract has methods for listing, buying, and viewing tokens for sale. It contains information about the items for sale:
- Token contract address
- Seller account address
- Requested value
- Token identification
As we mentioned earlier, we do not store any token information on our smart contracts, only the identification, ownership, and URI of the token. This way, an example of our data structure and token metadata (stored on the IPFS network) would be:
The token metadata provides information about the token, such as name, description, URL where the image is stored, and attributes. We use the token metadata structure from OpenSea. This also allows our tokens to be displayed correctly on the OpenSea platform and other open marketplaces based on Ethereum. The “Body Type” and “Model Identifier” attributes are the information we use in our Unity application to identify the corresponding outfit that this token represents.
How to Interact with Our Smart Contracts?
To interact with the blockchain and our smart contracts, we built a simple web application to be used as a marketplace. The code was built using popular tools such as Next.js (a React-based framework for building server-rendered web applications), Tailwind (a utility-first CSS framework that provides many pre-designed CSS classes), and Axios (JavaScript library for making HTTP requests).
Our marketplace application provides the following functionality:
- Create (Mint) NFT: This enables the owner of the marketplace, the account that deployed the contract, to create new NFTs. The access control for this functionality is implemented in the smart contract, which verifies if the requester is the contract owner before creating the token.
- List NFT: This allows token owners to list their tokens for sale on the Market Place.
- Buy NFT: Allows users to buy tokens that were listed by other users or the marketplace owner.
To connect our web application to the blockchain, we used an Ethereum wallet provider: MetaMask.
- MetaMask is a web browser extension that enables users to create and manage Ethereum accounts
- All accounts and their corresponding private keys are stored locally and guarded by a passphrase provided during the setup process
- When interacting with decentralized applications (dApps) in the web browser, MetaMask can detect the interactions and provide a user-friendly interface for users to review and confirm transactions
- From a developer’s perspective, MetaMask also provides an interface to interact with the blockchain using the web3.js library (JavaScript library for interacting with the Ethereum blockchain)
- MetaMask is preset with a connection to both the Ethereum mainnet and testnet. It can also be configured to connect to other networks, such as a local test network
It is possible to utilize web3.js to interact directly with an Ethereum node, but it should be noted that operating a full Ethereum node requires substantial computing resources, including high processing power, storage capacity, and bandwidth. That’s why companies like Infura and Alchemy offer Node-as-a-Service, which is in summary an API endpoint that can be used to interact directly with an Ethereum node they host. Infura is a provider used by MetaMask.
How to Interact with the IPFS Network?
As mentioned earlier, we chose to use the IPFS network to store our token metadata. For our PoC, we established our IPFS node and interacted directly with it. Although, it is worth noting that companies like Infura also offer services for hosting IPFS nodes, which can serve as a viable alternative if you wish to avoid the responsibility of setting up and maintaining an IPFS node.
To interact with our node, we used the IPFS Http Client library.
Gym Marketplace Demonstration
Wrapping up all the components, this is how the architecture of our web application looks like:
Now let’s explore the functionalities of the marketplace in detail.
Creating an Outfit Token (Marketplace Owner)
There are a few things we want to highlight in this video. First is the concept of minting a token. Minting a token is the same as creating a token on the smart contract, which means the token is then registered on the blockchain. In our marketplace, we inherit a smart contract called ownable. This contract simplifies the access permission to methods that can only be called by the owner of the smart contract, in other words, the Ethereum account that deployed the smart contract on the blockchain. For example, the “marketplace owner” account registered with MetaMask is the owner of the marketplace’s smart contract. Note that when we try to mint a token using another account (“User 1”), we get an error.
Another point to note is the MetaMask pop-up when we click on Create Outfit Button. MetaMask detects the transaction and requests the user to proceed with the transaction. Note that MetaMask also provides gas estimates and other information about the transaction. Gas is the amount of Ether that the requester pays to perform the transaction. Only transactions that update or insert information need gas. If you only want to query information, then it is not necessary to provide gas. That’s why when we clicked on the "My Outfits" tab to view our recently created tokens, there was no need to sign the transaction.
It is also interesting to note that when switching between accounts in MetaMask and refreshing the page, the page will already show information related to the new account. That happens because the web page can fetch the selected account from MetaMask.
Purchasing an Outfit Token
In the following video, we list the outfit tokens for sale using the “marketplace owner” account, and purchase 2 of them using a different account (“User 1”). After that we will list 1 of the purchased tokens for sale as “User 1”.
Notice that something different happened when we tried to list the outfit as a regular user instead of the marketplace owner. MetaMask requested the user to sign a smart contract consent to perform token transactions on his behalf. That was not required for the marketplace owner because we granted this permission at the time we deployed the contract, calling the corresponding method inside the contract's constructor. It is also interesting to note that MetaMask understands this transaction (as we are using a token standard) and warns the user about it. In addition to approving the permission, a second signature from the user was required. This signature corresponds to the record of the sale listing in the smart contract. To avoid additional gas costs, many marketplaces record sales listing information off the blockchain. To simplify our scenario, we kept the listing information on the blockchain.
Integrating Unity with the Ethereum Blockchain
Now that our marketplace is in place, we need a way for our Unity application to retrieve information about the user’s outfits from the Ethereum blockchain. We also need a way to store users’ information so we can link the logged user to its corresponding outfits.
For that, we created a serverless login system using AWS DynamoDB, API Gateway, and Lambda. DynamoDB is a NoSQL database that is part of the free tier on AWS, meaning you can store a certain amount of information for free. To integrate Unity with DynamoDB, we used API Gateway to expose the CRUD endpoints to Unity and AWS Lambda to process the requests and interact with the database.
In Unity, we created a simple account creation interface, where users can input their login information and more importantly their Ethereum Account. Unity uses this information to search for the user’s outfits on the Ethereum blockchain.
Now that our user’s information is stored, we must find a way for Unity to fetch information from the blockchain. For that, we are going to use Nethereum. Like web3.js, Nethereum is also a library for interacting with the blockchain, but in this case, using C#. To reach a blockchain node with Nethereum, we use Infura as the node provider.
Finally, we created an Avatar selection interface that fetches the user’s outfit data from the blockchain and enables the selection of the outfits that the user currently owns.
This is how our Unity architecture looks like in the end:
Conclusion
In this article, we observed that although blockchain is a technology that is beginning to be used at a higher scale, there are now several tools to facilitate its development. Using these tools, we were able to quickly set up a simple outfit token marketplace integrated with our Metaverse Gym PoC.
Acknowledgment
This piece was written by Guilherme Carrenho, an Innovation Expert at Encora’s Innovation Team. Thanks to Álison Ramos da Silva, Flavia de Melo Negrão, Hugo Martins Gonçalves, João Augusto Caleffi, and João Pedro São Gregorio Silva for their reviews and insights.
References
- The web application code was inspired by a marketplace example provided by the Truffle community.
- https://ethereum.org/en/developers/docs/standards/tokens/
- https://www.techtarget.com/whatis/definition/URI-Uniform-Resource-Identifier
- The outfits used on the PoC were obtained from Readyplayer.me.
- The sounds on videos were obtained from Mixkit.com
About Encora
Fast-growing tech companies partner with Encora to outsource product development and drive growth. Contact us to learn more about our software engineering capabilities.