1,摘要

ERC1410为STO环境中使用的一个以太坊协议标准。辉哥着眼于深度理解和编码实现,从以下几个方面阐述对ERC1410的理解。
1) ERC1410和ERC1411(ERC1400),ERC1404的区别
2)同质化通证,非同质化通证,部分同质化通证的区别
3)ERC1410标准的数据结构分析
4) ERC1410的接口函数分析
5) ERC1410的场景尝试
6) 代码部署和测试

2, ERC1410和ERC1411(ERC1400),ERC1404的区别

ERC1410标准由 Gosselin, Adam Dossa, Pablo Ruiz 和 Fabian Vogelsteller 撰写,其中 Gosselin 和 Dossa 为 Polymath 工作,就是那个发布ST20,帮助资产实现证券化通证的平台公司。
ERC1410是一种以太坊上实现STO的技术方案,它兼容ERC20和ERC777标准的证券型通证发行标准,引入了部分同质化通证(Partially Fungible Token Standard)的概念。
它在GITHUB的地址为ERC 1410: Partially Fungible Token Standard #1410。

ERC1400同ERC1411是同一个标准,现在在GITHUB上已经把他们合并了。ERC1411(ERC1400)则是继承ERC1410标准,增加了证券相关业务会使用到的函数:证券增发,相关法律文件存储等。
它在GITHUB的地址为ERC 1400: Security Token Standard #1411。

ERC1404是指简单的受限代币标准,ERC-1404则在ERC-20标准的基础上,添加了两种函数。
detectTransferRestriction:此函数是发行者强制执行通证传输的限制逻辑。例子包括,(1)检查通证接收者是否在白名单内,(2)检查发送者的通证是否在锁定期内被冻结等等。该函数实现仅面向发行者,另外,第三方可以公开调用该函数来检查转移的预期结果。因为这个函数会返回一个uint8代码,所以它允许函数调用者知道传输失败的原因,并将其报告给相关的对方。
messageForTransferRestriction:这个函数实际上是一个“消息”访问器,它负责以人类可阅读的方式解释一笔交易为什么会被限制。通过规范消息查找,开发者授权用户界面构建器,有效地向用户报告错误。
它在GITHUB的地址为https://github.com/ethereum/EIPs/issues/1404。

3,同质化通证(FT),非同质化通证(NFT),部分同质化通证(PFT)的区别

ERC1410引入了部分同质化通证(Partially Fungible Token Standard)的概念,在此之前介绍下同质化通证(FT),非同质化通证(NFT)的概念。
所有的ERC20 Token都是“同质化通证”(Fungible Token,简称FT),同一通证内两个相等单位的Token并无差别。这个类似于美元,作为一般等价物,假设都是真钞,你手里的美元和我手里的美元在购物能力上并无区别。
ERC721 Token都是“非同质化通证”(Non-Fungible Token,简称NFT)。非同质代表独一无二,谜恋猫为例,每只猫都被赋予拥有基因,是独一无二的(一只猫就是一个NFTs),猫之间是不能直接替换的。
非同质性其实广泛存在于我们的生活中,如图书馆的每一本,宠物商店的每一只宠物,歌手所演唱的歌曲,花店里不同的花等等,因此ERC721合约必定有广泛的应用场景,例如房地产,画作等上链具有广泛的意义。
ERC1410 Token是部分可替代通证(Partially Fungible Token,简称PFT)就是兼具了可替代性和不可替代性2种属性的通证形态。它可以把TOKEN跟证券对等起来,可以做security token的一些功能。ERC1410标准引入了“Tranche”的名字,在证券行业中通常翻译为“分级”(例如AAA级、AA级、次级),目的是将不同的通证持有者的账户内Token分成不同的tranches级别。举个例子来说,辉哥发起主导了一个名为“BIG STO PROGRAMME”的项目,由辉哥,欧阳和ELLA小姐姐一起参与,并且已经经过了天使轮(尖晶资本投资),A轮(IDG资本)参与,项目发展不错,正准备到美国做STO申请。那么,创始团队(创始股),尖晶资本(天使轮),IDG资本(A轮)这些投资方对应的价格,基金到期时间都不相同,可以定义tranches级别分别为1级,2级,3级等。
这3级的TOKEN具有相同性和不同性,后面场景尝试的时候会深入分析。

4,ERC1410标准的数据结构分析

1,TOKEN总供应量

uint256 public totalSupply;

2,TOKEN名称

