Dapp开发实战教程1-在BSC上打造自己的第一个数字藏品NFT并上传到IPFS

从0开始打造自己的第一个NFT,并将元数据上传到IPFS

编写NFT合约

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface INFT {
    function setContractURI(string memory _contractURI) external returns(bool);

    function createToken(string memory _tokenURI) external returns(uint256 tokenId);

    function getInfo(uint256 _nftTokenId) external view returns (address, string memory, string memory, string memory);

    function getTokens(address _user) external returns(uint256[] memory);
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import './interfaces/INFT.sol';

contract NFT is INFT, ERC721Enumerable, ERC721URIStorage {

    address public owner; // 记录合约发布者
    uint256 public lastTokenId = 100000; // 记录最后1个tokenId,初始tokenId为100000
    string public contractURI; // 如果上opensea会用到此参数

    // 发布合约时,传入name和symbol两个参数
    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {
        owner = _msgSender();
    }

    // 设置contractURI参数
    function setContractURI(string memory _contractURI) external override virtual returns(bool) {
        require(msg.sender == owner, 'NFT: 4001');
        contractURI = _contractURI;
        return true;
    }

    // 创建token接口,传入tokenURI
    function createToken(string memory _tokenURI) external override virtual returns(uint256 tokenId) {
        // 此处要求只有合约发布者可以创建
        require(_msgSender() == owner, "NFT: 4002");
        tokenId = mint(owner, _tokenURI);
        // 如果没有设置过contractURI,将第一个tokenURI设置给contractURI
        if(bytes(contractURI).length == 0 ){
            contractURI = _tokenURI;
        }
    }

    // 传入tokenId,获取token详情(返回owner、symbol、name、tokenURI)
    function getInfo(uint256 _tokenId) external view virtual override returns (address ownerAddress, string memory name, string memory symbol, string memory _tokenURI) {
        ownerAddress = super.ownerOf(_tokenId);
        name = super.name();
        symbol = super.symbol();
        _tokenURI = tokenURI(_tokenId);
    }

    // 私有函数,用于打造NFT
    function mint(address _to, string memory _tokenURI) private returns (uint256) {
        lastTokenId++; // tokenId加1
        _mint(_to, lastTokenId); // 将token打造给_to
        _setTokenURI(lastTokenId, _tokenURI); // 设置tokenURI

        return lastTokenId;
    }

    // 根据tokenId获取tokenURI
    function tokenURI(uint256 tokenId) public view virtual override (ERC721, ERC721URIStorage) returns (string memory) {
        return super.tokenURI(tokenId);
    }

    // 燃烧token
    function _burn(uint256 tokenId) internal virtual override (ERC721, ERC721URIStorage) {
        require(tokenId > 0, "GoShard: 4003");
        super._burn(tokenId);
    }

    // 在转赠NFT前执行的操作
    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override(ERC721, ERC721Enumerable) {
        // TODO 此处可以加入自己的逻辑
        super._beforeTokenTransfer(from, to, tokenId);
    }

    // 判断支持的接口
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    // 获取指定地址拥有的全部token
    function getTokens(address _user) external view override virtual returns(uint256[] memory) {
        // 第一次遍历所有token,找到属于_user的token,记录到_userTokens数组
        uint256[] memory _userTokens = new uint256[](lastTokenId);
        uint256 idx = 0;
        for(uint256 tokenId = 100000 + 1; tokenId <= lastTokenId; tokenId++){
            if(super.ownerOf(tokenId) == _user){
                _userTokens[idx] = tokenId;
                idx++;
            }
        }
        // idx为_userTokens数组长度,再次遍历,将值赋给新的数组userTokens
        // 遍历两次是因为_userTokens的长度为lastTokenId,中间会有0值,第二次遍历实现将0值排除,保留有效的tokenId并返回
        uint256[] memory userTokens = new uint256[](idx);
        for(uint256 i = 0; i < idx; i++){
            userTokens[i] = _userTokens[i];
        }
        return userTokens;
    }
}

首先复制以上的NFT合约代码到Remix,新建一个openzeppelin erc721项目模板。在左侧项目结构的contracts目录下新建一个NFT.sol合约文件,粘贴以上代码到文件中。然后进行编译。如图: _20220708105207.png 编译成功后,选择Injected Web3,连接到自己的钱包。 image.png 在CONTRACT下拉列表中选择NFT.sol,填写name和symbol,点击deploy部署合约 image.png

部署成功后如下图所示,会生成合约地址: image.png

这样我们的NFT合约就部署完成了。

视频讲解:

视频讲解:https://www.bilibili.com/video/BV1D34y1p7Gt?share_source=copy_web

下一节,讲解如何创建元数据,并上传元数据到IPFS。

本文参与区块链开发网写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2022-07-08 11:05
  • 阅读 ( 584 )
  • 学分 ( 18 )
  • 分类:DApp
© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发
区块链技术的头像-区块链开发网

昵称

取消
昵称表情代码图片