Build an NFT marketplace on ICE
Non-fungible token (NFT) is a type of digital asset that is unique and cannot be replaced. NFTs are typically used to represent physical or virtual objects having distinct identities, such as a specific card in a game or an automobile. They are also used to represent ownership of digital assets such as domain names, software licenses, and virtual land in games.
NFT marketplaces are places where users can buy and sell NFTs for a variety of purposes such as trading, gambling, and so on. NFT marketplaces are platforms where artists from all over the world list their NFT assets (for eg: digital arts) for trading with other users. Cryptocurrencies are mostly used in trading these NFT assets, while some NFTs can also be purchaed with Fiat currencies. Some examples of NFT marketplaces are OpenSea, Rarible, Craft, etc.
What we will build
- Write and deploy an NFT smart contract, and a MarketPlace smart contract on Arctic Testnet using Remix IDE and Metamask.
- Interact with NFT using a user interface for the NFT marketplace.
Prerequisites
- Metamask configured with Arctic testnet
- Account with ICZ testnet tokens from ICE Faucet
NFT Smart Contract
Creating NFT smart contract
We’ll directly utilize the OpenZeppelin Contracts Wizard to create the initial base template for our NFT smart contract. Select ERC721 tab and set the features as shown in the image below.
Adding Royalty to NFTs
EIP-2981 standard provides a standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal support for royalty payments across different NFT marketplaces and ecosystem participants.
Openzeppelin provides an implementation of ERC721Royalty which can be directly imported into the project.
Since the royalty receiver should always be the creator and not the current owner, we have to implement this logic ourselves. For that, we can create a mapping creators, that stores the original minter.
Additionally, also add a mint function such that anyone would be able to create the NFT and add creatorOf function to see who created the NFT in the first place.
Furthermore, we have implemented the following functions:
- setTokenRoyalty: This function allows the NFT creator to set the royalty percentage.
- setDefaultRoyalty: This function allows the owner of the contract to set the default percentage.
Note: feeNumerator attribute is set in terms of per ten thousand.
Example: 5% -> 500 feeNumerator.
The full code for the MyToken NFT smart contract can be found here.
Now let us head over to Remix IDE and deploy the MyToken contract.
- In an existing workspace, create a file on the contracts folder named MyToken.sol, and paste the contract code into it.
- Compile the contract by pressing ctrl + s or cmd + s.
Deploying NFT smart contract
- Navigate to the Deploy & Run Transaction tab from Left Side Menu.
- From the Environment drop-down menu, Select Environment as “Injected Web3”; make sure that it’s connected to the “Custom 552” network. If it is connected to some other network, open your Metamask and change the network to “Arctic” by following the instruction here.
- Select MyToken — contracts/MyToken.sol from the Contract dropdown menu and hit Deploy
- Confirm the transaction on your Metamask wallet.
- After the contract is deployed, a success message will be logged to the console and the deployed Token contract instance will be fetched from the Arctic to the Deployed Contracts section at the bottom of the Deploy and Run Transactions window.
Interacting with NFT smart contract on Remix
You can directly interact with the created smart contract from the Remix IDE by invoking the methods shown below. ff
Marketplace Smart Contract
Creating Marketplace smart contract
Marketplace provides a common gateway for buyers looking to buy NFTs, as well as owners/creators looking to sell their NFTs. Thus, any marketplace contract must implement two basic features:
- Listing NFT for Sale:
The owner of NFT should be able to list his/her NFTs for sale. For this, we have created alistForSalemethod. To allow the marketplace to list tokens from different contracts, we set bothtokenAddressas well astokenID.Similarly, we also set theprice, and_urlthat stores additional information about the NFT outside the blockchain. - Buying NFT:
To buy NFT, one simply needs to provide the right price for the NFT. Once the contract receives the right price, the value is split between the royaltyReceiver and the current owner of the NFT and transferred accordingly.
Let’s look at the MarketPlace smart contract code.
Let’s head over to Remix IDE and deploy our MarketPlace contract.
- In the same workspace create another file in the contracts folder named MarketPlace.sol, and paste the above code into it.
- Compile the contract by pressing ctrl + s or cmd + s.
Deploying Marketplace Smart Contract
- Navigate to the Deploy & Run Transaction tab from Left Side Menu.
- From the Environment drop-down menu, Select Environment as “Injected Web3”; make sure that it’s connected to the “Custom 552” network. If it is connected to some other network, open your Metamask and change the network to “Arctic” by following the instruction here.
- Select MarketPlace — contracts/MarketPlace.sol from the Contract dropdown menu and hit Deploy
Interacting with Marketplace Smart Contract on Remix
Interacting is also similar to the process we described earlier. The following methods are available for the interaction.
Running the frontend
Directly via GitPod
Click here to directly run the frontend on GitPod.
Running Locally
a. Clone the repository
git clone https://github.com/prajwolrg/ice-workshop-nft-fullstack.gitb. Change directory and install dependencies
cd ice-workshop-nft-fullstack
npm installc. Start Server
npm run devSetting the right contract addresses
In the root directory of the project, inside config.js , set the NFTAddress and MarketPlaceAddress to the respective contract addresses you have obtained after deploying the contracts.
In the config.js file, add the contract addresses as shown below:
The Marketplace frontend will launch and will be accessible via any web browser at http://localhost:3000.
Note: Make sure you have configured your metamask with the Arctic testnet before building the UI since we have deployed our contract there. You can make the configuration following the instructions here.
Interacting with NFT smart contract using WebApp
Creating an NFT
Go to Create NFT section, and set the Asset Name, and Asset Description and Choose an image file to represent the NFT.
Additionally, you can select the checkbox to add royalty information to the asset.
If you have selected to add royalty, you must sign an additional transaction to set the royalty information.
Listing NFT
Once you have created the NFT, it should be visible under My NFTs. To list the NFT for sale, click on List and set your preferred price that you want your NFT to be listed for.
There are two transactions that you must sign with Metamask while listing the NFT for sale:
- Approve Marketplace to sell NFT on your behalf.
- Listing the NFT on marketplace for sale
Buying NFT
All the NFTs listed for sale are available on the Home page. Click on Buy to buy a particular NFT.
Once bought, you can check My NFTs section to view your NFTs or list them for sale.
IPFS
IPFS is a decentralized file system that is used to share and store files. To uniquely identify each file in a global namespace, IPFS uses content-addressing. It is critical for our NFTs to connect the NFT metadata to the location where the asset or artwork is housed.
On the frontend code, we have used ipfs-http-client to get CID (content identifier) i.e. the location where our NFT image is stored and we have used Crust Wiki as the IPFS storage provider. The location extracted, is then used as the url parameter that’s sent to the mint function on the MyToken.sol contract, and the listForSale function on the MarketPlace.sol contract. The snippet below, from the frontend code, shows how can we generate a url of the NFT image by using IPFS.
import { create } from 'ipfs-http-client';
import { ethers } from 'ethers';// 0. Construct web3 authed header// Now support: ethereum-series, polkadot-series, solana, elrond, flow, near, ...// Let's take ethereum as exampleconst pair = ethers.Wallet.createRandom();
const sig = await pair.signMessage(pair.address);
const authHeaderRaw = `eth-${pair.address}:${sig}`;
const authHeader = Buffer.from(authHeaderRaw).toString('base64');
const ipfsW3GW = 'https://crustipfs.xyz';// 1. Create IPFS instant
const ipfs = create({
url: `${ipfsW3GW}/api/v0`,
headers: {
authorization: `Basic ${authHeader}`
}
});// 2. Add file to ipfs
const { path } = await ipfs.add(Buffer(reader.result));
const url = `${ipfsW3GW}/ipfs/${path}`
NOTE: For more information about above snippet, please visit File Storing Demo by Crust Wiki.
Conclusion
In this article, we went through the concepts of NFT and NFT Marketplace. We wrote and deployed two smart contracts to the Arctic network: the ERC721 NFT Smart Contract and Marketplace Smart Contract. Then, using the Remix IDE we were able to interact with the smart contracts methods. We also deployed an existing open-source Marketplace UI to interact with the deployed contracts, where we could create, view, buy and sell NFTs.
