一个常规的NFT市场合约,可以用于数藏平台的搭建

一个常规NFT市场合约代码,支持上架、下架NFT艺术作品,设定价格,购买NFT,配置NFT白名单功能。

一个常规NFT市场合约代码,支持上架、下架NFT艺术作品,设定价格,购买NFT,配置NFT白名单功能。

pragma solidity >=0.8.0;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

library SafeTransferLib {
    // ERC721 & ERC1155 support
    function safeTransferFrom (address contractAddress, address from, address to, uint256 tokenID, uint256 amount) internal returns (bool) {
        try IERC721(contractAddress).safeTransferFrom(from, to, tokenID) {
            return true;
        } catch (bytes memory) {
            try IERC1155(contractAddress).safeTransferFrom(from, to, tokenID, amount, "0x0") {
                return true;
            } catch (bytes memory) {
                return false;
            }
        }
    }
}

contract LandNFTMarket is ERC721Holder, ERC1155Holder {
    using SafeMath for uint;
    using SafeERC20 for IERC20;
    using Address for address;

    struct OnSaleNFT {
        uint idx;
        address nftAddress;
        uint256 tokenId;
        address seller;
        uint256 price;
        uint256 amount;
    }
    address public creator;
    string public logoUrl; // 市场的logo图
    string public bannerUrl; // 市场的banner图
    address public settleToken; // 用于结算的token
    mapping(address => bool) public whitelist; // 只有白名单内的NFT地址可以上架
    bool public enableExternal = false;
    mapping(address => mapping(uint256 => uint256)) public nftList; //  nftAddress => tokenId => idx
    mapping(uint256 => OnSaleNFT) public nftBriefList; // idx => tokenData
    uint256 public nftCount; // idx 从1开始,只加不减
    address private feeTo; // 费用接收地址

    event OnSale(address indexed market, address indexed nftAddress, uint, uint);
    event OffSale(address indexed market, address indexed nftAddress, uint);
    event Buy(address indexed market, address indexed nftAddress, uint, uint);

    constructor() {
        creator = msg.sender;
    }

    function setSettleToken(address _settleToken) external returns(bool){
        require(msg.sender == creator, 'Error: 9101');
        settleToken = _settleToken;
        return true;
    }

    // 设置费用接收地址
    function setFeeTo(address _feeTo) external virtual returns(bool){
        require(msg.sender == creator, 'Error: 0011');
        feeTo = _feeTo;
        return true;
    }

    // 设置市场的banner
    function setLogo(string memory _logoUrl) external returns (bool) {
        require(msg.sender == creator, 'Error: 9003');
        logoUrl = _logoUrl;
        return true;
    }

    // 设置市场的logo
    function setBanner(string memory _bannerUrl) external returns (bool) {
        require(msg.sender == creator, 'Error: 9004');
        bannerUrl = _bannerUrl;
        return true;
    }

    // 允许普通用户上架作品
    function enable(bool _flag) external returns (bool) {
        require(msg.sender == creator, 'Error: 9005');
        enableExternal = _flag;

        return true;
    }

    // 上架作品
    function onSale(address _nftAddress, uint256 _tokenId, uint256 _price, uint256 _amount) external returns (bool) {
        require(whitelist[_nftAddress] == true, 'Error: 9100');
        if(msg.sender != creator){
            require(enableExternal, 'Error: 9006');
        }
        require(nftList[_nftAddress][_tokenId] == 0, 'Error: 9007');
        require(_price > 0, 'Error: 9008');
        // to market
        if(SafeTransferLib.safeTransferFrom(_nftAddress, msg.sender, address(this), _tokenId, _amount)){
            // add to onsales
            nftCount++;
            nftList[_nftAddress][_tokenId] = nftCount;
            OnSaleNFT memory nftBrief = OnSaleNFT(nftCount, _nftAddress, _tokenId, msg.sender, _price, _amount);
            nftBriefList[nftCount] = nftBrief;

            emit OnSale(address(this), _nftAddress, _tokenId, _price);

            return true;
        }

        return false;
    }

    function _verify(address _nftAddress, uint256 _tokenId) internal view returns(address seller,uint256 price,uint256 amount){
        ( seller, price, amount) = _getBrief(_nftAddress, _tokenId);
        require(nftList[_nftAddress][_tokenId] > 0, 'Error: 9010');
        require(price > 0, 'Error: 9011');
        require(seller != address(0), 'Error: 9012');
    }

    // 下架作品
    function offSale(uint idx) external returns (bool) {
        OnSaleNFT memory nftBrief = nftBriefList[idx];
        require(msg.sender == nftBrief.seller || msg.sender == creator, 'Error: 9014');
        require(nftBrief.nftAddress != address(0), 'Error: 9015');
        require(nftBrief.tokenId > 0, 'Error: 9016');
        require(nftBrief.amount > 0, 'Error: 9017');
        // to seller
        if(SafeTransferLib.safeTransferFrom(nftBrief.nftAddress, address(this), nftBrief.seller, nftBrief.tokenId, nftBrief.amount)){
            delete nftBriefList[idx];
            delete nftList[nftBrief.nftAddress][nftBrief.tokenId];

            emit OffSale(address(this), nftBrief.nftAddress, nftBrief.tokenId);

            return true;
        }
        return false;
    }

    function _getBrief(address _nftAddress, uint256 _tokenId) private view returns(address seller, uint256 price, uint256 amount){
        uint256 idx = nftList[_nftAddress][_tokenId];
        OnSaleNFT memory nftBrief = nftBriefList[idx];
        (seller, price, amount) = (nftBrief.seller, nftBrief.price, nftBrief.amount);
    }

    function getBrief(address _nftAddress, uint256 _tokenId) external view returns(address seller, uint256 price, uint256 amount){
        return _getBrief(_nftAddress, _tokenId);
    }

    // 购买作品
    function buy(uint idx, uint256 _amount) external returns (bool) {
        OnSaleNFT memory nftBrief = nftBriefList[idx];
        // check amount
        require(nftBrief.amount >= _amount, 'Error: 9015');
        require(nftBrief.price > 0, 'Error: 9016');
        require(nftBrief.seller != address(0), 'Error: 9012');
        require(nftBrief.nftAddress != address(0), 'Error: 9015');
        require(nftBrief.tokenId > 0, 'Error: 9016');
        uint256 totalPrice = uint(nftBrief.price).mul(_amount);
        // to seller
        IERC20(settleToken).safeTransferFrom(msg.sender, nftBrief.seller, totalPrice);
        // to buyer
        if(SafeTransferLib.safeTransferFrom(nftBrief.nftAddress, address(this), msg.sender, nftBrief.tokenId, 1)){
            // remove from onsales
            // NFT
            delete nftBriefList[idx];
            delete nftList[nftBrief.nftAddress][nftBrief.tokenId];

            emit Buy(address(this), nftBrief.nftAddress, nftBrief.tokenId, totalPrice);

            return true;
        }
        return false;
    }

    // 分页获取在售作品,每页10个
    function getNftList(uint startIdx) external view returns (OnSaleNFT[] memory) {
        uint256 counter = 0;
        for(uint256 i = 1; i <= nftCount; i++){
            if(nftBriefList[i].tokenId > 0){
                counter++;
            }
        }
        OnSaleNFT[] memory _lists = new OnSaleNFT[](counter);
        if (counter != 0) {
            uint256 itemCounter = 0;
            for(uint256 i = startIdx + 1; i <= nftCount; i++){
                if(nftBriefList[i].tokenId > 0){
                    _lists[itemCounter] = nftBriefList[i];
                    itemCounter++;
                    if(itemCounter >= 10){
                        break;
                    }
                }
            }
        }
        return _lists;
    }

    // 获取指定用户出售中的作品
    function getNftListBySeller(address seller) external view returns (OnSaleNFT[] memory) {
        uint256 counter = 0;
        for(uint256 i = 1; i <= nftCount; i++){
            if(nftBriefList[i].seller == seller){
                counter++;
            }
        }
        OnSaleNFT[] memory _lists = new OnSaleNFT[](counter);
        if (counter != 0) {
            uint256 itemCounter = 0;
            for(uint256 i = 1; i <= nftCount; i++){
                if(nftBriefList[i].seller == seller){
                    _lists[itemCounter] = nftBriefList[i];
                    itemCounter++;
                }
            }
        }
        return _lists;
    }

    function setNFTWhitelist(address _address, bool _status) external returns(bool){
        require(msg.sender == creator, 'Error: 1009');
        whitelist[_address] = _status;
        return true;
    }
}
点赞 1
收藏 5
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
快乐的程序猿
快乐的程序猿
软件开发v colorful_cloud_sea