NFT 合约部署教程

news2024/11/13 13:03:30

本篇文章主要介绍如何将您的 NFT(ERC-721 Token) 通过智能合约部署到去中心化网络中

Init Project

 
//创建一款ocean的NFT
mkdir  nft-ocean

//进入目录
cd nft-ocean

//初始化项目,根据提示填写即可,packname和description填写即可
npm init

//添加hardhat依赖
npm install --save-dev hardhat


/*使用脚手架搭建项目,我们选择Create a basic sample project
可以帮助我们创建1个demo工程并按照所需的依赖*/
npx hardhat

这是初始化完成后的代码结构

  • contracts目录用来存放我们的智能合约代码

  • scripts用来存放我们的脚本,比如合约部署就会依赖其中的脚本

  • test目录用来存放我们为智能合约编写的测试代码

  • hardhat.config.js是关于hardhat框架的一些配置,比如solidity版本等

  • package.json是npm的相关配置

编写合约代码

目前就可以开始写合约代码了,本文主要是介绍NFT的发行,我们简单来实现一份NFT智能合约代码。

//安装openzeppelin/contracts依赖,内置较多合约协议的实现以及工具代码
npm install @openzeppelin/contracts

我们在contracts目录下创建NFT_OCEAN.sol的文件。

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

contract NFT_OCEAN is ERC721, ERC721Enumerable, Ownable {
    string private _baseURIextended;
    //Set mint limit
    uint256 public constant MAX_SUPPLY = 5;
    //0.01eth per mint
    uint256 public constant PRICE_PER_TOKEN = 0.01 ether;

    constructor() ERC721("nft_ocean", "NFT_OCEAN") {
    }

    function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function setBaseURI(string memory baseURI_) external onlyOwner() {
        _baseURIextended = baseURI_;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseURIextended;
    }

    function mint(uint numberOfTokens) public payable {
        uint256 ts = totalSupply();
        require(ts + numberOfTokens <= MAX_SUPPLY, "Purchase would exceed max tokens");
        require(PRICE_PER_TOKEN * numberOfTokens <= msg.value, "Ether value sent is not correct");

        for (uint256 i = 0; i < numberOfTokens; i++) {
            _safeMint(msg.sender, ts + i);
        }
    }

    function withdraw() public onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }
}

该代码不具备上线标准,因为没有白名单。每个地址限制mint多少个等,仅供示意。建议发行NFT前需要好好设计合约

合约编译

//合约编译
npx hardhat compile

合约部署

修改scripts目录下自动生成的脚本改名为deploy.js并修改内部代码

const hre = require("hardhat");

async function main() {
  // Hardhat always runs the compile task when running scripts with its command
  // line interface.
  //
  // If this script is run directly using `node` you may want to call compile
  // manually to make sure everything is compiled
  // await hre.run('compile');

  // We get the contract to deploy
  const Nft_ocean = await hre.ethers.getContractFactory("NFT_OCEAN");
  const nft_ocean = await Nft_ocean.deploy();

  await nft_ocean.deployed();

  console.log("NFT_OCEAN deployed to:", nft_ocean.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  }); 

选择节点服务代理

有很多方法可以向以太坊区块链发出请求,但为了让事情变得简单,我们将使用 Alchemy 上的免费帐户,这是一个区块链开发人员平台和 API,允许我们与以太坊链,无需运行我们自己的节点。创建过程参考文档,分别创建一个Ethereum Mainnet 和 Ethereum Sepolia 的APP

测试网络环境搭建

我们首先需要在测试网络中部署,我们选择Sepolia作为我们的测试网络。

因为在代码执行过程中会用到公钥、私钥、API等数据,但这些数据又不能编码到代码中,因为如果我们使用git来管理项目,信息将会泄露。我们使用dotenv存放部署合约以及和合约交互需要用到的数据。

//添加dotenv依赖
npm install dotenv

//工程根目录下创建变量存储文件
touch .env

为.env增加内容

PRIVATE_KEY= 导出你metamask的私钥填在这里
API=Alchemy APP中的HTTPS
PUBLIC_KEY= metamask地址
NETWORK=sepolia
API_KEY=Alchemy的API KEY
  • metamask私钥导出:打开钱包-账号详情->导出私钥。

  • API、API_KEY:打开Alchemy 中 Ethereum Sepolia 的API KEY,复制HTTPS和API_KEY

修改hardhat.config.js