string public name;

3,TOKEN标识

string public symbol;

4,覆盖所有投资人所持通证的每个账户地址下的通证余额总额

// Mapping from investor to aggregated balance across all investor token sets

mapping (address => uint256) balances;

5, 投资人到分级份额Tranche[]的映射
// Mapping from investor to their tranches

mapping (address => Tranche[]) tranches;

// Represents a fungible set of tokens.
struct Tranche {uint256 amount;bytes32 tranche;
}
6, trancheToIndex-分级份额索引
// Mapping from (investor, tranche) to index of corresponding tranche in tranches
//三维数组,就是在分级份额Tranches映射(investor, tranche) 到对应分级份额的索引(index)

mapping (address => mapping (bytes32 => uint256)) trancheToIndex;

7,交易员针对tranche,的授权状态
// Mapping from (investor, tranche, operator) to approved status
//四维数组,就是三维数组(investor, tranche, operator)的授权状态

mapping (address => mapping (bytes32 => mapping (address => bool))) trancheApprovals;

8,交易员针对投资人的授权状态
// Mapping from (investor, operator) to approved status (can be used against any tranches)
//三维数组,就是 投资人对应的操作员(investor, operator)的授权状态

mapping (address => mapping (address => bool)) approvals;

5,ERC1410的接口函数分析

5.1 与tranche有关的查询接口

5.1.1 查询某个账户下指定 tranche 的余额:

function balanceOfByTranche(bytes32 _tranche,address _tokenHolder) external view returns (uint256);

查询某个账户下所有的tranches:

function tranchesOf(address _tokenHolder) external view returns (bytes32[]);

5.2 与tranche有关的转账接口

5.2.1 从调用者的指定tranche转指定金额到目的账户

 function sendByTranche(bytes32 _tranche,address _to,uint256_amount,bytes _data) external returns (bytes32);

表示上述接口表示从调用者的指定tranche转指定金额到目的账户。

  • 如果转账交易不能完成,函数必须revert;
  • 如果转账成功,必须emit SentByTranche event;
  • 如果转账成功但接收者的tranche与发送者的tranche不同,则必须emit ChangedTranche event;

返回值为目的账户接受此次转账的tranche;

最后一个参数_data,可以将目标tranche直接用此参数指定,或存放任何与该交易相关的数据,比如授权信息。

5.2.2 从指定的多个tranches往多个目标地址进行转账。

function sendByTranches(bytes32[] _tranches,address[] _tos,uint256[] _amounts,bytes _data) external returns (bytes32);

上述接口是sendByTranche接口的升级版本,从指定的多个tranches中,往多个目标地址进行转账。

  • 如果转账交易不能完成,函数必须revert;
  • 如果转账成功,必须emit SentByTranche event;
  • 如果转账成功但接收者的tranche与发送者的tranche不同,则必须emit ChangedTranche event

sendByTranche、sendByTranches接口均为交易发起者(msg.sender)对自有账户的操作。

5.2.3 交易员转账特定Tranche

ERC1410基于 ERC777继承了交易员(operator)的相关概念,允许某个交易员代表某个账户持有者基于tranche进行转账。operatorSendByTranche和operatorSendByTranches就是该类型接口。

function operatorSendByTranche(bytes32 _tranche,address _from,address _to,uint256 _amount,bytes _data,bytes _operatorData) external returns (bytes32);
  • 如果一个未被授权(isOperatorForTranche)的地址调用,函数必须revert;
  • 如果转账成功,则必须emit SentByTranche event;
  • 如果转账成功且接收者的tranche与发送者的tranche不同,则必须emit ChangedTranche event。

5.2.4 交易员转账多个Tranches:

function operatorSendByTranches(bytes32[] _tranches,address _from,address _to,uint256[] _amounts,bytes _data,bytes _operatorData) external returns (bytes32[]);
  • 如果一个未被授权(isOperatorForTranche)的地址调用,函数必须revert;
  • 如果转账成功,则必须emit SentByTranche event;
  • 如果转账成功且接收者的tranche与发送者的tranche不同,则必须emit ChangedTranche event。

5.3 默认tranche管理

5.3.1 设定默认Tranches(setDefaultTranches)

为了保证与ERC777、ERC20的兼容性,当调用send时,需要决定从哪个或哪几个tranches中转出。为解决这个问题,可以指定某一个或某几个tranches为默认。

function setDefaultTranche(bytes32[] _tranches) external;

