2019独角兽企业重金招聘Python工程师标准>>>

我们可以用以太坊智能合约来模拟稀有的收藏品,每一个通证都遵循以太坊ERC-721标准, 它是DieterShirley在2017年末提出的以太坊改进建议书。ERC721可以使智能合约像类似于 ERC20代币一样进行交易, 区别在于,ERC721通证是独一无二的,每一个都有唯一的ID,具有不可取代性。

如果你希望马上开始学习以太坊智能合约和应用开发,可以访问汇智网提供的出色的在线互动教程:

  • ERC721以太坊通证实战
  • 以太坊智能合约和应用开发入门
  • 以太坊去中心化电商DApp实战开发

ERC721约定了一些接口函数,使它在一定程度上符合ERC20代币标准。这么做是为了让现有的 钱包更容易显示代币的基本信息。这些函数可以让符合ERC721标准的智能合约像比特币或者 以太币这样普通的数字加密币一样,通过智能合约编程的方式定义一些功能让用户实现向他人 发送代币或检查账户余额等操作。

这是一个简明的ERC721智能合约声明:

contract ERC721 {//与ERC20兼容的接口function name() constant returns (string name);function symbol() constant returns (string symbol);function totalSupply() constant returns (uint256 totalSupply);function balanceOf(address _owner) constant returns (uint balance);//所有权相关的接口function ownerOf(uint256 _tokenId) constant returns (address owner);function approve(address _to, uint256 _tokenId);function takeOwnership(uint256 _tokenId);function transfer(address _to, uint256 _tokenId);function tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId);//通证元数据接口function tokenMetadata(uint256 _tokenId) constant returns (string infoUrl);//事件event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
}

name - 名称

该函数应当返回通证的名称。 例如:

contract MyNFT {function name() constant returns(string name){return "My Non-FungibleToken";  }
}

Symbol - 符号

该函数应当返回通证的符号,它有助于提高与ERC20的兼容性。例如:

contract MyNFT {function symbol() constant returns(string symbol){return "MNFT";}
}

totalSupply - 总发行量

该函数应当返回区块链上供应的通证总数量,该数量不一定是固定不变的。 例如:

contract MyNFT {//想发行多少取决于你 ;)uint256 private totalSupply = 1000000000;function totalSupply() constant returns (uint256supply){return totalSupply;}
}

balanceOf - 余额

该函数用于查询某一地址里的通证余额。例如:

contract MyNFT {mapping(address => uint) privatebalances;function balanceOf(address _owner) constant returns(uint balance){ return balances[_owner];}
}

下面这些函数定义了合约如何处理通证的所有权及如何转移所有权。其中最重要的两个函数 是获取(takeOwnership)和转账(transfer),用来实现用户之间的通证流转,就像银行的提款 和汇款功能。

ownerOf - 持币人

该函数返回通证持有人的地址。因为每一个ERC721通证都是不可替代的,因此可以在区块链上 唯一的地址找到,我们可以用通证的ID来确定其持有人。

contract MyNFT {mapping(uint256 => address) privatetokenOwners;mapping(uint256 => bool) private tokenExists;function ownerOf(uint256 _tokenId) constant returns (address owner) {require(tokenExists[_tokenId]);return tokenOwners[_tokenId];}
}

approve - 授权

该函数用来授权给另一主体代表持有人进行通证转移操作。例如,假设Alice有一个ERC721通证,她可以 调用approve函数来授权给她的朋友Bob,然后Bob就可以代表Alice行使通证持有人的权利。

contract MyNFT {mapping(address => mapping (address=> uint256)) allowed;function approve(address _to, uint256 _tokenId){require(msg.sender ==ownerOf(_tokenId));require(msg.sender != _to);allowed[msg.sender][_to] = _tokenId;Approval(msg.sender, _to, _tokenId);}
}

takeOwnership - 获取

该函数类似于取款功能,一个外部主体通过调用takeOwnership函数来从另一个用户的账户 中提取ERC721通证。

因此,在一个用户被(其他人)授权拥有一定数量的通证的情况下,可以通过该功能将这部分 通证从另一个用户的账户中提取出来。

