1.imageHash
就是将punk所有图像合在一起的那张图punks.png进行hash得到一个值,并将该值存储到链上,用处就是你可以通过将图像hash然后跟该值对比看图像对不对。这就是它的用处,在代码中它没用。即该图punks.png,在https://github.com/larvalabs/cryptopunks/tree/master/test能得到:


2.函数简单介绍
CryptoPunksMarket
创建10000个token,该合同的拥有者即该合约的部署者owner = msg.sender

setInitialOwner\setInitialOwners
将token初始无偿送给一些用户的函数,只有合同拥有者才能调用这两个函数(if (msg.sender != owner) throw;)当变量allPunksAssigned为false时这两个函数才能调用,这时候其他的函数都不能调用。该两个函数是在合同刚部署时使用的,因为当allPunksAssigned被设为true后,这两个函数将永远不能被调用。即使一个token刚刚送给了别的用户,合同拥有者还是能通过函数setInitialOwner将其拿回,转送给另一个用户

allInitialOwnersAssigned
将变量allPunksAssigned设为true,这样,上面的两个无偿赠送的函数就不能使用了,只能使用下面的其他函数

getPunk
用户还是可以通过这份函数来无偿获得token,不同之处在于:
首先不需要是合同拥有者也能调用这个函数,但是这有那些无主的token才能被get

transferPunk
把自己拥有的token转赠给别的用户

punkNoLongerForSale
把之前标价打算要卖出去的token取消了,就是不打算sell了

offerPunkForSale
把自己的token标一个最低价想要卖出

offerPunkForSaleToAddress
把自己的token标一个最低价想要卖给一个指定的用户

buyPunk
购买那些标价卖出的token

withdraw
将自己临时账户中的钱取出来
enterBidForPunk
进入到某个token的竞标市场,只有出价比之前最高价高时该竞标才回成功,成为最高价

acceptBidForPunk
sell方接受竞标

withdrawBidForPunk
竞标方放弃竞标

