以太坊ERC721智能合约NFT交易市场实战开发

文章介绍了如何使用开源Solidity合集仓库来创建一个基于以太坊的NFT交易所,涵盖了上架、下架和购买NFT的功能,以及智能合约的实现和项目部署过程。
摘要由CSDN通过智能技术生成

介绍

一个开源solidity合集仓库
https://github.com/qdwds/smart-contracts
以太坊ERC721全栈开发开NFT合集从入门到项目实战项目
https://learnblockchain.cn/course/31
https://edu.51cto.com/course/33566.html

一起学习吧

我们一起沟通、交流、学习吧!

NFT交易平台

因为NFT是可以被交易买卖的数字资产,而NFT交易所可以收集大量的NFT来撮合买家买家,所以交易所是生态中不可缺少的一个部分。

接下来我们实现自己的交易所,我们的交易所会实现以下几个功能

  • 上架NFT
  • 下架NFT
  • 购买NFT
  • 获取单个NFT信息
  • 获取所有NFT信息
  • 提取收益

代码实现

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

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "./ComposeNFT.sol";
contract Markets  {
    using Counters for Counters.Counter;
    Counters.Counter private indexCounter;
    struct Market {
        address seller;
        uint256 tokenId;
        uint256 index; //  订单
        uint256 price;
        string uri;
        bool active;
    }

    Market[] public markets;
    mapping (uint => Market) public tokenIdToMarket;
    ComposeNFT  compose;
    mapping (address => uint) public tokenIdToPrice;
    constructor(ComposeNFT _compose){
        compose = _compose;
    }
    // 上架状态
    function hasActive(uint256 _tokenId) public view returns(bool){
        return tokenIdToMarket[_tokenId].active;
    }
    
    
    // 上架 
    function shelve(uint256 _tokenId, uint256 _price) public {
        require(compose.ownerOf(_tokenId) == msg.sender, "The is owner?");
        require(!hasActive(_tokenId),"Already on shelves");
        require(
            compose.getApproved(_tokenId) == address(this) || 
            compose.isApprovedForAll(msg.sender, address(this)),
            "No approve"
        );

        uint256 index = indexCounter.current();
        indexCounter.increment();
        string memory uri = compose.tokenURI(_tokenId);
        console.log(uri);
        Market memory newMarket = Market(
            msg.sender,
            _tokenId,
            index,
            _price,
            uri,
            true
        );

        markets.push(newMarket);
        tokenIdToMarket[_tokenId] = newMarket;
    }
    // 下架
    function unShelve(uint256 _tokenId) public {
        require(compose.ownerOf(_tokenId) == msg.sender, "The is owner?");
        require(hasActive(_tokenId),"Removed from shelves");
        // require(compose.getApproved(_tokenId) == address(this), "No approve");

        _unShelve(_tokenId);
    }

    function allMarkets() public view  returns(Market[] memory allMarket){
        if(markets.length == 0){
            return new Market[](0);
        }

        uint256 count = 0;
        for (uint i = 0; i < markets.length; i ++){
            Market memory market = markets[i];
            if(market.active){
                count ++;
            }
        }

        allMarket = new Market[](count);
        uint j = 0;
        for (uint i = 0; i < markets.length; i++){
            if(markets[i].active){
                allMarket[j] = markets[i];
                j++;
            }
            if(j >= count){
                return allMarket;
            }
        }
    }

    function _unShelve(uint256 _tokenId) internal {
        uint index = tokenIdToMarket[_tokenId].index;
        delete markets[index];
        delete tokenIdToMarket[_tokenId];
         
    }
    // 全部市场信息
    // 购买
    function buy(uint256 _tokenId) public payable {
        Market memory market = tokenIdToMarket[_tokenId];
        require(msg.value >= market.price," Price error");
        require(msg.sender != market.seller, "Address error");
        require(market.active, "No market");


        _unShelve(market.tokenId);

        tokenIdToPrice[market.seller] = msg.value;

        compose.safeTransferFrom(market.seller, msg.sender, _tokenId);
    }
    // 取款
    function withdraw() public{
        uint balance = tokenIdToPrice[msg.sender];
        require(balance > 0, " no Price");
        tokenIdToPrice[msg.sender] = 0;
        (bool sent,) = msg.sender.call{value:balance}("");
        require(sent,"Withdraw error");
    }
}

项目部署

import { ethers } from "hardhat";
import { address } from "../abi/ComposeNFT.json";
import { createAbi } from "../utils/createAbi";
const main  = async () => {
    const Markets = await ethers.getContractFactory("Markets");
    const markets = await Markets.deploy(address);
    await markets.deployed();
    console.log(markets.address);
    createAbi("Markets",markets.address);
} 

main()
    .catch(err =>{
        console.log(err);
        process.exit(1);
    })

项目调试

在项目部署完之后,任意NFT都可以在市场中上架。但是上架的时候需要先授权给当前交易平台,否者交易平台是无法操作用户上架的NFT的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值