solidity实现ERC1155多代币标准
文章目录
- 1、NFT - 维基百科
- 2、IERC1155MetadataURI
- 3、IERC1155Receiver
- 4、IERC1155
- 5、ERC1155
- 6、NFT1155
- 7、开源地址
1、NFT - 维基百科
ERC-1155 标准于2018年6月由Witek Radomski、Andrew Cooke、Philippe Castonguay、James Therien、Eric Binet及Ronan Sandford提出。此标准可针对单一应用合约,提供同质代币、非同质代币(用ERC-1155建构ERC-721资产)及其他结构类型(例如半同质代币,semi-fungible tokens)的多元组合。相较于ERC-721每创立一个代币ID就对应一个单独智能合约资产,在ERC-1155多元代币标准下,每个代币ID可以代表一系列不同类型的资产,并附加量化区块以标示钱包中各类型资产的数量;同类型资产可以互换,要转让多少数量也可以。
ERC-1155 标准下的NFT结构上更有弹性:拥有元数据、供应量与其他属性;新功能包括:可一次传输多种代币类型以节省交易成本、也可同时进行多个代币交易(托管/原子交换)而无需逐一批准每个合约、可在单一应用合约中注明并混搭多种FT、NFT及SFT。
2、IERC1155MetadataURI
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;// ERC1155的可选接口,加入了uri()函数查询元数据
interface IERC1155MetadataURI {// 返回第`id`种类代币的URIfunction uri(uint256 id) external view returns (string memory);
}
3、IERC1155Receiver
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;import "./IERC165.sol";interface IERC1155Receiver is IERC165 {// 接受ERC1155安全转账`safeTransferFrom` function onERC1155Received(address operator,address from,uint256 id,uint256 value,bytes calldata data) external returns (bytes4);// 接受ERC1155批量安全转账`safeBatchTransferFrom` function onERC1155BatchReceived(address operator,address from,uint256[] calldata ids,uint256[] calldata values,bytes calldata data) external returns (bytes4);
}
4、IERC1155
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;import "./IERC165.sol";// https://eips.ethereum.org/EIPS/eip-1155[EIP].
interface IERC1155 is IERC165 {// 单类代币转账事件event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);// 批量代币转账事件, ids和values为转账的代币种类和数量数组event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);// 批量授权事件, 当`account`将所有代币授权给`operator`时释放event ApprovalForAll(address indexed account, address indexed operator, bool approved);// 当`id`种类的代币的URI发生变化时释放,`value`为新的URIevent URI(string value, uint256 indexed id);// 持仓查询,返回`account`拥有的`id`种类的代币的持仓量function balanceOf(address account, uint256 id) external view returns (uint256);// 批量持仓查询,`accounts`和`ids`数组的长度要想等。function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);// 批量授权,将调用者的代币授权给`operator`地址。释放{ApprovalForAll}事件.function setApprovalForAll(address operator, bool approved) external;// 批量授权查询,如果授权地址`operator`被`account`授权,则返回`true`function isApprovedForAll(address account, address operator) external view returns (bool);// 安全转账,将`amount`单位`id`种类的代币从`from`转账给`to`. 释放{TransferSingle}事件.function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;// 批量安全转账, 释放{TransferBatch}事件function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}
5、ERC1155
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;import "./IERC1155.sol";
import "./IERC1155Receiver.sol";
import "./IERC1155MetadataURI.sol";
import "./Address.sol";
import "./Strings.sol";
import "./IERC165.sol";// ERC1155多代币标准 https://eips.ethereum.org/EIPS/eip-1155
contract ERC1155 is IERC165, IERC1155, IERC1155MetadataURI {using Address for address; using Strings for uint256; // Token名称string public name;// Token代号string public symbol;// 代币种类id 到 账户account 到 余额balances 的映射mapping(uint256 => mapping(address => uint256)) private _balances;// address 到 授权地址 的批量授权映射mapping(address => mapping(address => bool)) private _operatorApprovals;// 构造函数,初始化`name` 和`symbol`, uri_constructor(string memory name_, string memory symbol_) {name = name_;symbol = symbol_;}function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {returninterfaceId == type(IERC1155).interfaceId ||interfaceId == type(IERC1155MetadataURI).interfaceId ||interfaceId == type(IERC165).interfaceId;}// 持仓查询 实现IERC1155的balanceOf,返回account地址的id种类代币持仓量。function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {require(account != address(0), "ERC1155: address zero is not a valid owner");return _balances[id][account];}// @dev 批量持仓查询 function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) {require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");uint256[] memory batchBalances = new uint256[](accounts.length);for (uint256 i = 0; i < accounts.length; ++i) {batchBalances[i] = balanceOf(accounts[i], ids[i]);}return batchBalances;}// 批量授权,调用者授权operator使用其所有代币function setApprovalForAll(address operator, bool approved) public virtual override {require(msg.sender != operator, "ERC1155: setting approval status for self");_operatorApprovals[msg.sender][operator] = approved;emit ApprovalForAll(msg.sender, operator, approved);}// 查询批量授权.function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {return _operatorApprovals[account][operator];}// 安全转账,将`amount`单位的`id`种类代币从`from`转账到`to`function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) public virtual override {address operator = msg.sender;// 调用者是持有者或是被授权require(from == operator || isApprovedForAll(from, operator),"ERC1155: caller is not token owner nor approved");require(to != address(0), "ERC1155: transfer to the zero address");// from地址有足够持仓uint256 fromBalance = _balances[id][from];require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");// 更新持仓量unchecked {_balances[id][from] = fromBalance - amount;}_balances[id][to] += amount;// 释放事件emit TransferSingle(operator, from, to, id, amount);// 安全检查_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); }// 批量安全转账,将`amounts`数组单位的`ids`数组种类代币从`from`转账到`to`function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) public virtual override {address operator = msg.sender;// 调用者是持有者或是被授权require(from == operator || isApprovedForAll(from, operator),"ERC1155: caller is not token owner nor approved");require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");require(to != address(0), "ERC1155: transfer to the zero address");// 通过for循环更新持仓 for (uint256 i = 0; i < ids.length; ++i) {uint256 id = ids[i];uint256 amount = amounts[i];uint256 fromBalance = _balances[id][from];require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");unchecked {_balances[id][from] = fromBalance - amount;}_balances[id][to] += amount;}emit TransferBatch(operator, from, to, ids, amounts);// 安全检查_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); }// 锻造function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual {require(to != address(0), "ERC1155: mint to the zero address");address operator = msg.sender;_balances[id][to] += amount;emit TransferSingle(operator, address(0), to, id, amount);_doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);}// 批量铸造function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {require(to != address(0), "ERC1155: mint to the zero address");require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");address operator = msg.sender;for (uint256 i = 0; i < ids.length; i++) {_balances[ids[i]][to] += amounts[i];}emit TransferBatch(operator, address(0), to, ids, amounts);_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);}// 销毁function _burn(address from, uint256 id, uint256 amount) internal virtual {require(from != address(0), "ERC1155: burn from the zero address");address operator = msg.sender;uint256 fromBalance = _balances[id][from];require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");unchecked {_balances[id][from] = fromBalance - amount;}emit TransferSingle(operator, from, address(0), id, amount);}// 批量销毁function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual {require(from != address(0), "ERC1155: burn from the zero address");require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");address operator = msg.sender;for (uint256 i = 0; i < ids.length; i++) {uint256 id = ids[i];uint256 amount = amounts[i];uint256 fromBalance = _balances[id][from];require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");unchecked {_balances[id][from] = fromBalance - amount;}}emit TransferBatch(operator, from, address(0), ids, amounts);}// 安全转账检查function _doSafeTransferAcceptanceCheck( address operator, address from, address to,uint256 id, uint256 amount, bytes memory data) private {if (to.isContract()) {try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {if (response != IERC1155Receiver.onERC1155Received.selector) {revert("ERC1155: ERC1155Receiver rejected tokens");}} catch Error(string memory reason) {revert(reason);} catch {revert("ERC1155: transfer to non-ERC1155Receiver implementer");}}}// ERC1155的批量安全转账检查function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to,uint256[] memory ids, uint256[] memory amounts, bytes memory data) private {if (to.isContract()) {try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {revert("ERC1155: ERC1155Receiver rejected tokens");}} catch Error(string memory reason) {revert(reason);} catch {revert("ERC1155: transfer to non-ERC1155Receiver implementer");}}}// 返回id种类代币的uri,存储metadata,类似ERC721的tokenURI.function uri(uint256 id) public view virtual override returns (string memory) {string memory baseURI = _baseURI();return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, id.toString())) : "";}// 计算{uri}的BaseURI,uri就是把baseURI和tokenId拼接在一起,需要开发重写.function _baseURI() internal view virtual returns (string memory) {return "";}
}
6、NFT1155
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;import "./ERC1155.sol"; contract NFT1155 is ERC1155 {uint256 constant MAX_ID = 10000;constructor() ERC1155("NFT1155", "NFT1155"){}function _baseURI() internal pure override returns (string memory) {return "ipfs://QmcPGA3kecSMfHcv8i6wpgB2RkPA1FSVqu6AZY3rKNmxuj/";}function mint(address to, uint256 id, uint256 amount) external {require(id < MAX_ID, "id overflow");_mint(to, id, amount, "");}function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts) external {for(uint256 i = 0; i < ids.length;i++){require(ids[i] < MAX_ID, "id overflow");}_mintBatch(to, ids, amounts, "");}
}
测试运行:

