玩转Web3:创建属于自己的ERC-721(NFT)
大家好,本章是 《玩转Web3》 的第三章,我们本次使用 Solidity
进行 ERC721
合约编写,来创造属于我们自己的 NFT
,我们会将 NFT
图片上传到 IPFS
,并将整个合约部署到 Rinkeby
测试网络。
前提知识了解
NFT了解
ERC-721
就是为了创造所谓的 非同质化代币 即 NFT
(下文我们都简称NFT),NFT
藏品已经非常流行了,如 Azuki
、CryptoZunks
、Cryptokitties
项目等,
都是采用 721
标准创建的,NFT 的使用场景也挺丰富,如:
- 数字艺术(或实物艺术):艺术作品是NFT最受欢迎的使用案例。 数字艺术拍卖是NFT的第一个应用,并且还在继续发展。
- 游戏:提供游戏内购和游戏收藏。
- 房地产:将房产和智能合约Token化,并进行买卖。
- 金融:贷款、期货等金融工具,并承担其他责任。
- 软件标题:软件授权,确保反盗版和隐私。
- 演唱会门票/体育比赛门票:为了保证在卖票过程中不发生欺诈行为,粉丝可以在一个地方查看以往的经历。
- KYC合规性:为特定用户的KYC创建代币。
NFT
在合约中的表现形式
// 查NFT数量
function balanceOf(address _owner) external view returns (uint256);
// 查token的属主
function ownerOf(uint256 _tokenId) external view returns (address);
// 也是转账函数,更加安全点 solidity是支持多态的,所以是同名函数
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
// 也是转账函数,更加安全点
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
// 将from这个地址的tokenID编号的NFT转给to这个地址
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
// 此函数批准另一个实体代表所有者转让代币的权限
function approve(address _approved, uint256 _tokenId) external payable;
// 授权或者取消授权operator这个地址转移你所有NFT
function setApprovalForAll(address _operator, bool _approved) external;
// 查询tokenId编号的NFT授权给了谁(查询谁可以转走你的NFT!)
function getApproved(uint256 _tokenId) external view returns (address);
// 查询某个operator是否有权转移某个owner的这一Collection中的所有NFT(查询某个地址是否可以转走你这个Collection的所有NFT!)
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
// 当代币的所有权从一个人变为另一个人时,该事件被触发。 发出的信息包括哪个账户转移了代币,哪个账户收到了代币,以及哪个代币(通过ID)被转移。
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
// 当用户批准另一个用户获得代币的所有权时,该事件就会被触发,也就是说,每当approve函数被执行时,该事件就会被触发。 它发出的信息包括:当前哪个账户拥有该代币,哪个账户被批准在未来拥有该代币,以及哪个代币(通过ID)被批准转让其所有权。
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
// 调用setApprovalForAll触发事件
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
openzeppelin
中有tokenURI
用来查看NFT
的描述数据openzeppelin
中有awardItem
用来铸造NFT
的描述数据 (这里为了方便没有设置铸造门槛,真实情况我们可以编写白名单进行铸造限制等)
IPFS了解
NFT
是所谓的数字资产,这些资产都是需要存储介质的,可以是中心化服务器,也可以是分布式去中心化的,IPFS
就是点对点的文件系统,官方称为 星际文件系统,是一个分布式存储和共享文件的网络传输协议,他可以尽可能地保证我们文件的存在。
- 官网安装:
https://ipfs.io/#install
可以使用 cli
版或者 desktop
版,都差不多,我们这边是采用 go-ipfs
,这个工具使用起来非常简单,这里就不多去说明,可以查阅这篇登链社区的文章 https://learnblockchain.cn/2018/12/25/use-ipfs
开篇
我们的操作流程如下:
Remix IDE
构建ERC-721
合约- 创建
NFT
元数据上传到ipfs
并写入到区块中 - 部署到
Rinkeby
测试网络
构建ERC-721合约
我们还是使用 openzeppelin
来进行合约的快速编写
- aopnft.sol
// "SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "./node_modules/@openzeppelin/contracts/utils/Counters.sol";
contract AOPNFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("AOPNFT", "AOPNFT") {}
// 铸造NFT方法
function awardItem(address player, string memory tokenURI)
public
returns (uint256)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(player, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
我们可以先使用 JavaScript VM
来进行合约部署测试,保证正常了我们再进行测试链部署,部署成功后,我们需要创建 NFT
啦。
创建NFT
将NFT图片上传到IPFS上
# nft原图
ipfs add apple.png # QmaeC5SBeGuQyLaXLAehLMnwWy8ruj123Ki1DK3RcbxJSd
# nft描述文件
ipfs add apple.json # QmRVSjT169HWZetXrDbAwXdZuBWV4dhixBTuM1H6RM9Ucc
通过 ipfs
协议去访问描述文件:ipfs://QmRVSjT169HWZetXrDbAwXdZuBWV4dhixBTuM1H6RM9Ucc
合约铸造
- 通过合约的
TOKENURI
方法获取nft
的资源路径,需要传入我们铸造nft
时返回的tokenId
tokenuri(1) // ipfs://QmRVSjT169HWZetXrDbAwXdZuBWV4dhixBTuM1H6RM9Ucc
这个时候,我们的 NFT
就创造成功了,接下来让我们部署到测试网络上去吧。
将合约部署到Rinkeby网络
然后 Deploy
,这一步需要我们使用小狐狸去签名确认,然后就部署成功了,合约地址为 0x5bCc79242339b8F231d5D358EEa370781EA713d1
,当然也可以通过测试网络的浏览器去在线查看和调式 https://rinkeby.etherscan.io/address/0x5bcc79242339b8f231d5d358eea370781ea713d1
- 然后我们在测试网络进行铸造
可以看到,我们的在测试网络的 NFT
已经铸造成功了
同时也可以将合约加入到我们的小狐狸钱包,剩下的就给大家自己操作啦。
总结
这一章,我们了解 NFT
的创作过程,可以发现,NFT
的本质是图片,其次在于描述文件,描述文件越丰富,NFT
就可以更加多样化,本章中我们 NFT
是存储在 IPFS
这个文件系统上,不容易丢失,当然你也可以存储在自己的服务器或者托管到第三方服务器,都不一样,NFT
对应的只是一个资源地址罢了,所以投资有风险,入市需谨慎。
如果是单纯地编写合约,那么不是开发人员根本不懂如何与合约交互,那门槛就更高了,我们需要让更多的人来参与我们的项目,所以我们需要构建合约的客户端,之后我们会创建合约的 web客户端,这样就可以让更多的人参与了。