3.整个代码的详细介绍

  1. pragma solidity ^0.4.8;
  2. contract CryptoPunksMarket {
  3.  
  4. // 图片的hash值,用于验证图片文件的正确性
  5. string public imageHash = "ac39af4793119ee46bbff351d8cb6b5f23da60222126add4268e261199a2921b";
  6.  
  7. //该合约的拥有者声明
  8. address owner;
  9. //该token的一些定义信息
  10. string public standard = 'CryptoPunks';
  11. string public name;
  12. string public symbol;
  13. uint8 public decimals;
  14. //token的总量声明
  15. uint256 public totalSupply;
  16.  
  17. //下一个被分配的token的索引,从0开始
  18. uint public nextPunkIndexToAssign = 0;
  19. //用于上锁函数
  20. bool public allPunksAssigned = false;
  21. //剩余的能够进行分配的token数量
  22. uint public punksRemainingToAssign = 0;
  23.  
  24. //将token索引映射到拥有者的地址,punkIndexToAddress[0]即得到索引为0的token的拥有者地址
  25. mapping (uint => address) public punkIndexToAddress;
  26.  
  27. //用户所拥有的token的数量
  28. mapping (address => uint256) public balanceOf;
  29.  
  30. //声明卖token的结构体
  31. struct Offer {
  32. bool isForSale;//true即token正在卖出
  33. uint punkIndex;
  34. address seller;//卖方,及其主人
  35. uint minValue; // in ether,卖出最低价
  36. address onlySellTo; //用于设置卖给谁,不设则卖给谁都可以
  37. }
  38.  
  39. //声明竞标token的结构体
  40. struct Bid {
  41. bool hasBid;//是否正在竞标
  42. uint punkIndex;
  43. address bidder;
  44. uint value;
  45. }
  46.  
  47. //通过token索引来查看该token的卖出信息,也可能没有
  48. mapping (uint => Offer) public punksOfferedForSale;
  49.  
  50. //通过token索引来查看该token的最高价竞标信息,也可能没有
  51. mapping (uint => Bid) public punkBids;
  52. //用户的临时账户,存放其卖token的回报或者竞标失败退回的竞标额
  53. mapping (address => uint) public pendingWithdrawals;
  54.  
  55. //用于事件监听
  56. event Assign(address indexed to, uint256 punkIndex);
  57. event Transfer(address indexed from, address indexed to, uint256 value);
  58. event PunkTransfer(address indexed from, address indexed to, uint256 punkIndex);
  59. event PunkOffered(uint indexed punkIndex, uint minValue, address indexed toAddress);
  60. event PunkBidEntered(uint indexed punkIndex, uint value, address indexed fromAddress);
  61. event PunkBidWithdrawn(uint indexed punkIndex, uint value, address indexed fromAddress);
  62. event PunkBought(uint indexed punkIndex, uint value, address indexed fromAddress, address indexed toAddress);
  63. event PunkNoLongerForSale(uint indexed punkIndex);
  64.  
  65. //构造函数,初始化该token
  66. function CryptoPunksMarket() payable {
  67.  
  68. owner = msg.sender;
  69. totalSupply = 10000; //token总数为10000
  70. punksRemainingToAssign = totalSupply; //余量为10000
  71. name = "CRYPTOPUNKS"; // Set the name for display purposes
  72. symbol = "Ͼ"; // Set the symbol for display purposes
  73. decimals = 0; // Amount of decimals for display purposes
  74. }
  75.  
  76. //合约拥有者通过调用该函数将token送给某些用户
  77. function setInitialOwner(address to, uint punkIndex) {
  78. if (msg.sender != owner) throw; //函数调用者必须是合约拥有者
  79. if (allPunksAssigned) throw; //allPunksAssigned要为false
  80. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  81. if (punkIndexToAddress[punkIndex] != to) { //token的主人不能是要送给的用户
  82. if (punkIndexToAddress[punkIndex] != 0x0) {//送出去的token可以收回再送给别的用户
  83. balanceOf[punkIndexToAddress[punkIndex]]--;
  84. } else {
  85. punksRemainingToAssign—; //该token之前没被赠送过,可分配token数减1
  86. }
  87. punkIndexToAddress[punkIndex] = to; //更换token拥有者为to
  88. balanceOf[to]++; //to用户的token拥有总数加1
  89. Assign(to, punkIndex); //事件event Assign,监听到该事件则说明该函数调用成功
  90. }
  91. }
  92.  
  93. //同时将多个token送给多个用户
  94. function setInitialOwners(address[] addresses, uint[] indices) {
  95. if (msg.sender != owner) throw;
  96. uint n = addresses.length;
  97. for (uint i = 0; i < n; i++) {
  98. setInitialOwner(addresses[i], indices[i]);
  99. }
  100. }
  101. //将变量allPunksAssigned设置为true,用以停止上面两个函数的使用,开始下面函数的使用
  102. function allInitialOwnersAssigned() {
  103. if (msg.sender != owner) throw;
  104. allPunksAssigned = true;
  105. }
  106.  
  107. //任何用户都可以通过该函数来获得无主的token
  108. function getPunk(uint punkIndex) {
  109. if (!allPunksAssigned) throw; //allPunksAssigned为true
  110. if (punksRemainingToAssign == 0) throw; //剩下能够分配的token数要大于0
  111. if (punkIndexToAddress[punkIndex] != 0x0) throw; //只能得到无主token
  112. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  113. punkIndexToAddress[punkIndex] = msg.sender;
  114. balanceOf[msg.sender]++;
  115. punksRemainingToAssign--;
  116. Assign(msg.sender, punkIndex); //事件event Assign,监听到该事件则说明该函数调用成功
  117. }
  118.  
  119. // 转赠token
  120. function transferPunk(address to, uint punkIndex) {
  121. if (!allPunksAssigned) throw; //allPunksAssigned为true
  122. if (punkIndexToAddress[punkIndex] != msg.sender) throw; //函数调用者必须是token的主人
  123. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  124. if (punksOfferedForSale[punkIndex].isForSale) { //如果之前想要sell这个token,则先取消sell
  125. punkNoLongerForSale(punkIndex);
  126. }
  127. punkIndexToAddress[punkIndex] = to;
  128. balanceOf[msg.sender]--;
  129. balanceOf[to]++;
  130. Transfer(msg.sender, to, 1); //事件event Transfer,监听到该事件则说明该函数调用成功
  131. PunkTransfer(msg.sender, to, punkIndex); //事件
  132. // Check for the case where there is a bid from the new owner and refund it.
  133. // Any other bid can stay in place.
  134. //查看被赠方是否之前有对该token进行投标,有则取消,并将其投标的金额放进其临时账户中
  135. Bid bid = punkBids[punkIndex];
  136. if (bid.bidder == to) {
  137. // Kill bid and refund value
  138. pendingWithdrawals[to] += bid.value;
  139. punkBids[punkIndex] = Bid(false, punkIndex, 0x0, 0);//清空投标信息,并设置状态为false
  140. }
  141. }
  142.  
  143. //取消之前设置的token卖出信息
  144. function punkNoLongerForSale(uint punkIndex) {
  145. if (!allPunksAssigned) throw; //allPunksAssigned为true
  146. if (punkIndexToAddress[punkIndex] != msg.sender) throw; //函数调用者必须是token的主人
  147. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  148. //清空卖出offer信息,并设置状态为false
  149. punksOfferedForSale[punkIndex] = Offer(false, punkIndex, msg.sender, 0, 0x0);
  150. PunkNoLongerForSale(punkIndex);
  151. }
  152.  
  153. //想将某token卖出,将相应信息写入offer中,用以告知大家
  154. function offerPunkForSale(uint punkIndex, uint minSalePriceInWei) {
  155. if (!allPunksAssigned) throw; //allPunksAssigned为true
  156. if (punkIndexToAddress[punkIndex] != msg.sender) throw; //函数调用者必须是token的主人
  157. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  158. //将相应的信息写入结构体offer中
  159. punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, 0x0);
  160. PunkOffered(punkIndex, minSalePriceInWei, 0x0);//事件PunkOffered,用以告知函数调用成功
  161. }
  162.  
  163. //声明某token想要卖给某个特定的用户
  164. function offerPunkForSaleToAddress(uint punkIndex, uint minSalePriceInWei, address toAddress) {
  165. if (!allPunksAssigned) throw; //allPunksAssigned为true
  166. if (punkIndexToAddress[punkIndex] != msg.sender) throw; //函数调用者必须是token的主人
  167. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  168. //将相应的信息写入结构体offer中
  169. punksOfferedForSale[punkIndex] = Offer(true, punkIndex, msg.sender, minSalePriceInWei, toAddress);
  170. PunkOffered(punkIndex, minSalePriceInWei, toAddress);//事件PunkOffered,用以告知函数调用成功
  171. }
  172.  
  173. //购买在offer中设置为卖出的token
  174. function buyPunk(uint punkIndex) payable {
  175. if (!allPunksAssigned) throw; //allPunksAssigned为true
  176. Offer offer = punksOfferedForSale[punkIndex]; //token的卖出信息
  177. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  178. if (!offer.isForSale) throw; // token的卖出状态要为true
  179. //token指定的卖出用户要是函数调用者或者没有指定卖出用户
  180. if (offer.onlySellTo != 0x0 && offer.onlySellTo != msg.sender) throw;
  181. if (msg.value < offer.minValue) throw; // 你的出价必须大于或等于offer中标出的价格
  182. if (offer.seller != punkIndexToAddress[punkIndex]) throw; //offer中表明的卖方必须还是token的主人
  183.  
  184. address seller = offer.seller;
  185.  
  186. punkIndexToAddress[punkIndex] = msg.sender;
  187. balanceOf[seller]--;
  188. balanceOf[msg.sender]++;
  189. Transfer(seller, msg.sender, 1); //事件Transfer,说明买卖成功
  190.  
  191. punkNoLongerForSale(punkIndex); //清空卖出offer信息
  192. pendingWithdrawals[seller] += msg.value; //将卖出的钱msg.value写入seller的临时账户
  193. PunkBought(punkIndex, msg.value, seller, msg.sender); //事件
  194.  
  195. //如果该函数调用者之前有投标过该token,则取消,并将投标钱放入临时账户中
  196. Bid bid = punkBids[punkIndex];
  197. if (bid.bidder == msg.sender) {
  198. // Kill bid and refund value
  199. pendingWithdrawals[msg.sender] += bid.value;
  200. punkBids[punkIndex] = Bid(false, punkIndex, 0x0, 0);//清空投标信息
  201. }
  202. }
  203.  
  204. //将临时账户中的钱拿出,其实就是要求合约地址send回钱
  205. function withdraw() {
  206. if (!allPunksAssigned) throw; //allPunksAssigned为true
  207. uint amount = pendingWithdrawals[msg.sender];
  208. // Remember to zero the pending refund before
  209. // sending to prevent re-entrancy attacks
  210. pendingWithdrawals[msg.sender] = 0; //清空临时账户
  211. msg.sender.transfer(amount); //合约地址send回钱amount给msg.sender,即合约调用者
  212. }
  213.  
  214. //进入某个token的投标市场
  215. function enterBidForPunk(uint punkIndex) payable {
  216. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  217. if (!allPunksAssigned) throw; //allPunksAssigned为true
  218. if (punkIndexToAddress[punkIndex] == 0x0) throw; //该token要有主
  219. if (punkIndexToAddress[punkIndex] == msg.sender) throw; //该token的主人不是函数调用者
  220. if (msg.value == 0) throw; //投标价格一定要大于0
  221. Bid existing = punkBids[punkIndex]; //之前的最高价的投标信息
  222. if (msg.value <= existing.value) throw; //出的投标价高于之前的最高价时,该投标才成功
  223. if (existing.value > 0) {//之前投标的人的投标价会返回到它的临时账户中
  224. // Refund the failing bid
  225. pendingWithdrawals[existing.bidder] += existing.value;
  226. }
  227. punkBids[punkIndex] = Bid(true, punkIndex, msg.sender, msg.value); //覆盖投标信息
  228. PunkBidEntered(punkIndex, msg.value, msg.sender); //事件
  229. }
  230.  
  231. //接受目前出最高投标价的投标者的投标
  232. function acceptBidForPunk(uint punkIndex, uint minPrice) {
  233. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  234. if (!allPunksAssigned) throw; //allPunksAssigned为true
  235. if (punkIndexToAddress[punkIndex] != msg.sender) throw; //只有token主人才能接受投标
  236. address seller = msg.sender; //卖方地址
  237. Bid bid = punkBids[punkIndex]; //投标信息
  238. if (bid.value == 0) throw; //投标价等于0说明没人投标
  239. if (bid.value < minPrice) throw; //投标价要大于接受投标的最小价格
  240.  
  241. punkIndexToAddress[punkIndex] = bid.bidder;
  242. balanceOf[seller]--;
  243. balanceOf[bid.bidder]++;
  244. Transfer(seller, bid.bidder, 1);
  245. //成功后,无论是卖出offer还是投标bid信息都要被清空,offer中的主人会换成投标者
  246. punksOfferedForSale[punkIndex] = Offer(false, punkIndex, bid.bidder, 0, 0x0);
  247. uint amount = bid.value;
  248. punkBids[punkIndex] = Bid(false, punkIndex, 0x0, 0);
  249. pendingWithdrawals[seller] += amount; //seller赚到的钱放入临时账户
  250. PunkBought(punkIndex, bid.value, seller, bid.bidder);//事件
  251. }
  252.  
  253. //取消对某个token的投标
  254. function withdrawBidForPunk(uint punkIndex) {
  255. if (punkIndex >= 10000) throw; //punkIndex即token的索引要小于token总数10000
  256. if (!allPunksAssigned) throw; //allPunksAssigned为true
  257. if (punkIndexToAddress[punkIndex] == 0x0) throw; //该token要有主
  258. if (punkIndexToAddress[punkIndex] == msg.sender) throw; //该token的主人不是函数调用者
  259. Bid bid = punkBids[punkIndex]; //投标信息
  260. if (bid.bidder != msg.sender) throw; //投标者即函数调用者
  261. PunkBidWithdrawn(punkIndex, bid.value, msg.sender); //事件
  262. uint amount = bid.value;
  263. punkBids[punkIndex] = Bid(false, punkIndex, 0x0, 0); //清空投标信息
  264. // Refund the bid money
  265. msg.sender.transfer(amount); //直接将投标价send给投标者,不放入临时账户
  266. }
  267.  
  268. }