设置默认tranches,这样在调用send时,将从default tranches中转账。

5.3.2 获取默认Tranches(getDefaultTranches)

function getDefaultTranches(address _tokenHolder) external view returns (bytes32[]);

获得某个账户的默认tranches。如果返回值为空,则调用send会抛出异常。如果返回多个,则可以按照某种策略进行转出。

5.3.3 交易员(Operator)相关接口

交易员可以被授权操作:

  • 所有账户的所有tranches
  • 所有账户的某个特定的tranche
  • 某个特定账户的所有tranches(包括现在与未来的)
  • 某个特定账户的特定tranche

5.3.3.1 defaultOperatorsByTranche

function defaultOperatorsByTranche(bytes32 _tranche) external view returns (address[]);

返回具有所有账户的某个特定tranche的默认操作员列表。

5.3.3.2 authorizeOperatorByTranche

function authorizeOperatorByTranche(bytes32 _tranche,address _operator) external;

消息发送者授权给某个交易员某个特定tranche的操作权。每次被调用,必须emit AuthorizedOperatorByTranche event。

5.3.3.3 revokeOperatorByTranche

function revokeOperatorByTranche(bytes32 _tranche,address _operator) external;

消息发送者撤销某个交易员对某个特定tranche的操作权。每次被调用,必须emit RevokedOperatorByTranche event。
(注: 此Operator仍有可能通过defaultOperatorsByTranche或defaultOperators拥有对此tranche的操作权。)

5.3.3.4 isOperatorForTranche:

function isOperatorForTranche(bytes32 _tranche,address _operator,address _tokenHolder) external view returns (bool);
查询_operator是否是某个账户特定tranche的操作员。

6,ERC1410的场景尝试

回到文章前面章节的故事,辉哥发起主导了一个名为“BIG STO PROGRAMME”的项目,由辉哥,欧阳和ELLA小姐姐一起出资参与,并且已经完成了天使轮(尖晶资本投资),A轮(IDG资本),项目发展不错,正准备到美国做STO申请。
我们假设以下为对应的合格投资人钱包地址:

辉哥地址:0xD1F7922e8b78cBEB182250753ade8379d1E09949
欧阳地址:0x17b1177E0491D25a13a8329a8D2C46621b6ca19F
ELLA地址:0x3D7DfB80E71096F2c4Ee63C42C4D849F2CBBE363
尖晶资本地址:0x8fc02f03c15179f8C6D37C3a29FE7A338DC68192
IDG资本地址:0xcE689dBB962DbF45534Af13e4414cCB2dFC78c30
交易员: 0xDD55dA111fBfcc671966D138dE7DFA249a6e76cC

我们假设创始团队(创始股),尖晶资本(天使轮),IDG资本(A轮)这些投资方对应的价格,基金到期时间都不相同,可以定义tranches级别分别为1级,2级,3级等。

tranche:
00000000000000000000000000000001 创始团队
00000000000000000000000000000002 天使轮
00000000000000000000000000000003 A轮

6.1 创始团队发起原始TOKEN

“ BIG STO PROJECT”项目,由辉哥/欧阳/ELLA创始发起,分配总额度和TRANCHE属性。
根据参与3人的投入的资金量,总发行量为1000万,由辉哥账号创建,分配份额如下:辉哥 400万,欧阳 300万,ELLA 300万。
1)首先创建PartialFungibleToken合约,设置初始属性如下:
totalSupply = 0;
name = “Big STO Project”;
symbol = “BST”;
2)调用接口增发1000万TOKEN。

mint("00000000000000000000000000000001", "0xD1F7922e8b78cBEB182250753ade8379d1E09949", "10000000,000000000000000000", "the founding team share tranche")

3) 辉哥转发给欧阳,ELLA对应份额

sendTranche("00000000000000000000000000000001", "0x17b1177E0491D25a13a8329a8D2C46621b6ca19F","3000000,000000000000000000", "创始团队欧阳份额,1级tranche") ;
sendTranche("00000000000000000000000000000001", "0x3D7DfB80E71096F2c4Ee63C42C4D849F2CBBE363","3000000,000000000000000000", "创始团ELLA份额,1级tranche") ;

6.2 尖晶资本参与天使轮

尖晶资本参与天使轮,再发行200万份额,其中辉哥占有100万,尖晶占有100万,锁仓1年;跟辉哥签订对赌条约,公司营收在2018年达到1000万元,设置操作员账号质押辉哥TOKEN份额。
1) 增发200万

