solidity实现智能合约教程(4)-ERC1155合约

猛戳订阅学习专栏🍁🍁 👉 solidity系列合约源码+解析 👈 🍁🍁

在这里插入图片描述

1 介绍

ERC-1155是一种以太坊代币标准,由Enjin首席技术官Witek Radomski等人开发,并于2018年6月17日将该标准的第一个版本放置到Ethereum的github库中。其主要可用于游戏行业中道具的生成和处理。该标准的提出对nft在游戏行业的应用起到了极大的提升。在一定程度上融合了ERC-20和ERC-721的功能。

其主要用途包括了发行同质化代币和非同质化代币。同质化代币即能像ERC-20一样发布各样的代币类型,但目前为止各钱包和交易所暂未支持ERC-1155标准代币;与此同时,ERC-1155标准更是能够发行NFT,且能基于一个合约同时发行多个NFT。伴随现在区块链游戏的大火,ERC-1155标准能够给基于以太坊的上的游戏开发运行提供大大的帮助。尤其在同质化道具的生成和处理上,该标准能够极大降低成本,提高效率。

2 主要功能

该标准定义了开发者可以按照标准要求使用一些简单的功能如:

  • 设定NFT名称
  • 设定NFT总量
  • 设定NFT元数据资源URI
  • 查看地址中NFT余额
  • 查看NFT的归属地址
  • 规范如何批准NFT转移
  • 一定条件下,允许第三方地址使用某账户中的NFT
  • 允许NFT和兼容ETH的智能合约及钱包服务等第三方个体兼容
    以及一些简单的函数功能等等。

我们先来看一下标准的 ERC1155 标准的接口:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IERC1155 {

    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    event TransferBatch(address indexed operator,address indexed from,address indexed to,uint256[] ids,uint256[] values);

    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    function balanceOf(address account, uint256 id) external view returns (uint256);

    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);

    function setApprovalForAll(address operator, bool approved) external;

    function isApprovedForAll(address account, address operator) external view returns (bool);

    function safeTransferFrom(address from,address to,uint256 id,uint256 amount,bytes calldata data) external;

    function safeBatchTransferFrom(address from,address to,uint256[] calldata ids,uint256[] calldata amounts,bytes calldata data) external;}

下面我们解释一下上述每个接口函数的作用:

  • event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value) 当任何NFT的所有权更改时,会触发此事件。

  • event TransferBatch(address indexed operator,address indexed from,address indexed to,uint256[] ids,uint256[] values); 当NFT发生批量转移时会触发该事件

  • event ApprovalForAll(address indexed account, address indexed operator, bool approved); 所有者启用或禁用操作员时触发。(操作员可管理所有者所持有的NFTs)

  • event URI(string value, uint256 indexed id);; 当给某个NFT绑定或更新URI资源文件时触发

  • function balanceOf(address account, uint256 id) external view returns (uint256); 查询某地址中指定tokenId的NFT的数量

  • function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); 查询给定的地址数组中的地址对应的tokenId数组中tokenId的NFT的数量

  • function safeTransferFrom(address from,address to,uint256 tokenId,bytes calldata data) external; 将NFT的所有权从一个地址转移到另一个地址,data : 附加额外的参数(没有指定格式),传递给接收者。

  • function setApprovalForAll(address operator, bool _approved) external; 启用或禁用第三方(操作员)管理 msg.sender 所有资产,触发 ApprovalForAll 事件。

  • function getApproved(uint256 tokenId) external view returns (address operator); 获取单个NFT的授权地址

  • function safeBatchTransferFrom(address from,address to,uint256[] calldata ids,uint256[] calldata amounts,bytes calldata data) external;}给指定的地址转移指定tokenId数组所对应的数量数组中的数量的NFT

3 代码示例

下面我们借助openzeppelin智能合约库来写一个ERC1155合约,来实现NFT的铸造、批量铸造、单个NFT的URI信息获取和批量URI获取等功能。
代码:

// SPDX-License-Identifier: MIT;

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/utils/Counters.sol";


contract Test1155 is ERC1155 {

    using Counters for Counters.Counter;
    Counters.Counter private _tokenId;

    mapping(uint => string) private _tokenURIs;

    constructor() ERC1155("https://baseUrl.com") {}

    function mint(address _recipient,uint _amount, string memory _tokenUrl) public returns(uint _mintTokenId){
        require(bytes(_tokenUrl).length > 0,"The _tokenUrl must be have");
        require(_amount > 0,"The _amount must be have");
        _tokenId.increment();
        uint newTokenId = _tokenId.current();
        _mint(_recipient, newTokenId,_amount,"");
        _tokenURIs[newTokenId] = _tokenUrl;
        return newTokenId;
    }

    function mintBatch(address _recipient,uint[] memory _amounts,string[] memory _tokenUrls) public returns(uint[] memory _mintTokenIds){
        require(_amounts.length > 0,"The _amounts must be have");
        require(_tokenUrls.length > 0,"The _tokenUrls must be have");
        require(_amounts.length == _tokenUrls.length,"The _tokenUrl length must be Equal _amounts length");

        uint newTokenId;
        uint[] memory returnTokenUrls = new uint[](_amounts.length);

        for(uint256 i = 0; i < _amounts.length; i++){
            _tokenId.increment();
            newTokenId = _tokenId.current();
            _tokenURIs[newTokenId] = _tokenUrls[i];
            returnTokenUrls[i] = newTokenId;
        }

        _mintBatch(_recipient, returnTokenUrls,_amounts,"");

        return returnTokenUrls;
    }

    function uri(uint256 _id) public view override returns(string memory _tokenUrl){
        return _tokenURIs[_id];
        
    }

    function uriBatch(uint[] memory _tokenIds) public view returns(string[] memory _tokenUrls){
        require(_tokenIds.length > 0,"The _tokenId must be have");

        string[] memory returnTokenUrl = new string[](_tokenIds.length);

        for(uint256 i=0;i<_tokenIds.length;i++){
            returnTokenUrl[i] = _tokenURIs[_tokenIds[i]];
        }

        return returnTokenUrl;
    }

}

4 部署测试

在这里插入图片描述
我们先部署好该1155合约

在这里插入图片描述
我们给当前地址铸造了5个tokenId相同的NFT,并给该NFT的URI资源设定为www.test.img,从交易的output中可以看到该tokenId为1

在这里插入图片描述
接下来我们查询到了该地址中tokenId为1的NFT数量为5个,代表着铸造成功!

在这里插入图片描述
然后我们查询到tokenId为1的NFT的URI地址为www.test.img,OK,没问题
我们可以根据该流程测试批量的mint和转账方法,这里就不再一一列举。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值