N合一代币合约ERC1151开发教程

Wesley13
• 阅读 776

ERC-1155是ERC-20和ERC-721的升级规范,它允许在一个交易中发送多种不同的代币,就像同时转账人民币和美元。ERC-1155以在区块链游戏中的广泛使用而闻名,但它其实也适合有很多其他的应用场景。在这个教程中我们将学习ERC-1155规范约定的主要接口,并利用openzepplin实现一个用于航空业的ERC-1155多重代币。

N合一代币合约ERC1151开发教程

用自己熟悉的语言学习 以太坊DApp开发Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart

1、什么是ERC-1155?

ERC-1155引入的关键功能是多代币支持。让我们通过航空代币来理解这一点的重要性。

假设我们处在一个世界上,每个航空公司都有自己的代币。现在,我想预订一架环球航班,其中有来自三家不同航空公司的三架转机航班。要支付机票,我需要进行三笔单独的交易,并分别为每笔交易使用不同的代币付款。

这个过程中许多事情可能会出错。如果我为航班1付费,然后已经预订了航班2怎么办?现在,我必须找到一个新的连接。在具有集中货币的现实世界中,这项工作是由在线旅行社(OTA)或更传统的传统旅行社完成的。但是,在我们的示例中,必须创建一个新的智能合约,该合约可以连续执行所有三笔交易,将其部署,然后调用交易功能。只为一次飞行就这么付费实在是有点复杂,不是吗?

好在我们可以创建了一个包含多个航空公司的单独代币的单一多代币合约,这正是ERC-1155允许我们执行的操作。我们可以添加任意种类的代币,而不仅仅是一个航空公司的代币。下面让我们更深入地了解ERC-1155的功能。

2、ERC-1155功能和特点

N合一代币合约ERC1151开发教程

  • 批量转移:一次调用即可转移多个资产。
  • 批次余额:一次调用即可获取多个资产的余额。
  • 批量批准:批准所有令牌到一个地址。
  • EIP-165支持:声明支持的接口。
  • 钩子接口:提供代币接受钩子接口。
  • NFT支持:如果供应量仅为1,则将其视为NFT。
  • 安全转移规则:安全转移的规则集

3、ERC-1155批量转账

批量转账与常规ERC-20转账非常相似。让我们看一下常规的ERC-20 transferFrom函数:

// ERC-20
function transferFrom(address from, address to, uint256 value) external returns (bool);

ERC-1155的唯一区别是,我们将值作为数组传递,并且还传递了id数组。例如,给定_ids= [3,6,13]和_values= [100,200,5],则转账结果为:

  • 将ID为3的100个代币从_from转移到_to。
  • 将ID为6的200个代币从_from转移到_to。
  • 将ID为13的5个代币从_from转移到_to。

在ERC-1155中只有transferFrom,没有transfer。要将其像ERC20转账一样使用,只需将from地址设置为调用该函数的地址即可。

  • 为什么将其称为“安全” -BatchTransferFrom? -有关安全转移规则,请参见下面的第7节。

  • 为什么不返回布尔值?-交易失败时将回滚,与我们之前讨论的SafeERC-20实现相同。

  • 什么是字节数据字段?-就像ERC-777一样,你可以传入任意数据,这些数据也将传递给接收钩子。

    // ERC-1155 function safeBatchTransferFrom( address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data ) external;

4、ERC-1155批量查询余额

在ERC-1155中,与ERC-20 balanceOf对应的调用同样支持批量查询。提醒一下,这是ERC-20版本:

// ERC-20
function balanceOf(address owner) external view returns (uint256);

对于余额查询来说,甚至更简单,我们可以在一个调用中检索多个余额。传入所有者数组,然后传入代币ID数组。

// ERC-1155
function balanceOfBatch(
    address[] calldata _owners,
    uint256[] calldata _ids
) external view returns (uint256[] memory);

例如,给定_ids = [3,6,13]和_owners = [0xbeef ...,0x1337 ...,0x1111 ...],返回值为:

[
  balanceOf(0xbeef...),
  balanceOf(0x1337...),
  balanceOf(0x1111...)
]

5、ERC-1155批量授权

批准授权与ERC-20略有不同。在ERC1155中无需设置授权金额,只需调用setApprovalForAll将操作员设置为批准或未批准即可。

// ERC-1155
function setApprovalForAll(
    address _operator,
    bool _approved
) external;

可以调用isApprovedForAll方法读取当前的授权状态。如你所见,它是全部或全部。你无法定义要批准的代币数量,也不能指定授权哪种代币。

// ERC-1155
function isApprovedForAll(
    address _owner,
    address _operator
) external view returns (bool);

这是有意的设计,目的是保持使用的简单性。你只能批准一个地址的所有内容。如果需要对特定批准进行更精细的控制,请查看EIP-1761。