mint("00000000000000000000000000000002", "0xD1F7922e8b78cBEB182250753ade8379d1E09949", "200000,000000000000000000", "the spinel captital joined in.")

2)尖晶占有100万; 辉哥占有100万,有业绩对赌;

sendTranche("00000000000000000000000000000002", 0x8fc02f03c15179f8C6D37C3a29FE7A338DC68192","1000000,000000000000000000", "尖晶资本参与天使轮,锁仓1年") ;

3)辉哥业绩对赌,TOKEN指定交易员授权;

authorizeOperator("0xDD55dA111fBfcc671966D138dE7DFA249a6e76cC")

4)该项目进展顺利,对赌失效
该项目进展顺利,对赌失效,辉哥要撤回授权。

revokeOperator("0xDD55dA111fBfcc671966D138dE7DFA249a6e76cC")

6.3 IDG资本参与A轮

该项目到2018年11月份就完成了全年目标,项目发展不错。IDG资本决定参与A轮。再发行200万TOKEN,其中辉哥占有50万,尖晶占有50万,IDG占有100万。

1) 增发200万TOKEN

mint("00000000000000000000000000000001", "0xD1F7922e8b78cBEB182250753ade8379d1E09949", "2000000,000000000000000000", "IDG CAPITAL joined in!")
sendTranche("00000000000000000000000000000003", 0x8fc02f03c15179f8C6D37C3a29FE7A338DC68192","500000,000000000000000000", "尖晶资本参与A轮,锁仓1年") ;
sendTranche("00000000000000000000000000000003", "0xcE689dBB962DbF45534Af13e4414cCB2dFC78c30","1000000,000000000000000000", "IDG资本参与A轮,锁仓1年") ;

2)跟辉哥对赌2级股权100万
IDG资本跟辉哥有对赌条款,约定到2018年年底总营收能到1500万人民币,把辉哥天使轮对应的TOKEN质押,授权交易员。

authorizeOperatorTranche("00000000000000000000000000000002", " 0xDD55dA111fBfcc671966D138dE7DFA249a6e76cC")

结果项目进展又特别顺利,对赌失效,辉哥撤回授权。

revokeOperatorTranche("00000000000000000000000000000002", " 0xDD55dA111fBfcc671966D138dE7DFA249a6e76cC")

6.4 尖晶质押50万2级TOKEN,找IDG融资5000万,后续转让100万给IDG,退出该项目

authorizeOperatorTranche("00000000000000000000000000000002", " 0xDD55dA111fBfcc671966D138dE7DFA249a6e76cC")

后来尖晶资本和IDG资本代表人到交易所办理了转让交割手续。

operatorSendTranche("00000000000000000000000000000002", "0x8fc02f03c15179f8C6D37C3a29FE7A338DC68192", "0xcE689dBB962DbF45534Af13e4414cCB2dFC78c30", "500000,000000000000000000", "尖晶资本转让2级TOKEN给IDG资本", "由Polyman交易所交易员Mask办理交割")

6.5 ELLA退出运营,销毁对应代币

ELLA因为要跟男票一起去苏南农村做ELLA山庄,享受田园生活。所以申请退出“BIG STO PROJECT”运营。公司回购300万,销毁对应代币。

burn("00000000000000000000000000000001", "0x3D7DfB80E71096F2c4Ee63C42C4D849F2CBBE363", "3000000,000000000000000000", "ELLA退出运营,缩股销毁TOKEN。")

7,代码部署和测试

故事讲完了,接下来就是部署测试。
这部分的代码量有点大,辉哥就不再全部列出了。有需要的小伙伴可以去知识星球下载来运行。
该工程代码还未经过商用测试,只作为练习使用。

8,参考

1)《币圈乱象终结者! 以太坊新STO方案详解》
2)ERC 1400: Security Token Standard #1411
3)ERC 1410: Partially Fungible Token Standard #1410
4)Security Token Standard
5)ERC-1404: Simple Restricted Token Standard
6)Protocol for security token for Transfer Agents Powered by OKTO
7)Security Token(证券型代币)标准 – ERC1400/ERC1410