contract MyNFT {function takeOwnership(uint256_tokenId){require(tokenExists[_tokenId]);address oldOwner = ownerOf(_tokenId);address newOwner = msg.sender;require(newOwner != oldOwner);require(allowed[oldOwner][newOwner] == _tokenId);balances[oldOwner] -= 1;tokenOwners[_tokenId] = newOwner;balances[oldOwner] += 1;Transfer(oldOwner, newOwner,_tokenId);}
}

transfer - 转账

另一种转移通证的方法时使用transfer函数。转账(transfer)功能可以让用户将通证发给另一个用户, 类似于操作比特币这样的加密数字货币。然而,只有在汇出账户之前授权过汇入账户持有其通证的 情况下,才可以进行转账。

contract MyNFT {mapping(address => mapping(uint256 => uint256)) private ownerTokens;function removeFromTokenList(address owner, uint256 _tokenId) private {for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ownerTokens[owner][i] = 0;}}function transfer(address _to, uint256 _tokenId){address currentOwner = msg.sender;address newOwner = _to;require(tokenExists[_tokenId]);require(currentOwner == ownerOf(_tokenId));require(currentOwner != newOwner);require(newOwner != address(0));removeFromTokenList(_tokenId);balances[oldOwner] -= 1;tokenOwners[_tokenId] = newOwner;balances[newOwner] += 1;Transfer(oldOwner, newOwner, _tokenId);}
}

tokenOfOwnerByIndex - 通证检索

这个函数是可选的,但推荐你实现它。

每一个ERC721通证的持有者可以同时持有不止一个通证,因为每个通证都有唯一的ID,但是,要跟踪某个用户持有的 通证可能就会比较困难。为此,合约需要记录每个用户持有的每个通证。通过这种方式,用户可以 通过索引清单检索其拥有的通证。通证检索(tokenOfOwnerByIndex)函数可以通过这种方式追溯某一特定的通证。

contract MyNFT {mapping(address => mapping(uint256 => uint256)) private ownerTokens;function tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId){return ownerTokens[_owner][_index];}
}

tokenMetaData - 通证元数据

就像我们之前所说的,使物品具有不可替代性的是它们独一无二的特质。美元和网球卡不可替代, 因为它们的特征不同。但是,在区块链上将这些区分每个通证的特征储存下来成本很高,也不推荐这么做。 为了解决这个问题,我们可以储存每个通证的引用(references),例如IPFS哈希或HTTP(S)链接,这些 引用,被称作元数据。元数据是可选的。

tokenMetaData函数应当返回通证的元数据,或者通证数据的链接。

contract MyNFT {mapping(uint256 => string) tokenLinks;function tokenMetadata(uint256 _tokenId) constant returns (string infoUrl) {return tokenLinks[_tokenId];}
}

当调用合约方法的时候,事件将会被触发,并且一旦被触发就会向监听系统传播。外部应用可以监听区块链 中的事件,一旦接收到区块链中的事件被触发,监听系统就可以通过事件中包含的信息执行逻辑程序。 ERC721标准定义了下面两个事件。

Transfer - 转账

当一个通证的所有权从一个用户转移到另一个时,将触发该事件,事件的信息包括汇出账户、汇入账户和通证ID。

contract MyNFT {event Transfer(address indexed _from,address indexed _to, uint256 _tokenId);}

Approval - 批准

当一个用户允许另一个用户持有其通证的时候(例如启用“授权”功能的时候),该事件就会被触发,事件的信息中 包含这些通证现在的持有账户、被授权账户以及通证ID。

contract MyNFT {event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
}

完整的源代码在这里。

原文:ERC721剖析:收藏品类的以太坊智能合约

转载于:https://my.oschina.net/u/3794778/blog/1808568