注:
1.为什么要设置临时账户:
因为当用户调用定义为payable的函数时,它通过msg.value    传入的金额其实已经从他的账户中转到了该合约地址当中,就是调用函数的交易的from为函数调用者,to为合约地址。当其后面想要取消该函数的调用时,比如之前投标bid了某token,后面想取消时,函数就会讲bid结构体中记录的你的投标价格放入你的临时账户中,语句msg.sender.transfer(金额数)就是合约地址将该金额转回给你了

对里面使用到的solidity的介绍,看这里solidity学习-cryptoPunks为实例

cryptopunks的代码解释的更多相关文章

  1. Deep Learning入门视频(下)之关于《感受神经网络》两节中的代码解释

    代码1如下: #深度学习入门课程之感受神经网络(上)代码解释: import numpy as np import matplotlib.pyplot as plt #matplotlib是一个库,p ...

  2. [ARM] Cortex-M Startup.s启动文件相关代码解释

    1. 定义一个段名为CSTACK, 这里: NOROOT表示如何定义的段没有被关联,那么同意会被优化掉,如果不想被优化掉就使用ROOT. 后面的括号里数字表示如下: (1):这个段是2的1次方即2字节 ...

  3. word2vec代码解释

    以前看的国外的一篇文章,用代码解释word2vec训练过程,觉得写的不错,转过来了 原文链接 http://nbviewer.jupyter.org/github/dolaameng/tutorial ...

  4. javascript代码解释执行过程

    javascript是由浏览器解释执行的脚本语言,不同于java c,需要先编译后运行,javascript 由浏览器js解释器进行解释执行,总的过程分为两大块,预编译期和执行期 下面的几个demo解 ...

  5. 临时2级页表的初始化过程 head_32.S 相关代码解释

    page_pde_offset = (__PAGE_OFFSET >> 20); /* __PAGE_OFFSET是0xc0000000,page_pde_offset = 3072 = ...

  6. cryptopunks测试代码cryptopunksmarket-setinitial.js

    require('babel-polyfill'); //测试用例要在执行完了truffle compile和truffle migrate后才能使用truffle test来进行测试 //要注意ar ...

  7. 零基础学python之入门和列表数据(附详细的代码解释和执行结果截图)

    Python学习笔记 1 快速入门 下载安装好Python之后,在开始找到 双击打开一个窗口,这是一个shell界面编辑窗口,点击左上角的file——new file新建一个窗口,这里可以输入完整的代 ...

  8. java 的一个hellow word 代码解释

    /* This is a simple Java program. Call this file "Example.java". */(上面是注释的方法) class Exampl ...

  9. TensorFlow的序列模型代码解释(RNN、LSTM)---笔记(16)

    1.学习单步的RNN:RNNCell.BasicRNNCell.BasicLSTMCell.LSTMCell.GRUCell (1)RNNCell 如果要学习TensorFlow中的RNN,第一站应该 ...

