前言
智能合约为数字藏品提供技术支持,它可以定义数字藏品的简称、全称、发行数量、铸造方法、版权税等等,所有关于数字藏品的现实信息都离不开智能合约。
这篇教程我们开始编写智能合约,智能合约标准我们使用的是ERC-721(非同质化代币),接着使用HardHat来编译,编译是为部署到区块链上做准备,最后我们会把智能合约部署到Rinkeby测试网络上。
警告
本指南仅供学习交流使用,不得用于违法用途,如果侵犯了国家法律,责任自负。
完善项目结构
为了让我们的项目看起来有迹可循,需要在我们的项目根目录下创建两个文件夹,一个文件夹存放智能合约代码,一个文件夹存放执行合约相关任务的脚本文件,使用cmd命令进入项目根目录,然后输入命令
mkdir contracts
按下回车键执行命令
mkdir scripts
按下回车键执行命令
contracts将存放合约代码文件,scripts将存放执行合约的脚本文件
编写合约代码
选择一款编辑器打开项目文件夹my-contract,在contracts文件夹下新建个文件,名字叫MyContract.sol,下边是我们的合约代码,我们使用了OpenZeppelin的ERC-721标准库,复制并粘贴到你的MyContract.sol文件
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract MyContract is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private currentTokenId;
constructor() ERC721("OAXTOKEN", "OAX") {}
function mintTo(address recipient, string memory tokenURI)
public
returns (uint256)
{
currentTokenId.increment();
uint256 newItemId = currentTokenId.current();
_safeMint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
看起来有点难以理解?别慌,让我们一行接着一行看下去。
- 第一行我们定义了使用的Solidity(智能合约语言)版本号。
- 接下来从第4-6行引入了三个openzeppelin的关键类文件,来快速实现ERC-721的标准,而不需要我们再自己去一行一行的写合约代码。
ERC721.sol,包含了实现以太坊ERC-721标准的所有方法,我们的合约将会继承它,这样就保证了我们的合约是有效的。
- Counters.sol,提供计数器,只能递增或递减一次。我们的智能合约使用一个计数器来跟踪铸造的数字藏品总数,并在我们的新数字藏品上上设置唯一的ID。(使用智能合约创建的每个数字藏品都必须分配一个唯一的ID,我们的唯一ID仅由存在的NFT总数决定,例如,我们使用智能合约创建的第一个的ID为“1”,第二个的ID就是“2”,等等。)
- ERC721URIStorage,为我们提供了公共方法setTokenURI来设置每个藏品对应的元数据信息,从而让我们的数字藏品有了现实意义,比如一张门票、一个视频、一张画。
- 下边就是我们合约代码的正文了,只有一个计数器(currentTokenId),一个构造函数方法(constructor),和一个铸造方法(mintTo)。构造函数共有两个变量,第一个是我们数字藏品的全称(OAXTOKEN),第二个是简称(OAX),给你的数字藏品起一个你喜欢的全称和简称,改动这两项就可以。铸造方法也有两个变量,第一个是个以太坊地址,用以接收将要铸造成的藏品,第二个是元数据信息,一般的做法是设置一个网址,网址里存储信息,设置完成这两个参数后,会返回藏品的唯一ID给调用者。
在写完合约代码后,我们的项目结构会是这个样子
编译合约
在编译合约前,请你确保按照第二篇教程已经完成所有配置,我们需要更新hardhat.config.js,代码如下,复制粘贴到你的文件里。
/**
* @type import('hardhat/config').HardhatUserConfig
*/
require('dotenv').config();
require("@nomiclabs/hardhat-ethers");
const { API_URL, PRIVATE_KEY } = process.env;
module.exports = {
solidity: "0.8.1",
defaultNetwork: "rinkeby",
networks: {
hardhat: {},
rinkeby: {
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`]
},
ethereum: {
chainId: 1,
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`]
},
},
}
通过设置配置项,我们定义了编译合约的solidity版本,区块链网络类型,接口地址和付费的地址私钥。
现在我们只需要执行编译命令就可以了,打开项目根目录my-contract,输入以下命令
npx hardhat compile
如果命令运行正常,会有如下提示
C:\Users\ThinkPad\my-contract>npx hardhat compile
Compiling 1 file with 0.8.1
Solidity compilation finished successfully
部署合约
最后一步就是把合约部署到区块链网络上,我们需要使用javascript写一个简单的部署脚本,然后使用HardHat运行它。
在scripts目录下,新建文件deploy.js,复制下边代码到文件中
async function main() {
const [deployer] = await ethers.getSigners();
const NFT = await ethers.getContractFactory("MyContract");
await NFT.deploy();
console.log('合约地址:',NFT.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
部署脚本将会从MyContract.sol拿到编译过的合约代码,然后部署到网络上,如果部署成功我们会看到部署后的合约地址。
在项目根目录下,使用HardHat执行部署脚本
npx hardhat --network rinkeby run scripts/deploy.js
C:\Users\ThinkPad\my-contract>npx hardhat --network rinkeby run scripts/deploy.js
合约地址: 0x116Ca6682A03547BffF8Fa8E12Efd301872a1383
复制合约地址到以太坊rinkeby区块浏览器去查看刚才我们部署的合约,如果可以查到恭喜你,顺利为你的数字藏品部署了智能合约。
总结
目前为止,我们完成了智能合约的编写、编译、部署,在下篇教程里我们会开始铸造我们的数字藏品,方法是通过调用合约的mintTo方法,与此同时使用IPFS(去中心化的文件存储)绑定元数据到每个铸造出的数字藏品。
捐赠渠道
本教程是由本人自发的项目,如果你要支持我,请通过支付宝发送口令红包,将口令发送到我的邮箱351107490@qq.com,捐赠仅凭个人意愿,感谢支持。