玩转Web3:创建属于自己的ERC-721(NFT)

玩转Web3:创建属于自己的ERC-721(NFT)

大家好,本章是 《玩转Web3》 的第三章,我们本次使用 Solidity 进行 ERC721 合约编写,来创造属于我们自己的 NFT,我们会将 NFT 图片上传到 IPFS,并将整个合约部署到 Rinkeby 测试网络。

前提知识了解

NFT了解

ERC-721 就是为了创造所谓的 非同质化代币NFT (下文我们都简称NFT),NFT藏品已经非常流行了,如 AzukiCryptoZunksCryptokitties 项目等,
都是采用 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客户端,这样就可以让更多的人参与了。

您的支持是对我最大的鼓励!

发表于: 作者:憧憬。
关注互联网以及分享全栈工作经验的原创个人博客和技术博客,热爱编程,极客精神
Github 新浪微博 SegmentFault 掘金专栏