Logo

dev-resources.site

for different kinds of informations.

How to write smart contract for NFT marketplace

Published at
11/23/2024
Categories
nft
smartcontract
marketplace
erc721
Author
marksantiago02
Author
14 person written this
marksantiago02
open
How to write smart contract for NFT marketplace

Introduction

This technical guide will give you a comprehensive guide to building a complete NFT marketplace ecosystem using Solidity and Openzeppelin.
Our marketplace features a native token, NFT creation with customizable royalties, and secure trading mechanisms.

Technical Stack

  • Solidity ^0.8.27
  • OpenZeppelin Contracts
  • Hardhat Development Environment
  • TypeScript
  • Ethers.js

Contract Structure

The project is structured into three main contracts:

  • Platform Token (NYWToken.sol)
  • NFT Contract (NYWNFT.sol)
  • Marketplace Contract (NYWMarketplace.sol)

1. Platform Token Implementation (NYWToken.sol)

The foundation of our marketplace starts with implementing the platform's native token.

This NYWToken contract is a simple ERC20 token implementation.
It inherits from the OpenZeppelin ERC20 contract and initializes the token with a supply of 1 billion tokens.

Key Features:

  • Token Supply: 1 billion tokens
  • Token Standard: ERC20 compliance
  • Decimals: 18 decimal places for maximum divisibility
  • Initial Distribution: All tokens minted to contract deployer
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract NYWToken is ERC20 {
    uint256 initialSupply = 10 ** 9;

    constructor() ERC20("NYWToken", "NYW") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}
Enter fullscreen mode Exit fullscreen mode

2. NFT Contract Implementation

The NYWNFT contract handles creating and burning NYW NFT token, and royalty management.
This contract inherits from the OpenZeppelin ERC721 contract, which provides the necessary functionality for creating and managing NFTs.

Key Functions:

  • createNYW(): Creates new NFTs with customizable royalties
  • burnNYW(): Removes NFTs from circulation
  • getCreator(): Updates metadata URI
  • getRoyalty(): Returns royalty configuration