ERC721藏品合约详解,附代码实现相关推荐

  1. 动态规划---01背包问题--Dp(详解附代码)

    一.动态规划 代表一类问题(最优子结构或子问题最优性)的一般解法,是设计方法或者策略,不是具体算法 本质:递推,核心是找到状态转移的方式,写出dp方程. 解决问题:交叉,重叠子问题(最优子问题) 形式 ...

  2. 【排序】堆排序详解 附代码

    按照国际惯例,开篇前先简单介绍(吹一波)堆排序(Heapsort).Heapsort是一种优秀的排序算法(个人感觉基本排序算法中仅次于快速排序),时间复杂度为O(nlgn),同时,Heapsort具有 ...

  3. 各种进制转换(二,八,十,十六进制间转换)详解附代码

    进制转换 原理 进制转换是人们利用符号来计数的方法.进制转换由一组数码符号和两个基本因素"基数"与"位权"构成. 基数是指,进位计数制中所采用的数码(数制中用来 ...

  4. 前序遍历、中序遍历、后序遍历层序遍历详解附代码(数据结构C语言)

    目录 (1)前序遍历 (DLR) 递归算法 (2)中序遍历 (LDR) 递归算法 (3)后序遍历 (LRD) 递归算法 (4)层序遍历 队列实现方法 层序遍历的定义: 实现方法: 代码实现 结果截图 ...

  5. Numpy学习笔记(二):argmax参数中axis=0,axis=1,axis=-1详解附代码

    文章目录 1.argmax和max函数区别 2.axis=0/axis=1/axis=-1的区别 3.具体代码分析 ---3.1一维数组 ---3.2二维数组 ---3.3三维数组 1.argmax和 ...

  6. 随机分布嵌入(RDE)框架详解附代码

    介绍 研究了好一阵子马欢飞老师在PNAS上发的文章,下面附上个人的研究心得与代码与大家讨论. 在基于非线性系统的理论基础上,延迟嵌入理论以及广义嵌入理论等相空间重构的理论基础上,观察者便有可能从一个观 ...

  7. c++实现贪吃蛇详解(附代码)

    文章目录 前言 一.运行界面 二.类的大致抽象 三.关于一些问题的思考 四.最后一些想说的 五.代码 前言 经过一个多月的学习,又加深了对c++的理解,所以接下来,就和大家分享一下,一个月学习c++的 ...

  8. 【大道至简】机器学习算法之EM算法(Expectation Maximization Algorithm)详解(附代码)---通俗理解EM算法。

    ☕️ 本文来自专栏:大道至简之机器学习系列专栏

  9. 目标检测模型的评估指标mAP详解(附代码)

    https://zhuanlan.zhihu.com/p/37910324 对于使用机器学习解决的大多数常见问题,通常有多种可用的模型.每个模型都有自己的独特之处,并随因素变化而表现不同. 每个模型在 ...

最新文章

  1. SAP 序列号里'主批次'与'库存批次'不同,如何修改?
  2. python编写安装脚本_2. 编写安装脚本
  3. Java基础学习需要掌握哪些内容?
  4. nginx 配置https_nginx 配置https
  5. 根据文件前四个字节判断文件类型(centos 7)
  6. 问题三十六:ray tracing中的Inverse Mapping(3)——圆盘Inverse Mapping
  7. 预测接口表:MRP_FORECAST_INTERFACE
  8. iOS 不同数据类型存入可变数组
  9. 《信息安全系统设计基础》第三周学习总结
  10. 【转】Pycharm的激活
  11. 【线段树求逆序数】【HDU1394】Minimum Inversion Number
  12. 头文件交叉声明的解决办法
  13. jmeter录制脚本及操作数据库
  14. 遗传算法matlab_遗传算法和MATLAB (更新中)
  15. C#将大量数据批量写入Excel中
  16. (九)C#之WinForm程序设计-升级版文本编辑器
  17. 桌面widget详解(四)——桌面音乐播放器(实战)
  18. 基于Windows8与Visual Studio11开发第一个内核驱动程序
  19. 【向生活低头】将flv格式文件转为mp4
  20. 怎么让网站变灰色,我们该怎么做?

热门文章

  1. 如何用servle和c3p0-DBUtils实现用户登录功能
  2. springboot pom文件添加mysql组件_SpringBoot整合mybatis-plus+druid组件,实现增删改查
  3. java 处理unicode_Java与Unicode
  4. java判断回文用valueof_判断回文数,利用String类
  5. php中怎么让图片没有缓存文件,PHP页面文件缓存,PHP图片缓存实例
  6. Linux3种进程,linux内核获取进程的全路径3种方法
  7. eclipse导入maven项目
  8. 《天天数学》连载28:一月二十八日
  9. 大数据学习笔记37:Hive - 复杂数据类型
  10. 安卓案例:View动画——弹球碰壁