如何为 NFT 市场编写智能合约

2025-06-09

如何为 NFT 市场编写智能合约

介绍

本技术指南将为您提供使用 Solidity 和 Openzeppelin 构建完整 NFT 市场生态系统的全面指南。
我们的市场包含原生代币、可自定义版税的 NFT 创建以及安全的交易机制。

技术堆栈

  • 坚固性^0.8.27
  • OpenZeppelin 合约
  • 安全帽开发环境
  • TypeScript
  • Ethers.js

合同结构

该项目由三个主要合同组成:

  • 平台代币(NYWToken.sol)
  • NFT合约(NYWNFT.sol)
  • 市场合同(NYWMarketplace.sol)

1. 平台代币实现(NYWToken.sol)

我们的市场的基础始于实施平台的原生代币。

此 NYWToken 合约是一个简单的 ERC20 代币实现。
它继承自 OpenZeppelin ERC20 合约,并初始化代币供应量为 10 亿。

主要特点:

  • 代币供应量:10亿枚
  • 代币标准:符合 ERC20 标准
  • 小数:18 位小数,最大可除性
  • 初始分配:所有代币分配给合约部署者
//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合约实现

NYWNFT 合约负责创建和销毁 NYW NFT 代币,以及管理其使用费。
该合约继承自 OpenZeppelin ERC721 合约,后者提供了创建和管理 NFT 所需的功能。

主要功能:

  • createNYW():创建具有可定制版税的新 NFT
  • burnNYW():将 NFT 从流通中移除
  • getCreator():更新元数据 URI
  • getRoyalty():退货版税配置

以下是NYWNFT合约的详细实现:

//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. 市场合同实施(NYWMarketplace.sol)

NYWMarketplace 合约负责管理 NFT 的上架、下架、购买以及资金提取:

主要功能:

  • listNFT(uint256 tokenId_, uint256 price_): 将新的 NFT 上架到市场进行销售
  • delistNFT(uint256 tokenId_):从市场中移除 NFT
  • buyNFT(uint256 tokenId_):从市场购买 NFT
  • withdraw():从市场提取资金
    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

结论

构建一个安全高效的 NFT 市场需要精心设计多个智能合约的协同工作。本指南涵盖了以下几个基本组件:平台代币、NFT 合约和市场功能。

鏂囩珷鏉ユ簮锛�https://dev.to/marksantiago02/how-to-write-smart-contract-for-nft-marketplace-5mg
PREV
了解 NFT 市场的智能合约
NEXT
如何在实践中逐步编写动态权益智能合约