6、EIP-165支持

如果还不了解EIP-165是什么,请查看此教程。简而言之, EIP165规范了智能合约如何声明其支持的接口。例如,智能合约是否支持接收ERC-1155代币?如果是这样,则相应的supportsInterface功能必须存在,并且对于该合约返回true。

这直接将我们带到了下一个概念:钩子。

7、EIP-1155的接收钩子

有了EIP-165支持,ERC-1155仅支持智能合约的接收钩子。钩子函数必须返回一个预定义的4字节magic值,该值指定为:

bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))

当接收合约返回此值时,假定合约接受转账并知道如何处理ERC-1155代币,那么合约就不再会出现卡死的代币了。

function onERC1155BatchReceived(
    address _operator,
    address _from,
    uint256[] calldata _ids,
    uint256[] calldata _values,
    bytes calldata _data
) external returns(bytes4);

8、ERC-1155 非同质化代币支持

如果代币的发行量为1,那么这种代币本质上是非同质化代币(NFT)。按照ERC-721的标准,你可以定义元数据URL。客户端可以读取和修改该URL,详细内容请参见此处

9、ERC-1155安全转账规则

在前面的说明中,我们已经谈到了一些安全的转账规则。但是,让我们看一下最重要的规则:

  • 必须批准调用方可以消费该_from地址持有的代币,否则调用方必须为_from。
  • 在出现如下状况时,转账交易必须回滚:
    • _to 地址为0。
    • _ids与_values长度不同
    • 代币持有人在_ids中的任何余额都低于_values发送给接收者的相应金额。
    • 发生任何其他错误。

注意:包括钩子在内的所有批处理功能也作为不带批处理的版本存在。这样做是出于提高gas效率的考虑,考虑仅转移一种资产仍可能是最常用的方式。为了简单起见,我们省略了它们。名称相同,只需删除Batch前缀即可。

10、基于ERC-1155的航空代币实现

我们利用文档齐备并且经过审核的Openzeppelin合约库来实现基于ERC-1155的航空代币。通过npm安装它们或直接在Remix中导入Github URL。可以在此处查看Openzeppelin ERC-1155的文档。

我们之前的航空公司示例可以这样实现:

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

contract AirlineTokens is ERC1155 {
    address public governance;
    uint256 public airlineCount;
    
    modifier onlyGovernance() {
        require(msg.sender == governance, "only governance can call this");
        
        _;
    }

    constructor(address governance_) public ERC1155("") {
        governance = governance_;
        airlineCount = 0;
    }
    
    function addNewAirline(uint256 initialSupply) external onlyGovernance {
        airlineCount++;
        uint256 airlineTokenClassId = airlineCount;

        _mint(msg.sender, airlineTokenClassId, initialSupply, "");        
    }
}

这就是我们所需要的。现在可以调用:

AirlineTokens.safeBatchTransferFrom(
  myBuyerAddress, sellerAddress, 
  [airlineId1, airlineId2, airlineId3], 
  [firstFlightPrice, secondFlightPrice, thirdFlightPrice], 
  ''
);

一次交易就可以支付各航空公司的代币。棒极了!


原文链接:ERC-1155多重代币剖析与实战 — 汇智网

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
ERC20接入Uniswap教程【DeFi】
Uniswap是基于以太坊的去中心化数字加密货币交易协议,它为代币持有者提供了简洁的接口来将一种ERC20代币兑换为另一种,并且交易所需的gas成本很低。区块链开发者可以自己的ERC20代币接入Uniswap以增强其流动性。在这个教程中,我们将学习如何将一个ERC20代币接入Uniswap协议,并且在教程的最后提供完整的实现源代码。用自己熟悉的语言学
Stella981 Stella981
3年前
Fabtoken
HyperledgerFabric2.0(alpha)中有一个新特性:Fabtoken,可以原生支持数字加密货币的发行与管理。我们都知道以太坊的ERC20标准可以用来在以太坊区块链上创建数字加密代币,现在有了Fabtoken,开发者使用HyperledgerFabric也可以轻松实现数字加密货币的发行、转账等功能了!HyperledgerF
Wesley13 Wesley13
3年前
NEO从源码分析看UTXO交易
_0x00前言_社区大佬:“交易是操作区块链的唯一方式。”_0x01交易类型_在NEO中,几乎除了共识之外的所有的对区块链的操作都是一种“交易”,甚至在“交易”面前,合约都只是一个小弟。交易类型的定义在Core中的TransactionType中:源码位置:neo/Core/TransactionType
Stella981 Stella981
3年前
Android蓝牙连接汽车OBD设备
//设备连接public class BluetoothConnect implements Runnable {    private static final UUID CONNECT_UUID  UUID.fromString("0000110100001000800000805F9B34FB");
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这