/**
* @type import('hardhat/config').HardhatUserConfig
*/

require("@nomicfoundation/hardhat-toolbox");
require("@nomiclabs/hardhat-ethers");
//require("@nomiclabs/hardhat-waffle");

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
require('dotenv').config();
const { API, PRIVATE_KEY } = process.env;

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.19",
  defaultNetwork: "sepolia",
  networks: {
    hardhat: {},
    sepolia: {
      url: API,
      accounts: [`0x${PRIVATE_KEY}`]
    }
  },
};

获取测试网络ETH 因为合约测试需要消耗ETH,我们需要获取一些测试用的ETH,我们打开https://sepoliafaucet.com/,填入我们的钱包地址即可获取。

此时我们将钱包切换到sepolia测试网络,可以看到钱包中已经有一些ETH了。

执行合约部署

首先安装 ETHERS.JS

npm install --save-dev @nomiclabs/hardhat-ethers ethers@^5.7.2

执行合约部署

npx hardhat --network sepolia run scripts/deploy.js
//执行完成后得到提示,代表合约部署完成
NFT_WEB3_EXPOLRER deployed to: {合约地址}

此时我们可以在https://sepolia.etherscan.io/搜索我们的合约地址找到我们的合约信息

为NFT设置资源

现在的NFT仅仅包含tokenID,我们需要为其设置资源, 在ERC721的实现中我们可以看到tokenURI方法的实现,各个交易市场就是调用该方法来读取NFT资源信息的

/**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

我们可以看到这里是将BaseURI和tokenID拼接来读取tokenURI的,所以我们也按照这种格式来准备资源。

准备资源

//创建资源文件
mkdir res
cd res
//存放图片
mkdir  nfts
//存放metadata信息
mkdir  metadata

由于本文是示例项目,没有找专门的设计师设计图片,我们网上找了5张图片。将5张图片放入img目录下,依次命名为1.jpeg ~ 5.jpeg

我们资源文件上传到ipfs中,这里和以太坊网络一样,由于我们不想运行本地ipfs节点,所以我们寻找节点服务提供商进行上传。我们使用https://dashboard.4everland.org/bucket/storage/将nfts文件夹上传

上传完成后的图片资源

选中图片文件夹进行snapshots,即可生成root cid,网关访问效果如下:

接下来我们准备metadata文件,在metadata目录下新建5个文件依次命名为0~4,我们看下0号文件信息

{
    "name": "nft-ocean",
    "attributes": [
        {
            "trait_type": "tokenID",
            "value": "0"
        }
    ],
    "description": "nft-ocean image",
    //填入上面刚刚上传完成的图片地址
    "image": "ipfs://bafybeief75v57gu3khb5ftjkgldyzyea4x3r6sesekcia6lk2pijgl5idm/01.jpeg"
}

我们将metadata文件夹上传并snapshot,获取文件夹CID后进行publish

设置BaseURI

我们需要将刚刚上传后的metadata文件地址设置给合约的baseURI,这样各个平台在使用tokenURI获取资源信息才可以获取到。

编写代码与合约交互设置BaseURI,在scripts目录下新建setBaseURI.js文件。

setBaseURI.js

require("dotenv").config()
const hre = require("hardhat");
const PRIVATE_KEY = process.env.PRIVATE_KEY
const NETWORK = process.env.NETWORK
const API_KEY = process.env.API_KEY


const provider = new hre.ethers.providers.AlchemyProvider("sepolia",API_KEY);
//编译完成合约会自动生成
const abi = require("../artifacts/contracts/NFT_OCEAN.sol/NFT_OCEAN.json").abi
const contractAddress = "填合约地址" 
const contract = new hre.ethers.Contract(contractAddress, abi, provider)
const wallet = new hre.ethers.Wallet(PRIVATE_KEY, provider)
const baseURI = "ipfs://{metadata文件的root cid}/" //填

async function main() {
  const contractWithSigner = contract.connect(wallet);
  //调用setBaseURI方法
  const tx = await contractWithSigner.setBaseURI(baseURI)
  console.log(tx.hash);
  await tx.wait();
  console.log("setBaseURL success");
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

执行setBaseURI脚本

npx hardhat --network sepolia run scripts/setBaseURI.js

Mint 测试

因为只有mint过的tokenID才会展示在交易市场中,所以我们需要编写代码进行mint测试(实际场景,该操作应该由前端页面调用完成)。

mint.js

require("dotenv").config()
const hre = require("hardhat");
const PRIVATE_KEY = process.env.PRIVATE_KEY
const NETWORK = process.env.NETWORK
const API_KEY = process.env.API_KEY


const provider = new hre.ethers.providers.AlchemyProvider("sepolia",API_KEY);
const abi = require("../artifacts/contracts/NFT_OCEAN.sol/NFT_OCEAN.json").abi
const contractAddress = "0x531D6B8fBe5FAC349D05642E17F5E998A4DfEd68"
const contract = new hre.ethers.Contract(contractAddress, abi, provider)
const wallet = new hre.ethers.Wallet(PRIVATE_KEY, provider)

async function main() {
    const contractWithSigner = contract.connect(wallet);
    //获取mint需要多少ETH
    const price = await contract.PRICE_PER_TOKEN();
    console.log("price is" + price);
    //调用mint方法,支付mint费用
    const tx = await contractWithSigner.mint(1, { value: price});
    console.log(tx.hash);
    await tx.wait();
    console.log("mint success");
}

main()
    .then(() => process.exit(0))
    .catch((error) => {
        console.error(error);
        process.exit(1);
    });

执行mint脚本

npx hardhat --network sepolia run scripts/mint.js

Mint 成功

查看NFT

此时我们去opensea 测试网 https://testnets.opensea.io/ 查看我们mint的NFT 即可。

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

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

相关文章

【JAVA】Object类与抽象类

作者主页&#xff1a;paper jie_的博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和…

批量剪辑神器:AI智剪技巧全攻略

在视频剪辑的工作流程中&#xff0c;效率和质量都是至关重要的。有时候&#xff0c;我们需要对大量的视频进行剪辑&#xff0c;这可能会耗费大量的时间和人力。然而&#xff0c;随着技术的发展&#xff0c;AI智能剪辑工具如固乔智剪软件的出现&#xff0c;大大提高了剪辑的效率…

架构师之如何定位问题

1. 什么是问题 很多人对问题的理解不一样&#xff0c;有人认为问题就是解决方案中的难点&#xff0c;有人认为问题是现实和目标的差距&#xff0c;这些解读我觉得都还不够精确&#xff0c;尝试从毛主席的矛盾论中得到比较合理的解释&#xff1a; 问题就是事物的矛盾。哪里有没…

Ubuntu22.04 安装 MongoDB 7.0

稍微查了一些文章发现普遍比较过时。有的是使用旧版本的Ubuntu&#xff0c;或者安装的旧版本的MongoDB。英语可以的朋友可以移步Install MongoDB Community Edition on Ubuntu — MongoDB Manual&#xff0c;按照官方安装文档操作。伸手党或者英语略差的朋友可以按照本文一步步…

计算机重点学科评级B-,山东省属重点高校考情分析

山东科技大学(B-) 考研难度&#xff08;☆☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1175字预计阅读&#xff1a;3分钟 2023考情概况 山东科技大学计…

stable diffusion webui升级bug问题解决思路(纯干货)

个人网站&#xff1a;https://tianfeng.space/ 文章目录 一、前言二、个人方案1.扼杀在萌芽中A.解压后点击启动器运行依赖&#xff0c;然后点击A启动器B.更新本体和扩展&#xff08;全部到最新版本&#xff09;C.把controlnet1.1放入stable diffusion 中D.插件转移E.模型转移F…

怎么选动捕设备?惯性动作捕捉还是光学动捕?

动捕设备在3D角色动画、影视制作中使用&#xff0c;通过动捕设备记录真人演员的动作&#xff0c;然后将其转换为数字模型的动作生成三维的计算机动画&#xff0c;使用动捕设备可以让动画角色更逼真地移动。 目前市面上主要分为光学动捕设备与惯性动作捕捉设备&#xff0c;这二…

基于SSM的学生课外知识学习网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

电水壶上要求亚马逊美国站SOR/2016-181和CSA22.1标准?

电水壶作为一种常见的小家电&#xff0c;受到了广大消费者的喜爱。然而&#xff0c;由于安全问题的日益重视&#xff0c;亚马逊加拿大站决定加强对电水壶产品的审核&#xff0c;以确保消费者的安全和权益。 近日&#xff0c;亚马逊平台发布公告&#xff0c;要求在加拿大站销售…

跨越时空,亲临其境:3D展示技术让你在家就能游览全球旅游景区

随着科技的不断发展&#xff0c;3D虚拟现实技术在文旅景区中的应用越来越广泛。相比传统的游览方式&#xff0c;3D展示技术具有以下优点&#xff1a; 一、真实感强 3D全景展示可以将文旅景区的真实场景以三维的方式呈现出来&#xff0c;让游客可以在虚拟的环境中感受到真实的场…

电子产品出口欧盟做什么认证?电子产品CE认证标准有哪些?

CE认证是产品出口到欧盟的通行证&#xff0c;没有CE认证标志的产品是不允许在欧盟市场上销售的&#xff0c;今天就给大家介绍常见的电子产品的CE认证标准有哪些&#xff1f; 电子产品CE认证标准有哪些&#xff1f; 常见的电子产品办理CE认证&#xff0c;做的认证指令是EMC指令…

方案丨TSINGSEE青犀视频AI智能算法助力智慧农业高质量建设

我国是农业大国&#xff0c;随着AI等新兴技术的飞速发展&#xff0c;大数据、互联网等技术业运用到了农业生产的各个环节&#xff0c;为提高土地利用率、减少热工成本&#xff0c;提高生产效率&#xff0c;智慧农业应运而生。 旭帆科技TSINGSEE青犀视频AI智慧农业解决方案&…

如何在SOLIDWORKS中更改单位-硕迪科技

SOLIDWORKS中的单位系统 SOLIDWORKS中的单位系统可以针对单个文件修改、一次修改多个文件以及在默认模板中进行修改。每个SOLIDWORKS文件都有一个单位系统&#xff0c;该单位系统由该文件的文档属性控制。默认情况下&#xff0c;SOLIDWORKS零件、装配体和工程图模板各自规定了…

外贸erp软件条码管理解决方案,应对外贸客户变化多样性

在国际贸易市场下&#xff0c;仓库对于市场和企业之间是商品的流量和储存是必不可少的。其中&#xff0c;条形码在仓储物流中&#xff0c;主要的作用是对物料跟踪管理、建立完整的产品档案&#xff0c;保障仓储的稳定运行&#xff0c;利用仓储空间&#xff0c;提高服务质量。 …

(DXE_DRIVER)PciHostBridge

UEFI-PciHostBridge 1、PciHostBridge简介 PciHostBridge: 提供PCI配置空间,IO,MEM空间访问接口以及统一维护平台相关的PCI资源,提供gEfiPciHostBridgeResourceAllocationProtocolGuid,创建RootBridge等为PciBusDxe提供服务; 2、PciHostBridge 配置空间 PCI桥可管理其下PCI子…

table 单元格中嵌套子表格 样式撑开问题

如图&#xff0c;表格中的td嵌套表格&#xff0c;里边表格把外层撑开&#xff0c;不能按100%显示&#xff1b; 解决办法 给父级table 加一个table-layout:fixed;样式

Tomcat启动! 一文带你知道什么是Tomcat以及如何安装

前言&#xff1a; Tomcat&#xff08;全称为Apache Tomcat&#xff09;是一个开源的Java Servlet容器&#xff0c;也是JavaServer Pages&#xff08;JSP&#xff09;的引擎。它是Apache软件基金会的一个项目&#xff0c;用于使Java应用能够在Web服务器上运行。Tomcat充当Web服务…

小节2:Python数学运算

1、Python的运算优先级顺序和平时数学中的一样&#xff0c;都是先括号&#xff0c;再乘方&#xff0c;再乘除&#xff0c;再加减。 PS&#xff1a;乘方符号再Python中用**表示&#xff0c;如2的三次方用2**3表示 2、用Python做更高级的运算&#xff08;如&#xff1a;三角函数…

敏捷开发、V模型开发、瀑布模型

在软件开发领域&#xff0c;敏捷开发和V模型开发是两种主要的开发方法。它们之间的差异主要体现在开发过程的结构和组织方式上。在以下讨论中&#xff0c;我们将深入探讨这两种方法的特点和差异。 敏捷开发 敏捷开发是一种迭代和增量的软件开发方法&#xff0c;它强调灵活性和…

IDEA新建的Moudle失效显示为灰色

现象&#xff1a;IDEA新建的Moudle失效显示为灰色&#xff01;&#xff01;&#xff01; 解决方案&#xff1a; 1. 右键点击父模块&#xff0c;选择Open Moudle Settings&#xff1a; 2. 点击加号&#xff0c;选择Import Moudle - 导入模块&#xff1a; 3. 找到对应模块的po…