从零开始构建 NFT 网站(1)- 部署合约

Ethers.js
Vue3
DAPP
Alchemy

准备工作

Alchemy 账号

Alchemy 官网

创建 Alchemy 应用,获得 API KEY 和 RPC 节点地址。

Metamask 账号

下载 Metamask 插件,创建钱包,获得 ETH 地址和密钥。

领取测试币

每次可以领 0.5 个,没事的时候领点水以备不时之需。地址:https://www.alchemy.com/faucets/ethereum-sepolia

创建一个 Node 项目

mkdir my-nft && cd my-nft
npm init -y

创建 Hardhat 项目

my-nft 文件夹下,安装 Hardhat,并创建 dApp

npm install --save-dev hardhat
npx hardhat

这里可能会报错:Error: Cannot find module ‘@nomicfoundation/hardhat-toolbox’

安装一下即可:npm install --save-dev @nomicfoundation/hardhat-toolbo

检查一切是否正常运行:npx hardhat test

现在 Hardhat 开发环境搭建好了,继续安装 OpenZeppelin 合约包,这可以让我们访问 ERC721 接口,我们将在此基础上构建合约。

npm install @openzeppelin/contracts

编写智能合约

在 contracts 文件夹里创建一个名为 MyNFT.sol 的新文件,编写代码:

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

// 继承 ERC721 标准的所有方法,要制作有效的 NFT ,必须实现所有方法
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
// 跟踪铸造的 NFT 总数,并为新 NFT 设置唯一 ID
import "@openzeppelin/contracts/utils/Counters.sol";
// 设置访问控制,只有合约所有者才能铸造 NFT
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyNFT is ERC721URIStorage, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    // 参数:智能合约名称,合约符号
    constructor() ERC721("MyNFT", "NFT") {}

    // 参数:接收新铸造 NFT 的地址,NFT 元数据(名称,描述等属性)
    function mintNFT(address recipient, string memory tokenURI)
        public
        onlyOwner
        returns (uint256)
    {
        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);

        return newItemId;
    }
}

这里有一个小坑,@openzeppelin 5.0.0 删除了 Counters.sol 文件,可以自己写一个计数器替代,也可以降级到 4.9.3

把 Metamask 和 Alchemy 连接到项目

现在已经完成了三个步骤:创建 Metamask 钱包,创建 Alchemy 账号、创建智能合约。

接下来要把三者连接起来:从钱包发送的交易需要使用「私钥」进行签名,我们可以把私钥和 Alchemy API 秘钥存储在环境文件里。

npm install dotenv --save

根目录下创建 .env 文件:

API_URL = "https://eth-sepolia.g.alchemy.com/v2/your-api-key";
PRIVATE_KEY = "your-metamask-private-key";

更新 hardhat.config.js

require("dotenv").config();
require("@nomicfoundation/hardhat-ethers");
const { API_URL, PRIVATE_KEY } = process.env;

module.exports = {
	solidity: "0.8.24",
	defaultNetwork: "sepolia",
	networks: {
		hardhat: {},
		sepolia: {
			url: API_URL,
			accounts: [`0x${PRIVATE_KEY}`],
		},
	},
};

编写部署脚本

在根目录下创建 deploy.js,编写代码:

async function main() {
	// Grab the contract factory
	const MyNFT = await ethers.getContractFactory("MyNFT");

	// Start deployment, returning a promise that resolves to a contract object
	const myNFT = await MyNFT.deploy(); // Instance of the contract
	console.log("Contract deployed to address:", myNFT.target);
}

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

部署合约

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

成功之后应该会输出:

Compiled 18 Solidity files successfully (evm target: paris).
Contract deployed to address: 0x7130Df343097ED88d112Cec1B366bDaa3530a67e

到 Sepolia 浏览器上检查一下:sepolia etherscan

01

可以看到合约已经成功部署了。