随机推荐

  1. asp.net mvc 模型验证组件——FluentValidation

    asp.net mvc 模型验证组件——FluentValidation 示例 using FluentValidation; public class CustomerValidator: Abst ...

  2. NPOI 通过excel模板写入数据并导出

    private void ToExcel(string id) { //模板文件 string TempletFileName = Server.MapPath("template.xls& ...

  3. 漫画揭秘Hadoop MapReduce | 轻松理解大数据

    网址:http://www.iqiyi.com/w_19rtz04nh9.html

  4. 【IDEA&&Eclipse】2、从Eclipse转移到IntelliJ IDEA一点心得

    本人使用IntelliJ IDEA其实并不太久,用了这段时间以后,觉得的确很是好用.刚刚从Eclipse转过来的很多人开始可能不适应,我就把使用过程中的一些经验和常用功能分享下,当然在看这篇之前推荐你 ...

  5. Python3 系列之 环境配置篇

    以下所有操作是基于 Windows10 和 Python3.6 来进行的,其它平台和 python 版本请自行百度. 高效使用 Visual Studio Code 系列 环境安装 1.Python ...

  6. 解决Linux服务器tomact-8.0启动慢的问题

    环境信息: CentOS release 6.8 tomcat-8.0 JDK1.8 一.启动tomcat #sh /root/tomcat-8.0/bin/startup.sh #tailf /ro ...

  7. js查询数组或者List类型是否包含某个元素

    方法一:arr.indexOf(某元素) 实际用法:if(arr.indexOf(某元素) > -1){//则包含该元素} 例: var fruits = ["Banana" ...

  8. IDEA——错误: 找不到或无法加载主类 com.Main

    https://blog.csdn.net/gxx_csdn/article/details/79059884 这篇博客非常赞!

  9. U8 应付款管理 单据类型 分析

    Ap_CloseBill   收付款单主表 Ap_CloseBills 收付款单子表 cVouchType 在收付款单主表中  ,用于区分单据为收款单还是付款单(48,49)  49:付款单 48:收 ...

  10. JavaScript按IP地址排序

    JavaScript按IP地址列表排序,主要思路就是分割每个点号部分,然后ip1和ip2分别对不够三位数的进行补0操作,然后转换为数字类型进行一一比较. 上代码: 正序: var arr=[ {ip: ...