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.

nft Article's
30 articles in total
Favicon
Discover Top-Notch Decentralized Finance Exchange Development Services
Favicon
How to work with CAR files with NestJS
Favicon
Claim your NFT Legend boxes on Mint Blockchain
Favicon
Event | Mint Blockchain to Launch NFT Legends Season on January 2, 2025
Favicon
NFTScan 2024 Highlights: Empowering the NFT Landscape via Robust Data Infrastructure
Favicon
πŸ–ΌοΈ Blockchain NFT, ERC721 From Basics To Production πŸš€
Favicon
When to Use ERC-721 vs ERC-1155: Choosing the Right NFT Standard
Favicon
In-Depth Analysis of the Current Mint Pass: Ecosystem Value and Benefits
Favicon
Mint Blockchain: Connecting Global Consumers With NFTsπŸ€
Favicon
πŸ”¨ Lazy Minting vs Batch Minting: Which One is Right for Your NFT Project?
Favicon
Why ERC-721A is More Cost-Efficient Than ERC-721 for Batch Minting
Favicon
Send Tokens in Bulk with Low Fees and Fast Delivery: The Ultimate Airdrop Tool for 2024
Favicon
Kalp Studio NFT Creator: A Comprehensive Tutorial
Favicon
End-to-End Crypto Token Development Services for Next-Gen Blockchain Projects
Favicon
A Walkthrough of Solidity Custom Errors
Favicon
NFTCON 2024 Journey: Mint Blockchain’s Cutting-Edge Insights and Future Strategy
Favicon
Mint Blockchain Community Gathering: Vol. 2 coming soon!
Favicon
Mint 101: How does Mint Blockchain advance on-chain NFT development?
Favicon
How to Construct an NFT Marketplace: Exploring Varieties, Development Phases, and Future Prospects
Favicon
Beyond Art: The Expanding Horizons of NFT Marketplace Development Company
Favicon
Every Blockchain Developer Must Know About This Scam!
Favicon
One Month of MintSwap Mining: A Celebration of Growth and Community
Favicon
Smart Contract Safety: How to Verify Before You Interact
Favicon
Why and How to Get a Verified Blue Checkmark for Your NFT Collection on NFTScan Site
Favicon
Announcing the Launch of Mint Forest 3.0!
Favicon
NFTScan Site: Elevate Your NFT Project with Premium Blue Checkmark Verification and Powerful Project Management Capabilities
Favicon
Understanding smart contracts for NFT marketplace
Favicon
How to write smart contract for NFT marketplace
Favicon
MintSwap Mining Program Update: Optimized Rewards for Maximum Impact!
Favicon
MintSwap Powering Future of Mint Blockchain: DEX, NFT Marketplace, and More

Featured ones: