NFT721中心化交易

  • 浪杭
  • 发布于 1天前
  • 阅读 103

设计逻辑实现一个简易版的NFT721代币,这个代币可以在opensea查看到,通过这个代币来实现一个交易NFT的合约。卖家:出售NFT的一方,可以挂单list、撤单revoke、修改价格update。买家:购买NFT的一方,可以购买purchase。订单:卖家发布的NFT链

<!--StartFragment-->

设计逻辑

  • 实现一个简易版的NFT721代币,这个代币可以在opensea查看到,通过这个代币来实现一个交易NFT的合约。

  • 卖家:出售NFT的一方,可以挂单list、撤单revoke、修改价格update

  • 买家:购买NFT的一方,可以购买purchase

  • 订单:卖家发布的NFT链上订单,一个系列的同一tokenId最多存在一个订单,其中包含挂单价格price和持有人owner信息。当一个订单交易完成或被撤单后,其中信息清零。

<!--EndFragment-->

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract WQQNFT is ERC721URIStorage {
    using Counters for Counters.Counter ;
    Counters.Counter private counter;
    // 构造函数
    constructor ()ERC721("wuqingqing","wuqingqing"){

    }

    // 可以是批量的操作元数据"ipfs://QmQkm9LsS*******BbA4E4kLrY8EGMKQTaBK/"为元数据的CID值
    function _baseURI() internal pure override returns (string memory) {
        return "ipfs://QmQkm9LsS*******BbA4E4kLrY8EGMKQTaBK/";
    }

    // 铸造函数
    function mint(address to, string memory tokenURI)external {
        uint tokenId = counter.current();
        _setTokenURI(tokenId, tokenURI);
        _mint(to, tokenId);
        counter.increment();
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

contract NFTSwap{
    // 挂单
    event List(
        address indexed seller,
        address indexed nftAddr,
        uint256 indexed tokenId,
        uint256 price
    );

    // 购买
    event Purchase(
        address indexed buyer,
        address indexed nftAddr,
        uint256 indexed tokenId,
        uint256 price
    );
  // 更新价格
    event Update(
        address indexed seller,
        address indexed nftAddr,
        uint256 indexed tokenId,
        uint256 price
    );
 // 撤单
    event Revoke(
        address indexed seller,
        address indexed nftAddr,
        uint256 indexed tokenId
    );

    struct Order{
        // 持有人信息
        address owner;
        // 挂单价格
        uint256 price;
    }

    // nft order映射
    mapping (address=>mapping (uint256=>Order)) public nftList;
    receive() external payable { }
    fallback() external payable { }

    // 卖家上架nft 合约地址为_nftAddr,tokenId为_tokenId,价格_price为以太坊(单位是wei)
    function list(address _nftAddress, uint256 _tokenId, uint256 _price)public {
        IERC721 _nft = IERC721(_nftAddress);
        require(_nft.getApproved(_tokenId)==address(this), "Need Approved");// 合约得到授权
        require(_price>0);// 价格大于0

        Order storage _order =nftList[_nftAddress][_tokenId]; // 设置NFT持有人和价格
        _order.owner = msg.sender;
        _order.price = _price;

        // 将NFT转账到合约
        _nft.safeTransferFrom(msg.sender, address(this), _tokenId);

        emit List(msg.sender, _nftAddress, _tokenId, _price);
    }

    // 买家购买NFT,合约为_nftAddress,tokenId为_tokenId,调用函数时要附带ETH
    function purchase(address _nftAddress, uint256 _tokenId) public  payable {
         Order storage _order =nftList[_nftAddress][_tokenId]; // 取得Order
         require(_order.price>0 ,"Invaild price");// 价格必须大于0
         require(msg.value>=_order.price,"Invaild price"); // 购买价格大于上架价格
         // 声明IERC721接口合约
         IERC721 _nft = IERC721(_nftAddress);
         require(_nft.ownerOf(_tokenId)==address(this), "Invalid Order"); // tokenId的主人是当前合约
         // 将合约拥有的NFT转给买家
         _nft.safeTransferFrom(address(this), msg.sender, _tokenId);
         // 将EHT转给Order.owner
         payable (_order.owner).transfer(_order.price);
         //多余的ETH退回给买家
         if (msg.value>_order.price){
            payable (msg.sender).transfer(msg.value-_order.price);
         }
         emit Purchase(msg.sender, _nftAddress, _tokenId, _order.price);
         delete nftList[_nftAddress][_tokenId]; // 删除上架的order
    }
    // 撤单卖家取消订单
    function revoke(address _nftAddress, uint256 _tokenId)public {
        Order storage _order =nftList[_nftAddress][_tokenId]; // 取得Order
        require(_order.owner==msg.sender, "Not Owner");// 必须是持有人发起
        // 声明IERC721接口合约
        IERC721 _nft = IERC721(_nftAddress);
        require(_nft.ownerOf(_tokenId)==address(this), "Invalid Order"); // tokenId的主人是当前合约
        // 将NFT 转移给卖家
        _nft.safeTransferFrom(address(this), msg.sender, _tokenId);
        delete nftList[_nftAddress][_tokenId];
        emit Revoke(msg.sender, _nftAddress, _tokenId);

     }
     // 调整价格卖家调整挂单价格
     function update(
        address _nftAddress,
        uint256 _tokenId,
        uint256 _newPrice
     )public {
        require(_newPrice>0, "Invaild Price");
        Order storage _order =nftList[_nftAddress][_tokenId]; // 取得Order
        require(_order.owner==msg.sender, "Not Owner");// 必须是持有人发起
         // 声明IERC721接口合约
        IERC721 _nft = IERC721(_nftAddress);
        require(_nft.ownerOf(_tokenId)==address(this), "Invalid Order"); // tokenId的主人是当前合约
        _order.price = _newPrice;
        emit Update(msg.sender, _nftAddress, _tokenId, _newPrice);
     }
     // 实现{IERC721Receiver}的onERC721Received,能够接收ERC721代币
    function onERC721Received(
        address operator,
        address from,
        uint tokenId,
        bytes calldata data
    ) external returns (bytes4){
        return IERC721Receiver.onERC721Received.selector;
    }
}
  • 原创
  • 学分: 3
  • 分类: NFT
  • 标签: NFT 
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
浪杭
浪杭
0x8EE7...F029
江湖只有他的大名,没有他的介绍。