第三十一课 ERC1410标准从分析到代码实现相关推荐

  1. 新版标准日本语中级_第三十一课

    语法   1. 男性用语:在男性之间的对话中,称呼.句尾形式.打招呼或应答等有时会使用一些很有特点的说法.这些说法比较随便,只用于关系亲近的人之间.   1) 称呼:称自己おれ,称对方おまえ. おれは ...

  2. 新版标准日本语初级_第三十一课

    语法   1. 小句1(动词基本形/ない形)と,小句2:~と用在表述恒常性状态.真理.反复性状态.习惯等内容的复句里,表示小句1是小句2的条件. このボタンを押すと,電源が入ります(按下这个钮,电源就 ...

  3. 【问链财经-区块链基础知识系列】 第三十一课 Fabric版本变迁之路从1.1-1.4

    Fabric个版本更新内容 V1.1 ・Node.js链代码支持 - 开发人员现在可以使用世界上最流行的编程语言最流行的框架编写链代码 ・基于通道的事件服务 - 使客户端能够在每个通道的基础上订阅阻止 ...

  4. 爱情三十一课,先信自己

    我们每个人一生都在迎接两个问题的考验:其一,我是否值得被爱:其二,我是否可以成功. 如果某人在这两个问题上的自我认识是"值得"和"可以",无论境遇多遭,都可以获 ...

  5. 前端学习第三十一课(ES6简介和babel的使用)

    目录 1.ECMAScript简介 1.1 ES6 与 ECMAScript 2015 的关系 2.Babel转码器 2.1 安装babel 2.2 配置文件.babelrc 2.3  命令行转码 2 ...

  6. 第三十一课.矩阵胶囊与EM路由

    矩阵胶囊的前向计算 矩阵胶囊在向量胶囊的基础上改变了胶囊的表示方式,矩阵胶囊由激活概率与姿态矩阵两部分构成一个元组单位.激活概率用于表示矩阵胶囊被激活的概率,姿态矩阵用于表示胶囊的姿态信息.在向量胶囊 ...

  7. AGG第三十一课 pattern_perspective样式透明

    摘自:http://article.gmane.org/gmane.comp.graphics.agg/2911/ > I've read the pattern_perspective.cpp ...

  8. python第三十一课--递归(3.递归的弊端)

    演示递归的弊端: def mySum(num):if num == 1:return 1return num+mySum(num-1)mySum(998) [注意]:递归可以解决绝大多数循环能干的事情 ...

  9. 【机器人学习】三自由机器人正逆运动学分析+matlab代码+直线轨迹与圆轨迹

    下载链接:https://download.csdn.net/download/yjw0911/85111527 clc clear all close all M=300;l=150;L=50; t ...

最新文章

  1. smack+openfire实现Android实时通信(实现大部分基本功能)
  2. 《CLR via C#》读书笔记 之 参数
  3. 百度地图移动端开发和ArcGIS for Android 开发入门
  4. Java SSM篇3——Mybatis
  5. android+残留软件包名,关于使用pm hide伪卸载系统软件的一些包名
  6. 数据结构与算法笔记(三) 线性表(链式描述) 链表
  7. entity framework扩展实战,小项目重构,不折腾
  8. Android UI学习之Dialog
  9. Linux命令学习:Linux中more和less命令以及查找用法
  10. 收银系统连接不上数据服务器,收银系统服务器数据库
  11. 记一次瞬时网络挂起和XMLHttpRequest: 网络错误 0x2eff
  12. LQBv13-Python:猜年龄
  13. Cortex-A8处理器编程(上)
  14. ORA-12154: TNS: 无法解析指定的连接“/one card”应用程序中的服务器错误
  15. 股票查询:每个客户净买入金额排名前3的股票
  16. JVM基础知识---对象的创建过程
  17. c# 利用ADODB连接ORACLE数据库
  18. 现代远程教育入学指南(石油大学)--高等数学(二)在线作业
  19. 非洛达芯片检测聚合教程NOT AIROHA CHIP
  20. 教你简单4步,快速去除电视机广告

热门文章

  1. 重新审视Visio的本质
  2. linux桌面小程序开发日记3(pyqt5+yolov5)
  3. 数据库查询_同时选修了两门课的学生姓名、学号
  4. 国内外比较出名的聚合路由器都有哪些?
  5. 2010年5月27日俱乐部晚场活动,“iPhone应用成功经验分享”主题研讨活动
  6. 静态包含和动态包含的区别
  7. 私人定制YX3系列高效节能电动机:这才是大腕儿!
  8. 一年手机信息安全囧事大调查,你有没有中招
  9. Android 11省电模式开启
  10. (9) iphone 开发 AppSettings , 系统setting与应用程序setting间的数据控制