如何创建智能合约来铸造 NFT
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
在本文中,我们将创建一个智能合约,用于在以太坊上铸造 NFT。
设置项目
为了启动该项目,我们将使用安全帽,它将为我们提供部署合约、进行测试等的样板。
安装安全帽
我们将使用 yarn 安装 hardhat 作为开发依赖项。
打开一个新的终端窗口,并运行以下命令:
mkdir nft-token
cd nft-token
yarn init -y
yarn add hardhat -D
在安装 Hardhat 的同一目录下运行:
npx hardhat
使用键盘选择“创建一个空的 hardhat.config.js”,然后按回车键。
888 888 888 888 888
888 888 888 888 888
888 888 888 888 888
8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
888 888 "88b 888P" d88" 888 888 "88b "88b 888
888 888 .d888888 888 888 888 888 888 .d888888 888
888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
👷 Welcome to Hardhat v2.6.4 👷
? What do you want to do? …
Create a basic sample project
Create an advanced sample project
❯ Create an empty hardhat.config.js
Quit
创建文件和目录
我们先在根文件夹中创建一个名为 contracts 的目录。
/node_modules
/contracts
hardhat.config.js
package.json
yarn.lock
创建文件夹后,我们可以在该目录下创建合约的第一个文件,我们将其命名为:factoryNFT.sol
/node_modules
/contracts
| - factoryNFT.sol
hardhat.config.js
package.json
yarn.lock
编写智能合约
现在我们进入文章中最令人期待的部分——撰写合同。
注:您可以在我的另一篇文章中回顾基础知识:如何使用 Solidity 创建智能合约来接收捐赠
让我们开始定义编译指示版本:
factoryNFT.sol
pragma solidity ^0.8.3;
为了帮助我们,我们将安装 openzeppelin 合约包。
yarn add @openzeppelin/contracts @openzeppelin/hardhat-upgrades
现在我们可以把它导入到合同中。
factoryNFT.sol
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
我们进行了 3 次进口:
计数器:这是一个很有用的工具,可以帮助我们为每个新令牌递增 tokenId。ERC721URI
存储:我们将提供一些函数来处理我们的 tokenURI,其中包含元数据和图像。
ERC721:我们将介绍ERC721的一些基本功能;
继承OpenZeppelin合约
现在我们可以开始定义合约名称并继承 OpenZeppelin 合约了。
factoryNFT.sol
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract FactoryNFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("Factory NFT", "FTN") {
}
}
创建我们的 Mint 功能
首先,我们创建一个名为 createToken 的函数,它将接收一个参数,即我们的 tokenURI。
factoryNFT.sol
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract FactoryNFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("Factory NFT", "FTN") {
}
function createToken(string memory tokenURI) public returns (uint) {
}
}
现在让我们增加存储中的令牌数量并将其保存到一个变量中。
factoryNFT.sol
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract FactoryNFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("Factory NFT", "FTN") {
}
function createToken(string memory tokenURI) public returns (uint) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
}
}
现在我们可以添加合约的主要功能,即铸造我们的 NFT 并设置其 tokenURI。
factoryNFT.sol
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract FactoryNFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("Factory NFT", "FTN") {
}
function createToken(string memory tokenURI) public returns (uint) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
编译和测试合约
现在为了测试合约,我们将编译它并为其编写测试。
首先,让我们打开hardhat.config.js文件,将 Solidity 版本更改为 ^0.8.3。
hardhat.config.js
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "^0.8.3",
};
插件
现在为了测试我们的合约,我们需要为 Hardhat 安装一些插件,以帮助我们与以太坊进行交互并测试我们的合约。
yarn add -D @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai
添加插件后,我们需要添加一行代码hardhat.config.js来设置插件。
hardhat.config.js
require("@nomiclabs/hardhat-waffle");
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "^0.8.3",
};
编写测试
现在在根文件夹下创建一个名为 test 的目录,并添加名为:factoryNFT.js
/node_modules
/contracts
/test
|- factoryNFT.js
hardhat.config.js
package.json
yarn.lock
现在我将把测试题放在下面,并逐行解释,以便大家理解。
const { expect } = require("chai");
describe("Minting the token and returning it", function () {
it("should the contract be able to mint a function and return it", async function () {
const metadata = "https://opensea-creatures-api.herokuapp.com/api/creature/1" //Random metadata url
const FactoryContract = await ethers.getContractFactory("FactoryNFT"); // Getting the contract
const factoryContract = await FactoryContract.deploy(); //Deploying the Contract
const transaction = await factoryContract.createToken(metadata); // Minting the token
const tx = await transaction.wait() // Waiting for the token to be minted
const event = tx.events[0];
const value = event.args[2];
const tokenId = value.toNumber(); // Getting the tokenID
const tokenURI = await factoryContract.tokenURI(tokenId) // Using the tokenURI from ERC721 to retrieve de metadata
expect(tokenURI).to.be.equal(metadata); // Comparing and testing
});
});
现在让我们配置 package.json 来运行我们的脚本,将此脚本添加到您的 package.json 中以编译合约。
"scripts": {
"compile": "yarn hardhat compile"
}
package.json
{
"name": "hardhat",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"compile": "yarn hardhat compile"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"chai": "^4.3.4",
"ethereum-waffle": "^3.4.0",
"ethers": "^5.4.6",
"hardhat": "^2.6.4"
},
"dependencies": {
"@openzeppelin/contracts": "^4.3.2",
"@openzeppelin/hardhat-upgrades": "^1.10.0"
}
}
现在只需编译并运行测试,就能得到结果!
yarn compile
npx hardhat test
到此结束,您可以阅读我的下一篇文章,了解如何部署到 Rinkeby 测试网:如何使用 Infura 和 Hardhat 将智能合约部署到 Rinkeby 测试网。
代码仓库:https://github.com/EmanuelCampos/mint-nft
关注我的推特