Here is a detailed implementation of the NYWNFT contract:

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract NYWNFT is ERC721URIStorage, Ownable {
    uint256 private _tokenId;

    mapping(uint256 => address) public creators;
    mapping(uint256 => uint256) public royalties;

    event NYWTokenCreated(
        address indexed creator,
        uint256 tokenId,
        uint256 royalty,
        string tokenURI
    );
    event NYWTokenBurned(address indexed burner, uint256 tokenId);

    constructor() ERC721("NYW NFT", "NYW") Ownable(msg.sender) {}

    function createNYW(
        string memory tokenURI,
        uint256 royalty
    ) external returns (uint256) {
        require(
            royalty >= 0 && royalty <= 30,
            "Royalty must be between 0 and 30"
        );
        _tokenId += 1;

        creators[_tokenId] = msg.sender;
        royalties[_tokenId] = royalty;
        _safeMint(msg.sender, _tokenId);
        _setTokenURI(_tokenId, tokenURI);
        _setApprovalForAll(msg.sender, address(this), true);

        emit NYWTokenCreated(msg.sender, _tokenId, royalty, tokenURI);

        return _tokenId;
    }

    function burnNYW(uint256 tokenId) external {
        require(
            msg.sender == ownerOf(tokenId),
            "Only the owner can burn the token"
        );

        _burn(tokenId);
        delete creators[tokenId];
        delete royalties[tokenId];

        emit NYWTokenBurned(msg.sender, tokenId);
    }

    function getCreator(uint256 tokenId) external view returns (address) {
        return creators[tokenId];
    }

    function getRoyalty(uint256 tokenId) external view returns (uint256) {
        return royalties[tokenId];
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721URIStorage)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Marketplace Contract Implementation (NYWMarketplace.sol)

The NYWMarketplace contract manages listings, delisting and buying NFTs and withdrawing funds:

Key Functions:

  • listNFT(uint256 tokenId_, uint256 price_): Lists new NFT to marketplace for sale
  • delistNFT(uint256 tokenId_): Removes NFT from marketplace
  • buyNFT(uint256 tokenId_): Purchases NFT from marketplace
  • withdraw(): Withdraws funds from marketplace
    function listNFT(uint256 tokenId_, uint256 price_) external {
        // Check if the NFT is already listed
        require(!isExisting[tokenId_], "NFT is already listed");
        // Check if the NFT is owned by the caller
        require(
            nftContract.ownerOf(tokenId_) == msg.sender,
            "You are not the owner of the NFT"
        );

        //Define new NFTMarketItem
        NFTMarketItem memory newNFTMarketItem = NFTMarketItem(
            tokenId_,
            price_,
            nywContract.getRoyalty(tokenId_),
            payable(msg.sender),
            nywContract.getCreator(tokenId_),
            true
        );

        isExisting[tokenId_] = true;
        listedNFTs.push(newNFTMarketItem);
        tokenIdToNFTMarketItemId[tokenId_] = totalListedNFTs;
        totalListedNFTs++;

        emit NYWNFTListed(
            tokenId_,
            price_,
            nywContract.getRoyalty(tokenId_),
            nywContract.getCreator(tokenId_),
            msg.sender
        );
    }

    function delistNFT(uint256 tokenId_) external {
        require(isExisting[tokenId_], "NFT is not listed");
        uint256 nftMarketItemId = tokenIdToNFTMarketItemId[tokenId_];
        require(
            listedNFTs[nftMarketItemId].seller == msg.sender,
            "Only the seller can delist the NFT"
        );

        deleteNFTfromArray(tokenId_);
        emit NYWNFTDelisted(tokenId_);
    }

    function deleteNFTfromArray(uint256 tokenId_) public {
        uint256 nftMarketItemId = tokenIdToNFTMarketItemId[tokenId_];
        uint256 lastIndex = listedNFTs.length - 1;
        listedNFTs[nftMarketItemId] = listedNFTs[lastIndex];
        tokenIdToNFTMarketItemId[
            listedNFTs[lastIndex].tokenId
        ] = nftMarketItemId;
        listedNFTs.pop();
        totalListedNFTs--;
        delete tokenIdToNFTMarketItemId[tokenId_];
        isExisting[tokenId_] = false;
    }

    function buyNFT(uint256 tokenId_) public payable {
        require(isExisting[tokenId_], "NFT is not listed");
        uint256 _nftMarketItemId = tokenIdToNFTMarketItemId[tokenId_];
        NFTMarketItem memory _nftMarketItem = listedNFTs[_nftMarketItemId];
        require(!_nftMarketItem.isSold, "NFT is already sold");
        require(msg.value == _nftMarketItem.price, "Incorrect payment amount");

        // Calculate royalty amount
        uint256 _royaltyAmount = (_nftMarketItem.price *
            _nftMarketItem.royalty) / deno;
        // Calculate platform fee
        uint256 _platformFeeAmount = (_nftMarketItem.price * platformFee) /
            deno;
        // Calculate seller amount
        uint256 _sellerAmount = _nftMarketItem.price -
            _royaltyAmount -
            _platformFeeAmount;
        // Transfer funds to the seller
        payable(_nftMarketItem.seller).transfer(_sellerAmount);
        // Transfer royalty amount to the creator
        payable(_nftMarketItem.creator).transfer(_royaltyAmount);
        // Transfer platform fee amount to the platform
        payable(owner()).transfer(_platformFeeAmount);
        //Transfer NFT to the buyer
        nftContract.safeTransferFrom(
            _nftMarketItem.seller,
            msg.sender,
            _nftMarketItem.tokenId
        );

        _nftMarketItem.isSold = true;
        deleteNFTfromArray(tokenId_);
        emit NYWNFTBought(
            _nftMarketItem.tokenId,
            msg.sender,
            _nftMarketItem.seller,
            _nftMarketItem.price
        );
    }

    function withdraw() external onlyOwner {
        uint256 balance = address(this).balance;
        require(balance > 0, "No funds to withdraw");
        payable(owner()).transfer(balance);
        emit NYWNFTWithdrawn(balance);
    }
Enter fullscreen mode Exit fullscreen mode

Conclusion

Building a secure and efficient NFT marketplace requires careful implementation of multiple smart contracts working together. This guide covered the essential components: platform token, NFT contract, and marketplace functionality.

marketplace Article's
30 articles in total
Favicon
Everything Developers Need to Know About WHOIS and Geolocation APIs
Favicon
Building an Open Source Seller Center in Public
Favicon
LaPrompt Marketplace: The #1 Resource of Verified GPT Prompts
Favicon
Best Programming Languages to Build an E-Commerce Website
Favicon
5 Essential Questions for Crafting a Marketplace Strategy in Consumer Tech
Favicon
How to Construct an NFT Marketplace: Exploring Varieties, Development Phases, and Future Prospects
Favicon
Online marketplace MVP - Building a two-sided marketplace MVP using Next.js and MongoDB - From idea to launch
Favicon
10 crazy ideas for a marketplace. Real examples
Favicon
Understanding smart contracts for NFT marketplace
Favicon
How to write smart contract for NFT marketplace
Favicon
Welcome to Marketplaces: The Next Evolution in E-Commerce
Favicon
How Are NFTs Shaping the Future of Gaming?
Favicon
Marketplaces: Where Competitors Become Commerce Allies
Favicon
How to build a marketplace MVP fast in Next.js
Favicon
What Makes eBay the Best Online Marketplace?
Favicon
Bazaars (BZR): The Path to $1,000—A Game-Changer for Crypto Holders
Favicon
Bazaars (BZR): The 100x Crypto Gem Poised to Explode
Favicon
Bazaars (BZR): The Next Big Thing in Crypto, Poised for Explosive Growth
Favicon
Bazaars (BZR): The Next Big Thing in Crypto, Set to Dominate the Market
Favicon
Bazaars (BZR): The Next Crypto Titan Poised for Explosive Growth
Favicon
Mercur - Medusa MultiVendor Marketplace Accelerator
Favicon
Vengo AI - Create and monetize your AI identity with one line of code
Favicon
e-commerce marketplace management services in delhi
Favicon
Why Should I Invest in Developing a Metaverse NFT Marketplace?
Favicon
Pros and Cons of Using OpenSea
Favicon
Как создать свой маркетплейс: варианты разработки
Favicon
Blockchain and Smart Contracts integraton, 3D experience
Favicon
AnyHelpNow Services GmbH & Co. KG
Favicon
🗞 Rapyd Developer Newsletter: March 2024
Favicon
Guide to Marketplace Payment Processing

Featured ones: