NFT交易市场开发(一)

实现的基本功能

  • (一)
    • 发行一个符合ERC20标准的测试Token,要求如下:
      • 总量::1亿
      • 精度:18
      • 名称:Fake USDT in CBI
      • 简称:cUSDT
  • (二)
    • 发行一个符合ERC721标准的测试Token,要求如下:
      • 名称:NFTMarketplace
      • 简称:NFTM
      • tokenid自增
      • 用户在网页上传图片提交之后自动发行给用户
  • (三)
    • 开发一个NFT交易市场,功能如下:
      • 用户在创建NFT时可以指定价格(以cUSDT计价)
      • NFT所有者可以修改上架的NFFT价格
      • NFT信息上传到IPFS
      • NFT所有者可以下架市场里自己的NFT
      • 用户可以在NFT市场以一定的价格购买NFT

实现的详细步骤

初始化hardhat工程
  • 前提是要安装好node.js。
  • 在自己新建的项目目录下打开终端
  • 使用npm install --save-dev hardhat命令安装hardhat
  • 输入npx hardhat init命令进行初始化
    在这里插入图片描述
  • 然后就搭建好了我们的一个hardhat框架
    在这里插入图片描述

ERC20

  • 然后输入code .命令在vscode打开该文件夹,在contracts文件夹下新建一个erc20-usdt.sol的合约文件,该文件夹下的初始合约文件可以删除,然后打开https://wizard.openzeppelin.com/#erc721网址复制合约代码
    在这里插入图片描述

  • 然后在vscode按照开发要求修改代码,修改后代码如下
    在这里插入图片描述

  • 在终端输入npm install @openzeppelin/contracts命令安装第三方的库

  • 在remix里面部署合约测试,关于本地文件连接remix教程前面文章详细讲过
    在这里插入图片描述

ERC721

  • 还是从之前的网址复制代码
    在这里插入图片描述
  • 新建erc721-nft.sol合约文件,将代码复制到该文件,然后编译测试一下

NFT交易市场

  • 新建一个nft-market.sol文件
  • 根据要求写合约代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";contract Market {//将erc20初始化为一个IERC20类型的实例,但具体的地址尚未赋值,后续的构造函数会使用传入的参数来设置erc20,从而与实际的ERC20代币合约进行交互IERC20 public erc20;IERC721 public erc721;bytes4 internal constant MAGIC_ON_ERC721_RECEIVED = 0x150b7a02;//包含代币售卖地址,代币Id,代币价格struct Order {address seller;uint256 tokenId;uint256 price;}mapping(uint256 => Order) public orderOfId;   //根据tokenId查询OrderOrder[] public orders;   //定义一个Order类型的数组存放所有的Ordermapping (uint256 => uint256) public idToOrderIndex;   //根据tokenId查询在数组中的索引event Deal(address seller, address buyer, uint256 tokenId, uint256 price);  //交易信息event NewOrder(address seller, uint256 tokenId, uint256 price);  //新的卖家信息event PriceChanged(address seller, uint256 tokenId, uint256 previousPrice, uint256 price);  //价格修改信息event OrderCancelled(address seller, uint256 tokenId);    //卖家退出交易市场信息//获取ERC20和ERC721的合约地址,这俩合约地址在部署合约时,在详细信息里面可以找到,合约地址不能时零地址constructor(address _erc20, address _erc721) {require(_erc20 != address(0), "zero address");require(_erc721 != address(0), "zero address");//将传入的地址_erc20转换为IERC20类型的实例,并将其赋值给变量erc20erc20 = IERC20(_erc20);erc721 = IERC721(_erc721);}//购买函数function buy(uint256 _tokenId) external {//获取该tokenId的卖家地址address seller = orderOfId[_tokenId].seller;//获取该tokenI的售卖价格uint256 price = orderOfId[_tokenId].price;//买方地址即当前调用合约的地址address buyer = msg.sender;//调用ERC20里面的授权转账函数进行转账require(erc20.transferFrom(buyer, seller, price), "transfer not successful");//调用了ERC721代币合约的safeTransferFrom函数,将指定的ERC721代币(由_tokenId标识)从当前合约地址(address(this))安全地转移到买家账户(buyer)。erc721.safeTransferFrom(address(this), buyer, _tokenId);emit Deal(seller, buyer, _tokenId, price);  //释放交易信息}//下架函数function cancelOrder(uint256 _tokenId) external {//获取卖家地址address seller = orderOfId[_tokenId].seller;//查看当前地址是不是卖家,因为商品只能由卖家自己下架require(msg.sender == seller, "not seller");erc721.safeTransferFrom(address(this),seller, _tokenId);emit OrderCancelled(seller, _tokenId);}//改价函数function changePrice(uint256 _tokenId, uint256 _price) external {address seller = orderOfId[_tokenId].seller;require(msg.sender == seller, "not seller");uint256 previousPrice = orderOfId[_tokenId].price;orderOfId[_tokenId].price = _price;//注意,不仅要修改Order的价格,orders数组里面存储的该地址的代币价格也需要修改//memory修改不会存储在链上,用于存储临时数据,storage修改会存储在链上,用于永久保存 Order storage order = orders[idToOrderIndex[_tokenId]];order.price = _price;emit PriceChanged(seller, _tokenId, previousPrice, _price);}//上架函数//用于处理ERC721代币的接收事件,当其它合约或用户向该合约发送ERC721代币时,会触发该函数,可以在该函数中编写逻辑来处理接收到的代币function onERC721Received(address operator,   //执行操作的地址address from,    //发送代币的地址uint256 tokenId,   //接收到的代币的唯一标识符bytes calldata data  //附加数据,可以是任意字节数组) external returns (bytes4) {//调用格式转换函数得到价格uint256 price= toUint256(data, 0);require(price > 0, "price must be greater than 0");//上架orders.push(Order(from, tokenId, price));orderOfId[tokenId] = Order(from, tokenId, price);idToOrderIndex[tokenId] = orders.length - 1;emit NewOrder(from, tokenId, price);//返回该值,这样发送方的合约就可以指导接收方是否已经正确处理了代币转移return MAGIC_ON_ERC721_RECEIVED;}//下架函数function removeOrder(uint256 _tokenId) internal {//先从数组中把他删除掉uint256 index = idToOrderIndex[_tokenId];uint256 lastIndex = orders.length - 1;if(index != lastIndex){Order storage lastOrder = orders[lastIndex];orders[index] = lastOrder;idToOrderIndex[lastOrder.tokenId] = index;}orders.pop();//从mapping里面删除delete  orderOfId[_tokenId];delete idToOrderIndex[_tokenId];}//格式转换函数function toUint256(bytes memory _bytes, uint256 _start) public pure returns (uint256) {require(_start + 32 >= _start,"Market: toUint256_overflow");require(_bytes.length >= _start + 32,"Market: toUint256_outOfBounds");uint256 tempUint;assembly {tempUint := mload(add(add(_bytes, 0x20), _start))}return tempUint;}//获取数组订单长度function getOrderLength() external view returns (uint256) {return orders.length;}//获取所有上架的NFTfunction getAllNFTs() external view returns (Order[] memory) {return orders;}//获取用户自己上架的NFTfunction getMyNFTs() external view returns (Order[] memory) {Order[] memory myOrders = new Order[](orders.length);uint256 count = 0;for (uint256 i = 0; i< orders.length; i++) {if (orders[i].seller == msg.sender) {myOrders[count] = orders[i];count ++;}}return myOrders;}
}

编译测试

  • 先编译部署ERC20,这个直接编译部署就行
  • 然后编译部署ERC721
    在这里插入图片描述
  • 编译部署NFT合约
    在这里插入图片描述
  • 在ERC721部署的合约里给自己mint几个NFT
    在这里插入图片描述
    在这里插入图片描述
  • 查看是否mint成功,我们可以看到地址是我们刚刚mint的地址,成功!
  • 上架!NFT价格参数格式在https://stackoverflow.com/questions/63252057/how-to-use-bytestouint-function-in-solidity-the-one-with-assembly这个里面找

    在这里插入图片描述
  • 在nft合约里验证是否上架
  • 再去ERC721里面上架代币,一样的,修改下tokenId就可以,因为在ERC721里面代币是唯一的,所以每个代币的tokenId都不同
    在这里插入图片描述
  • 获取所有上架的NFT信息
    在这里插入图片描述
  • 用户获取自己上架了几个NFT,在nft合约里面查看
    在这里插入图片描述
  • 初步已经实现了,后续还有,课程可以去哔哩哔哩上搜梁培利,很好的老师,也是我的老师。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/734159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——算法的空间复杂度

【本节内容】 1.空间复杂度 2.常见空间复杂度 1.空间复杂度 空间复杂度也是一个数学表达式&#xff0c;是对一个算法在运行过程中临时占用额外存储空间大小的量度。 空间复杂度不是程序占用了多少bytes的空间&#xff0c;因为这个也没太大意义&#xff0c;所以空间复杂度算…

random标准模块

一、概述 在 Python 中&#xff0c;random 是一个内置模块&#xff0c;用于生成随机数。它提供了各种用于生成随机数的函数&#xff0c;包括伪随机数生成器、随机序列操作等。 1、需要导包 不会自动导入&#xff0c;需要显示的将random模块导入 import random2、源码分析&…

课时59:流程控制_if条件控制_语法解读

2.2.1 语法解读 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 简介 条件结构能够根据某个特定的条件&#xff0c;结合内置的测试表达式功能&#xff0c;结合测试的结果状态值对于条件进行判断&#xff0c;然后选择执行合适的任务…

【Greenhills】MULTIIDE集成第三方的编辑器进行源文件编辑工作

【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 在使用GHS进行工作的时候&#xff0c;可以集成第三方的编辑器进行源文件编辑工作 2、 问题场景 用于解决在GHS中进行项目开发时&#xff0c;对于GHS的编辑器使用不习惯&#xff0c;想要切换到其他第三方的编辑…

为什么在镀膜时要测薄膜折射率?

在芯片制造中&#xff0c;镀膜工序&#xff08;PVD,CVD&#xff09;是必不可少的关键环节&#xff0c;薄膜的质量直接影响了芯片的性能。对这些薄膜的精细控制又离不开对其折射率的深入理解和精确测量。今天将对芯片制造中薄膜折射率的概念、测量方法&#xff0c;以及它在整个制…

Arcgis小技巧【19】——更改字段顺序

一、问题分析 一般情况下&#xff0c;一个合格且严谨的要素或表数据&#xff0c;它的字段顺序都是固定的。 比如三调数据&#xff0c;正常的字段数据如下&#xff08;截取部分字段&#xff09;&#xff1a; 数据经过处理&#xff0c;如增删字段&#xff0c;可能会出现字段顺序…

SAM模型

SAM与过去分割对比 根据以下Demo,我们可以发现&#xff0c;通过在图像中指定要分割的内容提示&#xff0c;SAM可以实现各种分割任务&#xff0c;且无需额外的训练、做到零样本泛化&#xff0c;即SAM学会了辨别物体、具备图像理解力、对不熟悉的图像和物体能进行零样本概括&…

论文阅读《FENET: FOCUSING ENHANCED NETWORK FOR LANE DETECTION》

ABSTRACT 受人类驾驶专注力的启发&#xff0c;这项研究开创性地利用聚焦采样&#xff08;Focusing Sampling&#xff09;、部分视野评估&#xff08;Partial Field of View Evaluation&#xff09;、增强型 FPN 架构和定向 IoU 损失&#xff08;Directional IoU Loss&#xff…

STM32单片机示例:ETH_LAN8742_DHCP_NonOS_Poll_H743

文章目录 目的基础说明关键配置关键代码示例链接总结 目的 以太网是比较常用到的功能&#xff0c;STM32系列单片机使用CubeMX配置使用以太网功能比非常方便。不过对于H7系列来说需要使能 DCache 才能启用LwIP&#xff0c;启用Cache后又会带来一些需要特别注意的事情。这篇文章…

AI智能应用百科立即落地实操课

该课程旨在教授学员如何将AI智能应用于实际场景。通过深入的案例研究和实操练习&#xff0c;学员将学会应用机器学习、自然语言处理等技术&#xff0c;快速解决现实问题。课程强调实际操作&#xff0c;帮助学员快速运用AI技术解决工作中的挑战。 课程大小&#xff1a;3.3G 课…

10 | MySQL为什么有时候会选错索引?

前面我们介绍过索引&#xff0c;你已经知道了在 MySQL 中一张表其实是可以支持多个索引的。但是&#xff0c;你写 SQL 语句的时候&#xff0c;并没有主动指定使用哪个索引。也就是说&#xff0c;使用哪个索引是由 MySQL 来确定的。 不知道你有没有碰到过这种情况&#xff0c;一…

【Selenium】selenium介绍及工作原理

一、Selenium介绍 用于Web应用程序测试的工具&#xff0c;Selenium是开源并且免费的&#xff0c;覆盖IE、Chrome、FireFox、Safari等主流浏览器&#xff0c;通过在不同浏览器中运行自动化测试。支持Java、Python、Net、Perl等编程语言进行自动化测试脚本编写。 官网地址&…

学会Web UI框架--Bootstrap,快速搭建出漂亮的前端界面

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属的专栏&#xff1a;前端泛海 景天的主页&#xff1a;景天科技苑 文章目录 Bootstrap1.Bootstrap介绍2.简单使用3.布局容器4.Bootstrap实现轮播…

二分与前缀和

789. 数的范围 - AcWing题库 import java.util.*;public class Main{static int N 100010;static int[] a new int[N];public static void main(String[] args){Scanner sc new Scanner(System.in);int n sc.nextInt();int m sc.nextInt();for(int i 0; i < n; i ){…

《互联网的世界》第五讲-信任和安全(第一趴:物理世界的非对称加密装置)

信任和安全的话题过于庞大&#xff0c;涉及很多数学知识&#xff0c;直接涉及 “正事” 反而不利于理解问题的本质&#xff0c;因此需要先讲一个前置作为 part 1。 part 1 主要描述物理世界的信任和安全&#xff0c;千万不要觉得数字世界是脱离物理世界的另一天堂&#xff0c;…

【C++庖丁解牛】实现string容器的增删查改 | string容器的基本接口使用

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 前言&#x1f4d6;pu…

MACBOOK PRO M2 MAX 安装Stable Diffusion及文生图实例

以前偶尔会使用Midjourney生成一些图片&#xff0c;现在使用的头像就是当时花钱在Midjourney上生成的。前段时间从某鱼上拍了一台性价比还不错的macbook&#xff0c;想着不如自己部署Stable Diffusion&#xff08;以下简称SD&#xff09;尝试一下。 网上有很多教程&#xff0c…

Apache POI 解析和处理Excel

摘要&#xff1a;由于开发需要批量导入Excel中的数据&#xff0c;使用了Apache POI库&#xff0c;记录下使用过程 1. 背景 Java 中操作 Excel 文件的库常用的有Apache POI 和阿里巴巴的 EasyExcel 。Apache POI 是一个功能比较全面的 Java 库&#xff0c;适合处理复杂的 Offi…

qt-C++笔记之使用Cmake来组织和构建QWidget工程项目

qt-C笔记之使用Cmake来组织和构建QWidget工程项目 —— 杭州 2024-03-10 code review! 文章目录 qt-C笔记之使用Cmake来组织和构建QWidget工程项目1.运行2.文件结构3.CMakeLists.txt4.main.cpp5.widget.h6.widget.cpp7.widget.ui 1.运行 2.文件结构 3.CMakeLists.txt 代码 c…

中国联通云联网在多元行业应用中的核心地位与价值体现

在全球化浪潮与数字化转型的时代背景下&#xff0c;中国联通积极响应市场需求&#xff0c;推出以云联网为核心的全球化智能组网解决方案&#xff0c;突破地理限制&#xff0c;为各行业提供高效、安全、灵活的网络服务。该方案不仅涵盖传统的通信连接&#xff0c;更是深入到能源…