7、开源地址
gitee 开源地址。
相关文章:
solidity实现ERC1155多代币标准
文章目录 1、NFT - 维基百科2、IERC1155MetadataURI3、IERC1155Receiver4、IERC11555、ERC11556、NFT11557、开源地址 1、NFT - 维基百科 ERC-1155 标准于2018年6月由Witek Radomski、Andrew Cooke、Philippe Castonguay、James Therien、Eric Binet及Ronan Sandford提出。此标…...
10、外观模式(Facade Pattern,不常用)
外观模式(Facade Pattern)也叫作门面模式,通过一个门面(Facade)向客户端提供一个访问系统的统一接口,客户端无须关心和知晓系统内部各子模块(系统)之间的复杂关系,其主要…...
<软考>软件设计师-3程序设计语言基础(总结)
(一) 程序设计语言概述 1 程序设计语言的基本概念 1-1 程序设计语言的目的 程序设计语言是为了书写计算机程序而人为设计的符号语言,用于对计算过程进行描述、组织和推导。 1-2 程序语言分类 低级语言 : 机器语言(计算机硬件只能识别0和1的指令序列)&…...
C/C++---------------LeetCode第278. 第一个错误的版本
第一个错误的版本 题目及要求二分查找 题目及要求 你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。 假设你…...
C语言三种循环输出9*9乘法表
解题思路: 1、外层循环控制1~9循环 2、内层控制循环的次数 比如: 1 * 1 1 循环一次 1 * 1 1 1 * 2 循环两次 依此类推 int i, j;printf("for 打印9*9乘法表\r\n");for(i 1; i <10; i) {for(j 1; j < i;j) {printf("%d * %d %d…...
IntelliJ IDEA 之初体验
文章目录 第一步:下载与安装 IntelliJ IDEA1)官网下载2)选择那种安装包3)开始下载4)解压 第二步:启动 IntelliJ IDEA第三步:创建第一个 Java 项目第四步:运行第一个 Java 程序1&…...
java中synchronized和Lock的区别是什么?
synchronized 和 Lock 都是 Java 中用于实现线程同步的机制,但它们在使用方式和功能上存在一些区别。 使用方式 synchronized: 是 Java 语言关键字,可用于方法或代码块。通过 synchronized 关键字实现的同步是隐式的,无需手动释…...
ESP32-Web-Server编程-通过 Base64 编码在网页中插入图片
ESP32-Web-Server编程-通过 Base64 编码在网页中插入图片 概述 不同于上节 ESP32-Web-Server编程-在网页中通过 src 直接插入图片,本节引入 Base64 编码来显示图片。 Base64 是一种用64个字符来编码表示任意二进制数据的方法。任何符号都可以转换成 Base64 字符集…...
聊一聊大模型 | 京东云技术团队
事情还得从ChatGPT说起。 2022年12月OpenAI发布了自然语言生成模型ChatGPT,一个可以基于用户输入文本自动生成回答的人工智能体。它有着赶超人类的自然对话程度以及逆天的学识。一时间引爆了整个人工智能界,各大巨头也纷纷跟进发布了自家的大模型&#…...
pandas空格及网页空格符NBSP替换处理
df3[动作一课程内容]df3[动作一课程内容].str.replace( ,) df3[动作一课程内容]df3[动作一课程内容].str.replace( ,) 截图中代码为python展示代码,由于网页空格符和常规空格符看起来大致相同,但却不能用常规空格替换解决...
智能优化算法应用:基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.战争策略算法4.实验参数设定5.算法结果6.参考…...
数据结构和算法-栈
数据结构和算法-栈 1. 栈的介绍 栈的介绍: 栈的英文为(stack)栈是一个先入后出的有序列表栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶,另一端为固…...
C#基础与进阶扩展合集-进阶篇(持续更新)
目录 本文分两篇,基础篇点击:C#基础与进阶扩展合集-基础篇 一、进阶 1、Predicate 2、设置C#语言版本 3、ListCollectionView过滤集合 4、值类型与引用类型 5、程序设置当前项目工作目录 6、获取App.config配置文件中的值 7、Linq常用语句 8、…...
快速入门GitHub 之超简单的注册方法和超好用的使用技巧
最近几天发现有些人对Github网站很好奇,但是无奈自己不会用,因为是外国人的网站,首先自己的英文就不过关。对于这个,其实可以用谷歌浏览器去浏览Github,它有一键翻译的功能。但还是有必要介绍一下关于Github的一些功能和具体操作,初学编程语言的小伙伴们一定对 GitHub 有…...
ESP32-Web-Server编程- 在 Web 上开发动态纪念册
ESP32-Web-Server编程- 在 Web 上开发动态纪念册 概述 Web 有很多有趣的玩法,在打开网页的同时送她一个惊喜。 需求及功能解析 本节演示在 ESP32 上部署一个 Web,当打开对应的网页时,将运行动态的网页内容,显示炫酷的纪念贺词…...
双向ESD保护 汽车级TVS二极管 ESD9B3.3ST5G工作原理、特性参数、封装形式
什么是汽车级TVS二极管? TVS二极管是一种用于保护电子电路的电子元件。它主要用于电路中的过电压保护,防止电压过高而损坏其他部件。TVS二极管通常被称为“汽车级”是因为它们能够满足汽车电子系统的特殊要求。 在汽车电子系统中,由于车辆启…...
Ribbon-IRule 修改负载均衡的规则
1、负载均衡规则描述 (1)整体关系 (2)规则描述 内置负载均衡规则类规则描述RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下&…...
双十二电视盒子哪个牌子最好?自费3000+测评整理电视盒子推荐
双十二不知道电视盒子哪个牌子最好的新手很多,想要我分享电视盒子推荐,为结果更客观我花费三千多购入了十几款热销电视盒子,通过一个月时间的全面对比测评后整理了电视盒子推荐,给双十二不知道怎么选电视盒子的朋友们提供参考。 一…...
排序:直接选择排序
直接选择排序: 本质: 直接选择排序的本质就是在数组中进行遍历挑选出最大的元素,讲最大的元素放到对应的位置后,再次选出次大的位置,而后又放到对应的位置..........................直到数组成为一个有序序列。 优…...
Nacos多数据源插件
Nacos从2.2.0版本开始,可通过SPI机制注入多数据源实现插件,并在引入对应数据源实现后,便可在Nacos启动时通过读取application.properties配置文件中spring.datasource.platform配置项选择加载对应多数据源插件.本文档详细介绍一个多数据源插件如何实现以及如何使其生效。 注意:…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
