├── IPFS技术详解1.pdf
├── IPFS技术详解2.pdf
├── storj技术详解.pdf
├── 智能合约内容分享.pptx
├── 20180803 区块链白皮书分享.ppt
├── 2018-7-10 以太坊常用术语-王文刚.pdf
├── how-to-hold-blockathon.pdf
├── images
└── blockchain-learning-status.png
├── blockchain2.0-ethereum-introduction.pptx
├── LICENSE
├── learning-blockchain-together.md
├── smart-contract-traveller-guides.md
├── CryptoZombies游戏学习Solidity笔记.md
├── agile-and-blockchain.md
├── upgradable-smart-contract-step-by-step.md
├── README.md
└── contracts.rst
/IPFS技术详解1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/IPFS技术详解1.pdf
--------------------------------------------------------------------------------
/IPFS技术详解2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/IPFS技术详解2.pdf
--------------------------------------------------------------------------------
/storj技术详解.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/storj技术详解.pdf
--------------------------------------------------------------------------------
/智能合约内容分享.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/智能合约内容分享.pptx
--------------------------------------------------------------------------------
/20180803 区块链白皮书分享.ppt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/20180803 区块链白皮书分享.ppt
--------------------------------------------------------------------------------
/2018-7-10 以太坊常用术语-王文刚.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/2018-7-10 以太坊常用术语-王文刚.pdf
--------------------------------------------------------------------------------
/how-to-hold-blockathon.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/how-to-hold-blockathon.pdf
--------------------------------------------------------------------------------
/images/blockchain-learning-status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/images/blockchain-learning-status.png
--------------------------------------------------------------------------------
/blockchain2.0-ethereum-introduction.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HiBlock/blockchain-learning/HEAD/blockchain2.0-ethereum-introduction.pptx
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/learning-blockchain-together.md:
--------------------------------------------------------------------------------
1 | # Learning blockchain together
2 |
3 | ## What is the learning blockchain together
4 |
5 | Learning Blockchain together ([HiBlock区块链技术布道](https://github.com/HiBlock/blockchain-learning)),成立于2018年5月13日,是一个以输出的方式来加速区块链技术学习的小组。
6 |
7 | 我们的宗旨是:抱团学习,一起学习共同输出,相互鼓励与扶持。
8 |
9 | ### 现状
10 |
11 | 持续7周时间,10位来自不同地区的小伙伴累计输出文章等素材44篇。给大家点个赞!
12 |
13 | 
14 |
15 | ## What can I get
16 |
17 | 最好的学习就是教会别人,最好的学习是以目标为导向,不断思考不断输出的方式。
18 |
19 | 所以在这里,你不仅仅是写出自己的思想,还能结交一群同样喜欢思考的小伙伴。
20 |
21 | ## What can I do
22 |
23 | 非常简单,拿起你的键盘,写下你对于区块链的思考与认识。每周一篇文章,固定节奏与频率,和小伙伴们一起!
24 |
25 | 加入我们? 参考下面的如何加入小结。
26 |
27 | ## How to join
28 |
29 | - [github repo](https://github.com/HiBlock/blockchain-learning)
30 | - 技术布道者:要求,1. 对区块链技术有热情; 2. 对技术布道有热情; 3. 请参考1和2
31 | - 联系方式:bob@hiblock.net 、 微信:hiblocknet
32 |
33 | ## 关于 HiBlock 社区
34 |
35 | HiBLock区块链社区秉承开放、协作、透明、链接、分享的价值观,致力打造一个专注于区块链的开发者社区,我们不仅在开发者中宣传推广区块链,还会帮助开发者真正掌握区块链技术和应用。
36 |
37 | [HiBlock官网](https://hiblock.one/contact/)
38 |
39 | ## HiBlock community
40 |
41 | Last, but not least, [hiblock community](https://hiblock.one) focuses on blockchain technology, could provide services like technology training, consulting, smart contract auditing, organizing hackthon etc.
42 |
43 | If you have interest, please [Mail us](mailto:info@hiblock.one) .
44 |
--------------------------------------------------------------------------------
/smart-contract-traveller-guides.md:
--------------------------------------------------------------------------------
1 | # smart contract traveller guide
2 |
3 | I start to learn smart contract just from a few weeks ago, here is my learning experience I would like to share those who are new to blockchain like me.
4 |
5 | ## what is blockchain
6 |
7 | Blockchain is a distributed ledge, who is to solve the trust problem amongst the un-trust individules. In 2008, Satoshi published a paper named *A peer to peer electronic cash system*, where blockchain technology is introduced first time. Next year Sotoshi mined the first 50 bitcoins including genisis block.
8 |
9 | For now blockchain is well-known because it is high price for bitcoins, but it is really underestimated for the blockchain technology. Anyway the high price it is great thing, because it attacted more people to focus on the blockchain.
10 |
11 | Let's from different perspectives to understand blockchain:
12 | - blockchain is next generation internet (e.g web 3.0)
13 | - blockchain is distributed database
14 |
15 | Key features of blockchain:
16 | - transparent
17 | - decentralization
18 | - trustless
19 |
20 | ## what is smart contract
21 | Smart contract is a e-contract which is coded and executed by computer. It is first introduced by Nick Szabo in 1994. In the real world we need the contract to complete the work between 2 clients or multiple clients. There are possibily blured points malnupalated by people. Smart contract could program the contract into code.
22 |
23 | ## environment preparation
24 | Here is the [course link for prepare ethereum development](https://edu.csdn.net/course/detail/8078?pre_view=1). The environment includes:
25 | - development env
26 | - deployment env
27 | - testnet
28 |
29 | ## 0 to 1 learn ethereum from the scratch
30 | 1. env
31 | 2. truffle framework
32 | 3. code (solidity)
33 | 4. compile
34 | 5. test framework in truffle
35 | 6. migrate (deploy)
36 | 7. testnet or mainnet
37 |
38 | ## example
39 | I have 2 examples free course about how to program your first DAPP, and how to issue your own token.
40 | - [program your first DAPP](http://www.itdks.com/liveevent/detail/11076)
41 | - [issue your token](https://v.qq.com/x/page/m0633xje4q2.html)
42 |
43 | ## solidity
44 | Solidity is official smart contract language provided by Ethereum. Here is the [document](https://solidity.readthedocs.io/), here is [Chinese document](https://solidity-cn.readthedocs.io/).
45 |
46 |
--------------------------------------------------------------------------------
/CryptoZombies游戏学习Solidity笔记.md:
--------------------------------------------------------------------------------
1 | 作者:倔强的小红军
2 | 注释:这是学习https://cryptozombies.io时的笔记
3 | 1. 函数的写法
4 | ```
5 | function createZombies(string _str, uint _id) public pure returns(result){
6 |
7 | }
8 | ```
9 | returns后带括号写返回的参数名
10 |
11 | 2. 修饰符
12 | - public/private限定函数可以被所有人调用/只能在合约内部使用
13 | - internal/external限定函数函数可以被继承合约调用/只能从外部被调用
14 | - pure/view/留空可以限定函数不使用该DAPP的任何数据(不看也不写)/只查看该DAPP的数据保证不修改/可以修改合约数据
15 | - modifier修饰符,用于自定义其对函数的约束逻辑。在函数之前运行,常用来添加require检查是否满足限制条件,如下展示了自定义参数的modifier,其定义形式跟函数一样:
16 | ```
17 | // 存储用户年龄的映射
18 | mapping (uint => uint) public age;
19 |
20 | // 限定用户年龄的修饰符
21 | modifier olderThan(uint _age, uint _userId) {
22 | require(age[_userId] >= _age);
23 | _;
24 | }
25 |
26 | // 必须年满16周岁才允许开车 (至少在美国是这样的).
27 | // 我们可以用如下参数调用`olderThan` 修饰符:
28 | function driveCar(uint _userId) public olderThan(16, _userId) { //modifier后也要记得传递参数
29 | // 其余的程序逻辑
30 | }
31 | ```
32 | modifier修饰符的最后一行为`_;`,表示修饰符调用结束后返回,并执行调用函数余下的部分。 一个常用的modifier叫onlyOwner,它能达到禁止第三方修改我们的合约的同时,留个后门给咱们自己去修改的目的。使用方法为先集成ownable合约。注意onlyOwner表明只能合约的作者调用,而合约的调用者不能调用该函数。
33 | - payable 一种可以接收以太的特殊函数。可以用于向一个合约要求支付一定的钱来运行一个函数。
34 |
35 | # 第三章 高级Solidity编程
36 | 这节介绍在以太坊上的DApp与其它程序真正的区别之处
37 | 1. 在你把智能协议传上以太坊之后,它就变得不可更改, 这种永固性意味着你的代码永远不能被调整或更新。
38 | 因此需要给可能需要修改的参数预留修改接口。
39 |
40 | 2. 两种存储方式 storage/memory,前者会写入区块链,后者只是临时变量
41 | 默认的函数参数,包括返回的参数,是memory。
42 | 默认的局部变量是一个指向storage的指针。
43 | 状态变量,合约内声明的公有变量。是被分配了空间的storage型数据。
44 | memory与storage之间的赋值,具体请看[这里](http://me.tryblockchain.org/solidity-data-location.html)
45 |
46 |
47 | 3. 另一个使得Solidity编程语言与众不同的特征:
48 | ```
49 | 用户想要每次执行你的 DApp 都需要支付一定的 gas(用以太币购买,因此,用户每次跑 DApp 都得花费以太币)。
50 |
51 | ```
52 | 为什么要这样?
53 | ```
54 | 用户想要每次执行你的 DApp 都需要支付一定的 gas(用以太币购买,因此,用户每次跑 DApp 都得花费以太币)。
55 | ```
56 | 节省`gas`的方法:
57 | - 结构封装 (Struct packing)
58 | uint即为uint256,另外还有uint32,uint64等,
59 | 因为存储数据比做个运算贵得多,所以当 uint 定义在一个 struct 中的时候,尽量使用最小的整数子类型以节约空间。 并且把同样类型的变量放一起(即在 struct 中将把变量按照类型依次放置),这样 Solidity 可以将存储空间最小化。
60 | - 利用view函数节省gas
61 | view 函数不会真正改变区块链上的任何数据——它们只是读取。
62 | 用 view 标记一个函数,意味着运行这个函数只需要查询你的本地以太坊节点,而不需要在区块链上创建一个事务(事务需要运行在每个节点上,因此花费 gas)。
63 | 因此在所能只读的函数上标记上表示“只读”的“external view 声明,就能为你的玩家减少在 DApp 中 gas 用量。
64 | - `storage`(存储)非常昂贵
65 | - 大多数编程语言中,遍历大数据集合都是昂贵的。但在 Solidity 中,使用一个标记了external view的函数,遍历比 storage 要便宜太多,因为 view 函数不会产生任何花销。
66 | - 在数组后面加上 memory关键字,表明这个数组是仅仅在内存中创建,不需要写入外部存储,并且在函数调用结束时它就解散了。如:
67 |
68 | ```
69 | uint[] memory values = new uint[](3);
70 |
71 | ```
72 |
73 | - 其实就是将程序用到的数据范围严格限定,避免不必要的存储,以节约gas
74 |
75 | 在大多数编程语言中,遍历大数据集合都是昂贵的。但是在 Solidity 中,使用一个标记了external view的函数,遍历比 storage 要便宜太多,因为 view 函数不会产生任何花销。 (gas可是真金白银啊!)。
76 |
77 |
78 | 4. Solidity中的时间
79 | unix时间戳,Solidity中还包含seconds,minutes,hours,days,weeks,years 等时间单位,分别会转换为相应的秒数存入uint中。
80 | now变量(uint256类型),固定返回当前时间
81 |
82 | 5. Solidity的继承,可以像传统一样定义is a关系,但好像还可以用于分割文件,避免一个文件中的逻辑过于复杂。
83 | ```
84 | contract cat is animal, creature{
85 |
86 | }
87 | ```
88 |
89 | # 第五章 代币和交易
90 | 1. #### 什么是代币?
91 | 一个 代币 在以太坊基本上就是一个遵循一些共同规则的智能合约——即它实现了所有其他代币合约共享的一组标准函数,例如 transfer(address _to, uint256 _value) 和 balanceOf(address _owner).
92 | 在智能合约内部,通常有一个映射, mapping(address => uint256) balances,用于追踪每个地址还有多少余额。
93 | 所以基本上一个代币只是一个追踪谁拥有多少该代币的合约,和一些可以让那些用户将他们的代币转移到其他地址的函数。
94 | #### 什么是ERC20?
95 | ERC20事实上是一个标准,满足这个标准的代币就叫ERC20代币,他们共享具有相同名称的同一组函数,相互之间可以以相同的方式进行交互。
96 | 类似的标准还有ERC721等,它规定每个代币都被认为是唯一且不可分割的。只能以整个单位交易它们,并且每个单位都有唯一的 ID。
97 | 使用标准的优势在于:在我们的合约中不必再实现交易逻辑。并且其他人可以为加密可交易的ERC721资产搭建一个交易所平台
98 |
99 | 2. 库的使用
100 | ```
101 | import "./safemath.sol";
102 |
103 | using SafeMath for uint256; // 这句写在contract中
104 | ```
105 | SafeMath库是OpenZeppelin建立的用来防止数据溢出的数学运算库,using可以自动把库的所有方法添加给某个数据类型,这样就不用每次都c = add(a,b)而可以简写成c = a.add(b)了。
106 |
107 | 3. 注释风格
108 | Solidity 社区所使用的一个标准是使用一种被称作 natspec 的格式,看起来像这样:
109 | ```
110 | /// @title 一个简单的基础运算合约
111 | /// @author H4XF13LD MORRIS 💯💯😎💯💯
112 | /// @notice 现在,这个合约只添加一个乘法
113 | contract Math {
114 | /// @notice 两个数相乘
115 | /// @param x 第一个 uint
116 | /// @param y 第二个 uint
117 | /// @return z (x * y) 的结果
118 | /// @dev 现在这个方法不检查溢出
119 | function multiply(uint x, uint y) returns (uint z) {
120 | // 这只是个普通的注释,不会被 natspec 解释
121 | z = x * y;
122 | }
123 | }
124 | ```
125 | @title(标题) 和 @author (作者)很直接了.
126 |
127 | @notice (须知)向 用户 解释这个方法或者合约是做什么的。 @dev (开发者) 是向开发者解释更多的细节。
128 |
129 | @param (参数)和 @return (返回) 用来描述这个方法需要传入什么参数以及返回什么值。
130 |
131 | 注意你并不需要每次都用上所有的标签,它们都是可选的。不过最少,写下一个 @dev 注释来解释每个方法是做什么的。
132 |
133 | # 第六章 应用前端和 Web3.js
134 | 用以太坊基金发布的 JavaScript 库 —— Web3.js,来为 DApp 创建一个基本的前端界面,和智能合约交互。
135 |
136 | 1. 什么是web3.js
137 | 以太坊网络是由节点组成的,每一个节点都包含了区块链的一份拷贝。当你想要调用一份智能合约的一个方法,你需要从其中一个节点中查找并告诉它:
138 | - 智能合约的地址
139 | - 你想调用的方法,以及
140 | - 你想传入那个方法的参数
141 |
142 | 以太坊节点只能识别一种叫做JSON-RPC的语言。这种语言直接读起来并不好懂。当你你想调用一个合约的方法的时候,需要发送的查询语句将会是这样的:
143 | `{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","gas":"0x76c0","gasPrice":"0x9184e72a000","value":"0x9184e72a","data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"}],"id":1}`
144 | web3.js是以太坊基金发布的 JavaScript 库,封装了查询语句,提供更易用的交互界面。
145 | Web3 Provider用来告诉我们的代码应该和哪个节点进行交互(就好比是传统的 Web 应用程序中为你的 API 调用设置远程 Web 服务器的网址)
146 | 可以运行你自己的以太坊节点来作为 Provider,也可以用第三方的服务:[Infura](https://infura.io/)。它维护了很多以太坊节点并提供了一个缓存层来实现高速读取。用 Infura作为节点提供者,你可以不用自己运营节点就能很可靠地向以太坊发送、接收信息。
147 | MetaMask:浏览器中的身份(私钥)管理插件,让你在浏览器中访问DAPP,而不需要运行完整的以太坊代码。
148 |
149 | 2. 使用方法:
150 | - Web3.js 需要两个东西来和你的合约对话: 它的 地址 和它的 ABI。
151 | > ABI(Application Binary Interface): 意为应用二进制接口,它是以 JSON 格式表示合约的方法,告诉 Web3.js 如何以合同理解的方式格式化函数调用。
152 | - Web3.js 有两个方法来调用我们合约的函数: call and send.
153 | > call 用来调用 view 和 pure 函数。它只运行在本地节点,不会在区块链上创建事务。
154 | > send 将创建一个事务并改变区块链上的数据。你需要用 send 来调用任何非 view 或者 pure 的函数。
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/agile-and-blockchain.md:
--------------------------------------------------------------------------------
1 | # Agile and Blockchain
2 |
3 | ## The origin
4 |
5 | Many say blockchain is just a decentralized ledger, it is true, but not the essential part for blockchain. I (BoB) as an experienced agile guru (Certified Scrum Trainer from [scrumalliance.org](http://scrumalliance.org/)), would anatomize blockchain with you together and compare agile and blockchain, and try to find the fundamental for both.
6 |
7 | In the beginning, let's start from the history to understand how they come.
8 |
9 | ### what is agile
10 |
11 | In 2001, there are 17 software pioneers gathering in snowbird to discuss the light software development methods. Finally they conclude Agile Manifesto with agile principles as well. More details, see also [Agile Manifesto](http://agilemanifesto.org/).
12 |
13 | > We are uncovering better ways of developing software by doing it and helping others do it. Through this work we have come to value:
14 | Individuals and interactions over processes and tools
15 | Working software over comprehensive documentation
16 | Customer collaboration over contract negotiation
17 | Responding to change over following a plan
18 | That is, while there is value in the items on the right, we value the items on the left more.
19 |
20 | ### what is blockchain
21 |
22 | > A blockchain,[1][2][3] originally block chain,[4][5] is a continuously growing list of records, called blocks, which are linked and secured using cryptography.[1][6] Each block typically contains a cryptographic hash of the previous block,[6] a timestamp, and transaction data.[7] By design, a blockchain is resistant to modification of the data. It is "an open, distributed ledger that can record transactions between two parties efficiently and in a verifiable and permanent way".[8] For use as a distributed ledger, a blockchain is typically managed by a peer-to-peer network collectively adhering to a protocol for inter-node communication and validating new blocks. Once recorded, the data in any given block cannot be altered retroactively without alteration of all subsequent blocks, which requires consensus of the network majority. -- [Definition from wikipedia](https://en.wikipedia.org/wiki/Blockchain)
23 |
24 | In 2008, a person (not sure whether a man or woman, still secret now) published a whitepaper named *BitCoin: A peer-to-peer electronic cash system*.
25 |
26 | Blockchain technology is mentioned for the first time there. And as we know, the whitepaper is delivered in cryptopunker maillist first.
27 |
28 | ## The same
29 |
30 | Agile and blockchain are 2 different concepts but they have several same points which are under the surface. They are:
31 |
32 | - Transparency
33 | - Community
34 | - Self organizing
35 |
36 | ### Transparency (Trust)
37 |
38 | Agile as an experimental process is based on 3 pillars:
39 |
40 | - transparency
41 | - inspect
42 | - adapt
43 |
44 | For example, in agile, information radiator is well used in many teams, in order to visualize and make it transparent. So that it increases trust. ( I see, then I believe )
45 |
46 | Blockchain's key charactoristics is Tamper-proof, which based on :
47 |
48 | - only add, no edit or delete
49 | - public transaction information (each transaction recorded on chain, and could be queried)
50 |
51 | So for agile and blockchain, both are transparent, agile intends to visualize information, and blockchain intends to make transaction (core of blockchain) public.
52 |
53 | ### Community
54 |
55 | From the history, we can see both are from community, agile is from face to face meetup to discuss, and blockchain is from a maillist dicussion.
56 |
57 | So community is a fundamental, but what is community, and why we need community.
58 |
59 | In blockchain area, many communities, but what I see is many people don't understand community, and abuse community. (E.g only for advertisement or promotion product/idea)
60 |
61 | Actually community is consensus, is a group people to have similar interest, is a group people who have similar belief. Based on that, community could exist, and live, but community is NOT for profit, is NOT for advertisement, is NOT for sales.
62 |
63 | ### Self organizing
64 |
65 | Agile is organization design process, which is based on self organizing feature team ( in special for Scrum ). Empower people by simplifying/decreasing roles in org.
66 |
67 | Blockchain is decentralized, so that means in blockchain there is no central point, no one is authority. Everyone could join or exit blockchain freely. It's more like self organizing with economics considering.
68 |
69 | ## The differency
70 |
71 | Although agile and blockchain have many same points at basis, both have differencies as well, let's take a look what are different.
72 |
73 | ### People vs. Technology
74 |
75 | In agile, it is key to respect people, which means to empower and focus people in agile organization. But for blockchain, it focuses technology more. I am not saying people is not important in blockchain, but it is a bit more focus.
76 |
77 | ### Offline vs. Online
78 |
79 | The most efficient and effective method of conveying information to and within a development team is face-to-face conversation. -- From Agile principles
80 |
81 | BLockchain field, it is decentralized, is open source, so most use cases are online collaborations. Such as github, slack, gitters, etc. Strangers start to gather with consensus, to work on one product (may be in github or gitlab). And then core developers could meet offline.
82 |
83 | So for blockchain, in the beginning, it should be online, but at last, it must be offline, back to agile principles.
84 |
85 | ### Company vs. Community
86 |
87 | Agile is adopted by companies, specially by huge companies, it is because for huge companies they realized to adapt the change quickly to win the market, this is a core competency. So many agile gurus (like speakers, trainers) emerged, like me [BoB Jiang](http://bobjiang.com/).
88 |
89 | But for blockchain, it is community based from the scatch. Maybe just a few people have an idea, and have some codes in repository, some people gathered around the repository/idea, and provide more codes.
90 |
91 | In the future, there are at least 2 kinds of organizations, company based and community based. And there would be more and more community based organization arises.
92 |
93 |
94 | ## HiBlock community
95 |
96 | Last, but not least, [hiblock community](https://hiblock.one) focuses on blockchain technology, could provide services like technology training, consulting, smart contract auditing, organizing hackthon etc.
97 |
98 | If you have interest, please [Mail us](mailto:info@hiblock.one) .
99 |
--------------------------------------------------------------------------------
/upgradable-smart-contract-step-by-step.md:
--------------------------------------------------------------------------------
1 | # How to program an upgradable smart contract step by step
2 |
3 | ## introduction
4 |
5 | As an information transform network, it is good for internet. And as we known [Agile](http://agilemanifesto.org/) and iteration is becoming popular in software development field.
6 |
7 | The good news for blockchain is that blockchain is design to [Tamper resistance](https://en.wikipedia.org/wiki/Tamper_resistance), but following is the bad news, it is hard to upgrade in blockchain field (e.g even we have found bugs in smart contract, it is hard to upgrade/fix it), which is preventing blockchain evolving.
8 |
9 | We would introduce a way to upgrade your smart contract with [ZepplinOS](https://zeppelinos.org/).
10 |
11 | ## installation/preparation
12 |
13 | First of all, we need to setup/prepare environment. Here we need:
14 |
15 | - zos
16 | - ganache-cli
17 | - truffle
18 |
19 | ### install zos
20 |
21 | We will use command line tool for ZeppelinOS `zos` :
22 |
23 | ```
24 | $ npm install -g zos
25 | ```
26 |
27 | ### install truffle/ganache-cli
28 |
29 | Install truffle, you can refer the [truffle official website](https://truffleframework.com/docs/getting_started/installation).
30 |
31 | ```
32 | $ npm install -g truffle
33 | ```
34 |
35 | Install ganache-cli
36 |
37 | ```
38 | $ npm install --save ganache-cli
39 | ```
40 |
41 | ## init project
42 |
43 | ```
44 | $ mkdir zos-demo
45 | $ cd zos-demo
46 | $ npm init -y
47 | $ zos init zos-demo
48 | ```
49 |
50 | **Notice**: the zos.json file that was produced. This is the configuration file that makes zos aware of your smart contract architecture. Feel free to read up on the zos.json file format to understand how zos sees your project.
51 |
52 | ```
53 | $ npm install --save zos-lib
54 | ```
55 |
56 | ## prepare smart contract in solidity
57 |
58 | In `contracts/` folder create a new file named `CounterContrat.sol` with following code:
59 |
60 | ```
61 | pragma solidity ^0.4.21;
62 | import "zos-lib/contracts/migrations/Migratable.sol";
63 | contract CounterContract is Migratable {
64 | uint256 public counter;
65 | function initialize(uint256 _counter) isInitializer("CounterContract", "0") public {
66 | counter = _counter;
67 | }
68 |
69 | function increment() public {
70 | counter += 1;
71 | }
72 | }
73 | ```
74 |
75 | For an upgradable contract, instead, replace constructor with an `initialize` function to set up the initial smart contract state. Make sure the `initialize` function with `isInitializer` modifer that take the name of your contract and version ID.
76 |
77 | **NOTE:** If you do use a constructor in an upgradeable smart contract, everything you set in the constructor will be ignored.
78 |
79 | ### Test locally (start ganache-cli)
80 |
81 | Issue following command in a separate console:
82 |
83 | ```
84 | $ npx ganache-cli --port 9545
85 | ```
86 |
87 | Then deploy smart contract to local network. (in another console) and add contract to zos and push it to local network.
88 |
89 | ```
90 | $ zos add CounterContract
91 | $ zos push --network local
92 | ```
93 |
94 | **NOTE:** If encountering following failure, check your `hosts` file to make sure define `localhost` as '127.0.0.1'
95 |
96 | ```
97 | Writing artifacts to ./build/contracts
98 |
99 | Could not connect to your Ethereum client. Please check that your Ethereum client:
100 | - is running
101 | - is accepting RPC connections (i.e., "--rpc" option is used in geth)
102 | - is accessible over the network
103 | - is properly configured in your Truffle configuration file (truffle.js)
104 | ```
105 |
106 | Mostly it should treat `localhost` as '127.0.0.1', but sometime `hosts` file corrupts.
107 |
108 | You can edit `truffle-config.js` to change host to '127.0.0.1'.
109 |
110 | ### invoke contract
111 |
112 | Next, we’ll create and initialize an upgradeable instance of CounterContract with zos. The `--args` option corresponds with the parameters of our initialize method.
113 |
114 | ```
115 | $ zos create CounterContract --init initialize --args 42 --network local
116 | ```
117 | **Note:** the output line ‘CounterContract proxy:
’. This is the address you will use for CounterContract. Save this address, as it is the permanent address for CounterContract. As following:
118 |
119 | ```
120 | Creating CounterContract proxy and calling initialize with:
121 | - _counter (uint256): "42"
122 | TX receipt received: 0x18746572bd744e231d8f0a9996a9afba8c2424e9c6329d1b7e71d429926b31d7
123 | CounterContract proxy: 0xfb011a654e7c39a19932ced52c04adec748ecdff
124 | Successfully written zos.local.json
125 | 0xfb011a654e7c39a19932ced52c04adec748ecdff
126 | ```
127 |
128 | Then we can test it in truffle console, launch truffle console by:
129 |
130 | ```
131 | $ npm truffle console --network=local
132 | ```
133 |
134 | We will see console with prefix `truffle(local)>`. And issue following command to set var:
135 |
136 | ```
137 | truffle(local)> counterContract = CounterContract.at("0xfb011a654e7c39a19932ced52c04adec748ecdff")
138 | truffle(local)> counterContract.increment()
139 | truffle(local)> counterContract.counter().then(counter => counter.toNumber())
140 | truffle(local)> 43
141 |
142 | ```
143 |
144 | ## upgrade smart contracts
145 |
146 | **NOTE:** for upgradable smart contracts, only support to add varables/functions, must not remove codes from previous contracts.
147 |
148 | For example, we add a new function as following:
149 |
150 | ```
151 | pragma solidity ^0.4.21;
152 | import "zos-lib/contracts/migrations/Migratable.sol";
153 |
154 | contract CounterContract is Migratable {
155 | uint256 public counter;
156 | mapping(uint256 => address) public history;
157 |
158 | function initialize(uint256 _counter) isInitializer("CounterContract", "0") public {
159 | counter = _counter;
160 | }
161 |
162 | function increment() public {
163 | counter += 1;
164 | history[counter] = msg.sender;
165 | }
166 |
167 | function incrementByTwo() public {
168 | counter += 2;
169 | history[counter] = msg.sender;
170 | }
171 | }
172 | ```
173 |
174 | ### push and update contracts
175 |
176 | exit truffle console with command (.exit)
177 |
178 | ```
179 | $ zos push --network local
180 | $ zos update CounterContract --network local
181 | $ npx truffle console --network=local
182 | ```
183 |
184 | Entering truffle console,
185 |
186 | ```
187 | truffle(local)> counterContract = CounterContract.at("0xfb011a654e7c39a19932ced52c04adec748ecdff")
188 | truffle(local)> counterContract.incrementByTwo()
189 | truffle(local)> counterContract.counter().then(counter => counter.toNumber())
190 | truffle(local)> 45
191 |
192 | ```
193 |
194 | **NOTE:** If at any point you’ve stopped Ganache and need to restart this process all over, make sure you delete zos.local.json file as well. This isn’t a problem for other networks, since typically networks don’t get wiped out :)
195 |
196 | Edited from [ZeppelinOS Blog](https://blog.zeppelinos.org/getting-started-with-zeppelinos/)
197 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HiBlock区块链技术布道
2 |
3 | ## 目标
4 | 目标:以输出的方式来加速学习
5 |
6 | ## 加入我们
7 | - 抱团学习,一起学习共同输出,相互鼓励与扶持。
8 | - 技术布道者:要求,1. 对区块链技术有热情; 2. 对技术布道有热情; 3. 请参考1和2
9 | - 联系方式:bob@hiblock.net 、 微信:hiblocknet
10 |
11 | ## 输出形式
12 | 输出形式多样:
13 | - 文章,如学习经验分享、心得、翻译等(不小于1000字)
14 | - 教程、课件(PPT)、视频、其他技术布道的输出
15 |
16 | ## 20181125
17 | - 笔名辉哥 [【区块链技术工坊23期实录】郝振亚:工业互联网领域边缘计算与区块链实践](https://www.jianshu.com/p/1cb25f890f9b)
18 | - AmyWu [Hyperledger Fabric构架简述之一 *再发布](https://www.jianshu.com/p/d0334265e33e)
19 |
20 |
21 | ## 20181118
22 | - 笔名辉哥 [【区块链技术工坊22期实录】王登辉:BANCOR算法详解及代码实现](https://www.jianshu.com/p/01877d787253)
23 | - AmyWu [BCH简史](https://www.jianshu.com/p/0d5078c2b6f5)
24 |
25 | ## 20181111
26 | - 笔名辉哥 [第二十九课 如何实现MetaMask签名授权后DAPP一键登录功能?](https://www.jianshu.com/p/8a0bd9bd487c)
27 | - AmyWu [EOS和Ethereum的区别(中)](https://www.jianshu.com/p/d84a37b70497)
28 |
29 | ## 20181104
30 | - 笔名辉哥 [第二十八课 区块链应用DAPP如何探测MetaMask的账号和登录状态?](https://www.jianshu.com/p/7d02202fa998)
31 | - AmyWu [EOS和Ethereum的区别(上)](https://www.jianshu.com/p/39b0bec71c2f)
32 |
33 | ## 20181028
34 | - 笔名辉哥 [IBO的金融原理和应用方向分析](https://www.jianshu.com/p/17c2151ff056)
35 | - AmyWu [3分钟漫谈以太坊The DAO事件,浅入浅出区块链(4)](https://www.jianshu.com/p/d2e43f01c66d)
36 |
37 | ## 20181021
38 | - 笔名辉哥 [【分析】最流行的3款DAPP浏览器和原理](https://www.jianshu.com/p/39e666ee2f2b)
39 | - AmyWu [3分钟漫谈以太坊The DAO事件,浅入浅出区块链(3)](https://www.jianshu.com/p/5fe1da76340f)
40 |
41 | ## 20181014
42 | - 笔名辉哥 [第二十七课 如何从BANCOR交易所兑换ENJIN通证](https://www.jianshu.com/p/617103393dc6)
43 | - 笔名辉哥 [第二十六课 如何从零开始搭建一个Truffle框架的DAPP应用](https://www.jianshu.com/p/ecaa4dc22bef)
44 | - AmyWu [3分钟漫谈以太坊The DAO事件,浅入浅出区块链(2)](https://www.jianshu.com/p/a6706b5bf7ff)
45 |
46 | ## 20181007
47 | - OliviaZhang [Cryptozombie part 1](https://www.jianshu.com/p/4a66db75f3b0)
48 | - 笔名辉哥 [第二十五课 如何开发自己的BANCOR去中心化交易平台?](https://www.jianshu.com/p/9fc78f8f5773)
49 | - 笔名辉哥 [【ERC1400标准】支持证券增发,交易,相关法律文件存储的证券类同质化通证](https://www.jianshu.com/p/1e300a73eeef)
50 | - 笔名辉哥 [肖风:未来三到五年内,一个去中心化的分布式AI平台或将出现](https://www.jianshu.com/p/a6ce20b61400)
51 | - AmyWu [3分钟漫谈以太坊The DAO事件,浅入浅出区块链(1)](https://www.jianshu.com/p/8a396d2a92c1)
52 |
53 | ## 20180930
54 | - OliviaZhang [Back to Basic On Smart Contract](https://www.jianshu.com/p/0ac8132d3312)
55 | - 笔名辉哥 [【区块链实践】区块链+数字版权:“权利”的游戏](https://www.jianshu.com/p/411fcc5623fa)
56 | - 笔名辉哥 [叶开:内容创作、知识版权、艺术品的Token内容模式](https://www.jianshu.com/p/90f35357e9e0)
57 | - 笔名辉哥 [Fomo玩法加持的PixelMaster为什么火了?](https://www.jianshu.com/p/4aaeea70b4ce)
58 | - 笔名辉哥 [【分析】比特大陆招股说明书解读[附pdf下载]](https://www.jianshu.com/p/c35847068075)
59 | - 笔名辉哥 [【深度知识】以太坊第2层扩容方案:状态通道(State Channels)、Plasma 和 Truebit](https://www.jianshu.com/p/9b63bd712be8)
60 | - 笔名辉哥 [【区块链实践】杭州互联网法院司法区块链解决方案](https://www.jianshu.com/p/ee1e3290338f)
61 | - 笔名辉哥 [这30个以太坊开发示例,让你成为80万都挖不走的区块链人才!](https://www.jianshu.com/p/f5d557c62a66)
62 | - AmyWu [通过小游戏学习Ethereum DApps编程(8)](https://www.jianshu.com/p/0fae5ff82ae4)
63 | - AmyWu [精通以太坊 摘录+笔记(1)](https://www.jianshu.com/p/8777dc7ac064)
64 | - AmyWu [精通比特币 摘录+笔记(1)](https://www.jianshu.com/p/c47013e62fff)
65 |
66 |
67 | ## 20180923
68 | - OliviaZhang [How to build your ERC20 token and launch an ICO](https://www.jianshu.com/p/5433ef1aeb34)
69 | - 笔名辉哥 [第二十四课 基于以太坊的交易所BANCOR算法实现-转换算法框架](https://www.jianshu.com/p/875ba83002dc)
70 | - 笔名辉哥 [【ERC1155实践】区块链游戏的平行宇宙和为此而生的Enjin钱包](https://www.jianshu.com/p/d558acbc8f65)
71 | - 笔名辉哥 [【易错概念】Solidity语法的重载,继承的定义](https://www.jianshu.com/p/231ba1048ef5)
72 | - 笔名辉哥 [【易错概念】Solidity语法的合约/抽象合约/接口/库的定义](https://www.jianshu.com/p/aa18346369cd)
73 | - 笔名辉哥 [【易错概念】Solidity语法constant/view/pure关键字定义](https://www.jianshu.com/p/5f1bc0d39d79)
74 | - AmyWu [通过小游戏学习Ethereum DApps编程(7)](https://www.jianshu.com/p/e0912339e842)
75 |
76 | ## 20180916
77 | - OliviaZhang [ TruffleDapp_Metacoin](https://www.jianshu.com/p/6af41265a37b)
78 | - 笔名辉哥 [【白皮书】Bancor协议:通过智能合约为加密货币提供持续流动性(附PDF下载)](https://www.jianshu.com/p/cbfb9abf8e07)
79 | - 笔名辉哥 [【易错概念】以实例形式深入浅出讲透BANCOR算法](https://www.jianshu.com/p/fe48ed1f38cd)
80 | - AmyWu [通过小游戏学习Ethereum DApps编程(6)](https://www.jianshu.com/p/3ef0914daba9)
81 |
82 |
83 | ## 20180908
84 | - 笔名辉哥 [第二十三课 如何部署TRUFFLE智能合约到以太坊主网(以宠物商店为例)](https://www.jianshu.com/p/d02381201033)
85 | - AmyWu [通过小游戏学习Ethereum DApps编程(5)](https://www.jianshu.com/p/e5ed2d26587d)
86 |
87 | ## 20180901
88 | - AmyWu [通过小游戏学习Ethereum DApps编程(4)](https://www.jianshu.com/p/ed9857d616f5)
89 |
90 | ## 20180825
91 | - AmyWu [通过小游戏学习Ethereum DApps编程(3)](https://www.jianshu.com/p/c9300c8f285a)
92 |
93 | ## 20180818
94 | - AmyWu [通过小游戏学习Ethereum DApps编程(2)](https://www.jianshu.com/p/3eaee42a5f63)
95 | - 冯宇 [Hyperledger Explorer简介](https://www.jianshu.com/p/1709d6f50f5a)
96 |
97 | ## 20180811
98 | - 王文刚 [简述智能合约--基于交付的项目](https://www.jianshu.com/p/1d099288a512)
99 | - AmyWu [通过小游戏学习Ethereum DApps编程(1)](https://www.jianshu.com/p/05e6ca067838)
100 | - 冯宇 [Hyperledger Cello简介](https://www.jianshu.com/p/afdf62088fe1)
101 |
102 | ## 20180804
103 | - AmyWu [搭建你的第一个以太坊智能合约 (1)](https://www.jianshu.com/p/f96a518c46e8)
104 | - 胡键 [区块链周周记:共识算法](https://www.jianshu.com/p/9ce900fb6f91)
105 | - 王文刚 [区块链白皮书分享.ppt](https://github.com/xifarm/blockchain-learning/blob/develop/20180803%20%E5%8C%BA%E5%9D%97%E9%93%BE%E7%99%BD%E7%9A%AE%E4%B9%A6%E5%88%86%E4%BA%AB.ppt)
106 | - 冯宇 [ERC20代币合约开发相关函数和事件](https://www.jianshu.com/p/a3a197ce9268)
107 | - BoB [Upgradable smart contracts](./upgradable-smart-contract-step-by-step.md)
108 |
109 | ## 20180728
110 | - AmyWu [Hyperledger Fabric的一次交易的旅程](https://www.jianshu.com/p/a5dc83988dbc)
111 | - 胡键 [OpenZeppelin周记:打开地图](https://www.jianshu.com/p/3d09bbafd8f2)
112 | - 冯宇 [理解ERC20代币合约](https://www.jianshu.com/p/c6c0256124fe)
113 | - 王文刚 [众说区块链:区块链应用场景之Token](https://mp.weixin.qq.com/s?__biz=MzA5NDAxNzIzNg==&mid=2450005496&idx=1&sn=5a9251763e9a53d21f0796b749741dd8&chksm=87a9be43b0de37555b65487e587bde9f8a8052ad4199cfaed697c528728b2c605be0c93f4639&scene=38#wechat_redirect)
114 |
115 | ## 20180721
116 | - AmyWu [如何使用Docker快速启动EOSIO环境](https://www.jianshu.com/p/7ea632fe1499)
117 | - 王文刚 [智能合约内容分享.ppt](https://github.com/xifarm/blockchain-learning/blob/HiBlock-develop/%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6%E5%86%85%E5%AE%B9%E5%88%86%E4%BA%AB.pptx)
118 | - 冯宇 [从开发者的角度快速解读以太坊白皮书](https://www.jianshu.com/p/41ae276ae65e)
119 | - BoB [如何发布和使用ERC875代币](https://github.com/HiBlock/non-fungible-token/blob/master/how-to-issue-erc875-nfts-cn.md)
120 | - 冯学雷 [钱包](https://www.jianshu.com/p/bf5129b202be)
121 |
122 | ## 20180714
123 | - 冯宇 [搭建以太坊测试链的简易教程](https://www.jianshu.com/p/904aaae80320)
124 | - 王文刚 [2018-7-10 分享PPT 以太坊常用术语-王文刚](https://github.com/xifarm/blockchain-learning/blob/develop/2018-7-10%20%E4%BB%A5%E5%A4%AA%E5%9D%8A%E5%B8%B8%E7%94%A8%E6%9C%AF%E8%AF%AD-%E7%8E%8B%E6%96%87%E5%88%9A.pdf)
125 | - 阿飞 [区块链-以太坊学习笔记(九)](https://blog.csdn.net/lxfgzm/article/details/81074144)
126 | - 胡键 [面向老程序员的Solidity摘要](https://www.jianshu.com/p/ec5ad71e28aa)
127 | - 冯学雷 [股票交易和数字货币交易对比](https://www.jianshu.com/p/312c15e11938)
128 | - AmyWu [关于dApp的问与答](https://www.jianshu.com/p/25409b86da70)
129 |
130 | ## 20180707
131 | - AmyWu [Hyperledger Fabric实践(3) 部署](https://www.jianshu.com/p/7181bc275316)
132 | - 冯宇 [使用Jenkins对以太坊Dapp应用持续集成](https://www.jianshu.com/p/1dfcca96bb65)
133 | - 胡键 [以太坊发币(ERC20)姿势解读](https://www.jianshu.com/p/d78353772029)
134 | - BoB [以太坊的学习笔记](https://github.com/etherchina/ethereum)
135 | - 王文刚 [常用MAC技巧---搭建以太坊私联过程经验](https://www.jianshu.com/p/0af88528c114)
136 | - 冯学雷 [快速搭建以太坊私链](https://www.jianshu.com/p/d2d21ff15c89)
137 | - 阿飞 [区块链-以太坊学习笔记(八)](https://blog.csdn.net/lxfgzm/article/details/80980392)
138 | - 笔名辉哥 [第5课 EOS环境搭建入门(私链节点-钱包-密钥-账号)](https://www.jianshu.com/p/533f849489b1)
139 |
140 | ## 20180630
141 | - BoB [关于Learning Blockchain Together](./learning-blockchain-together.md)
142 | - 笔名辉哥 [第4课 如何在UBUNTU虚拟机上编译EOS完成环境搭建?](https://www.jianshu.com/p/55cd194eff7a)
143 | - AmyWu [Hyperledger Fabric实践(2) 部署Hyperledger Composer理论](https://www.jianshu.com/p/4f3c5dbc5f67)
144 | - 胡键 [以太坊开发极简入门](https://www.jianshu.com/p/bec173e6cf73)
145 | - 冯宇[区块链跨链交易简介](https://www.jianshu.com/p/1540de9f370e)
146 | - 阿飞 [区块链-以太坊学习笔记(七)](https://blog.csdn.net/lxfgzm/article/details/80879497)
147 | - 王文刚 [简单谈谈区块链的事情](https://www.jianshu.com/p/c3120d546672)
148 | - 冯学雷 [搭建以太坊客户端](https://www.jianshu.com/p/bf23baf3e358)
149 |
150 | ## 20180623
151 | - BoB [Agile and Blockchain](./agile-and-blockchain.md)
152 | - AmyWu [Hyperledger Fabric实践(1) 组建最简网络](https://www.jianshu.com/p/1b83cb9d9aa9)
153 | - 阿飞 [区块链-以太坊学习笔记(六)](https://blog.csdn.net/lxfgzm/article/details/80796459)
154 | - 胡键 HiBlock西安23号活动图文:[区块链周周记:兵器谱](https://www.jianshu.com/p/a10052a5bbd4)
155 | - 冯宇:[Hyperledger学习小结](https://www.jianshu.com/p/8294e7f441d1)
156 | - 笔名辉哥:[第十五课 手把手教你以太坊ENS域名注册,抢做一个3000万的发财梦!](https://www.jianshu.com/p/d4b951ff21b1)
157 |
158 | ## 20180616
159 | - AmyWu [Hyperledger Fabric构架简述之二 节点](https://www.jianshu.com/p/8097a7dde804)
160 | - 笔名辉哥 [第十二课 SOLIDITY语法难点解析及故障排查](https://www.jianshu.com/p/275ed3d7aeb7)
161 | - 冯宇 [Hyperledger Composer开发流程](https://www.jianshu.com/p/43000b5ebd3d)
162 | - 阿飞 [区块链-以太坊学习笔记(五)](https://blog.csdn.net/lxfgzm/article/details/80796382)
163 | - 胡键 [区块链周周记:Token](https://www.jianshu.com/p/1a1c449f848c)
164 | - BoB [ERC20 中文版](https://github.com/bobjiang/EIPs/blob/master/EIPS-CN/eip-20.md)
165 |
166 | ## 20180609
167 | - BoB [How to issue ERC875 token](https://github.com/HiBlock/non-fungible-token/blob/master/how-to-issue-erc875-token.md)
168 | - AmyWu [Hyperledger Fabric构架简述之一](https://www.jianshu.com/p/d0334265e33e)
169 | - 阿飞 [区块链-以太坊学习笔记(四)](https://blog.csdn.net/lxfgzm/article/details/80646578)
170 | - 冯宇 [Hyperledger Composer概念介绍](https://www.jianshu.com/p/ebb5f25bd3f7)
171 | - 笔名辉哥[第十四课 以太坊开发从入门到精通学习导航](https://www.jianshu.com/p/6851fb958220)
172 | - 胡键 [区块链周周记:一位初学者的观点](https://www.jianshu.com/p/5ffe26dfe369)
173 |
174 | ## 20180602
175 | - 笔名辉哥 - [第十三课 如何在DAPP应用实现自带钱包转账功能](https://www.jianshu.com/p/139a71c0c497)
176 | - 阿东 [怎样拥有硬件钱包?币博士手把手教你!](https://mp.weixin.qq.com/s/PFJDFqq4xQnhnhriORoisw)
177 | - AmyWu [Hyperledger的Composer和Fabric到底是什么关系?](https://www.jianshu.com/p/15cc600b340f)
178 | - 冯宇 [Linux环境下安装和使用Hyperledger Composer](https://www.jianshu.com/p/f20e3046c2a1)
179 | - 胡键 [Hyperledger Fabric周周记:权限](https://www.jianshu.com/p/c502db96db15)
180 | - 阿飞 [区块链-以太坊学习笔记(三)](https://blog.csdn.net/lxfgzm/article/details/80575346)
181 | - BoB [以太坊入门ppt](https://github.com/HiBlock/blockchain-learning/blob/develop/blockchain2.0-ethereum-introduction.pptx)
182 |
183 | ## 20180527
184 | - 胡键 [HyperLedger Fabric快速入门视频](https://m.qlchat.com/topic/details?topicId=2000001352286793)
185 | - 冯宇 [Hyperledger Fabric网络手工运行](https://www.jianshu.com/p/9b6265ee6f4a)
186 | - 笔名辉哥 - [第十一课 从宠物商店案例看DAPP架构和WEB3.JS交互接口](https://www.jianshu.com/p/47174718960b)
187 | - BoB [如何筹办区块链的黑客马拉松](./how-to-hold-blockathon.pdf)
188 | - 阿飞 [区块链-以太坊学习笔记(二)](https://blog.csdn.net/lxfgzm/article/details/80474443)
189 | - 毛明旺 [风格指南(style guide)说明----solidity 语言中文文档](https://mp.weixin.qq.com/s/dL9Q7KGA2QramQG05NSYRQ)
190 | - 毛明旺 [合约(Contracts)-- solidity语言中文文档](https://mp.weixin.qq.com/s/M-4fILUZ3AKcDVbsWiTcmw)
191 |
192 | ## 20180520
193 | - 阿东 - [区块链走向何方,或许从美国证劵史可以得到答案](https://github.com/cdtakumi/HiBlock-learning/wiki/%E5%8C%BA%E5%9D%97%E9%93%BE%E8%B5%B0%E5%90%91%E4%BD%95%E6%96%B9%EF%BC%8C%E6%88%96%E8%AE%B8%E4%BB%8E%E7%BE%8E%E5%9B%BD%E8%AF%81%E5%8A%B5%E5%8F%B2%E5%8F%AF%E4%BB%A5%E5%BE%97%E5%88%B0%E7%AD%94%E6%A1%88)
194 | - 笔名辉哥 -[第十课 Solidity语言编辑器REMIX指导大全](https://www.jianshu.com/p/2110ed61d2cc)
195 | - BoB [Smart contract traveller guide](./smart-contract-traveller-guides.md)
196 | - 冯宇 [Hyperledger Fabric模型和工具介绍](https://www.jianshu.com/p/dbca08046432)
197 | - 倔强的小红军 [CryptoZombies游戏学习Solidity笔记](./CryptoZombies游戏学习Solidity笔记.md)
198 | - 胡键 [Hyperledger Fabric周周记:Composer](https://www.jianshu.com/p/9ff2cca70981)
199 | - 阿飞 [区块链-以太坊学习笔记(一)](https://blog.csdn.net/lxfgzm/article/details/80399755)
200 | ## 20180513
201 | - BoB - 以太坊实战之环境准备:[Youtube观看](https://www.youtube.com/playlist?list=PLnP6dU8KobC-QzHcbHFWIBmHwoxPqKq9p) | [CSDN观看](https://edu.csdn.net/course/detail/8078)
202 | - 胡键 - [Hyperledger Fabric周周记:起源](https://www.jianshu.com/p/267ac1f2d67d)
203 | - 笔名辉哥 -[【以太坊实践】第九课 如何在Remix环境下进行Solidity代码单步调试](https://www.bihu.com/article/374536)
204 | - 冯宇 - [Linux环境下搭建Hyperledger Fabric 1.1开发环境](https://www.jianshu.com/p/749c16a32097)
205 | - 三万分之一 - [合约](https://github.com/HiBlock/blockchain-learning/blob/master/contracts.rst)
206 |
207 | ## 20180525
208 | - 笔名辉哥 - [第十一课 从宠物商店案例看DAPP架构和WEB3.JS交互接口](https://www.jianshu.com/p/47174718960b)
209 |
210 | ## 进度与内容
211 | 每周日进行整理,未完成输出,第一次警告,第二次直接清退
212 | [输出进度](https://docs.google.com/spreadsheets/d/1192TcjGNVEhPl470y5y2Z3aZ9So0Imzucxbkm5Nxvn0/edit?usp=sharing)
213 |
214 | ## 有关HiBlock区块链社区
215 |
216 | - [HiBlock github首页](https://github.com/HiBlock)
217 |
218 | HiBlock 秉承开放、协作、透明、链接、分享的价值观,致力打造一个专注于区块链的开发者社区,我们不仅在开发者中宣传推广区块链,还会帮助开发者真正掌握区块链技术和应用。我们有线上活动(如一起译文档、一起学以太坊、一起学EOS等),有培训课程(提供专业的区块链技术培训 http://hiblock.net/topics/node16 )、也有线下沙龙聚会(全国各城进行线下交流),还有blockathon(链接全球区块链开发者)。详情参考:https://github.com/HiBlock/hiblock/tree/master/meetup
219 |
--------------------------------------------------------------------------------
/contracts.rst:
--------------------------------------------------------------------------------
1 | .. index:: ! contract
2 |
3 | ##########
4 | 合约
5 | ##########
6 |
7 | Solidity 合约类似于面向对象语言中的类。合约中有用于数据持久化的状态变量,和可以修改状态变量的函数。
8 | 调用另一个合约实例的函数时,会执行一个 EVM 函数调用,这个操作会切换执行时的上下文,这样,前一个合约的状态变量就不能访问了。
9 |
10 | .. index:: ! contract;creation, constructor
11 |
12 | ******************
13 | 创建合约
14 | ******************
15 |
16 | 可以通过以太坊交易 "从外部" 或从 Solidity 合约内部创建合约。
17 | 集成开发环境,像 `Remix `_, 使用用户界面元素流畅的创建合约。
18 | 在以太坊上编程创建合约最好使用 JavaScript API `web3.js `_。
19 | 从今天开始,有一个名为 `web3.eth.Contract `_ 的方法能够更容易的创建合约。
20 |
21 | 创建合约时,会执行一次构造函数(与合约同名的函数)。
22 | 构造函数是可选的。 只允许有一个构造函数,这意味着不支持重载。
23 |
24 | .. index:: constructor;arguments
25 |
26 | 在内部,构造函数参数在合约代码之后通过 :ref:`ABI 编码 `,但是如果你使用 ``web3.js``
27 | 则不必关心这个问题。
28 |
29 | 如果一个合约想要创建另一个合约,那么创建者必须知晓被创建合约的源代码(和二进制)。
30 | 这意味着不可能循环创建依赖项。
31 |
32 | ::
33 |
34 | pragma solidity ^0.4.16;
35 |
36 | contract OwnedToken {
37 | // TokenCreator 是如下定义的合约类型.
38 | // 不创建新合约的话,也可以引用它。
39 | TokenCreator creator;
40 | address owner;
41 | bytes32 name;
42 |
43 | // 这是注册 creator 和分配名称的构造函数。
44 | function OwnedToken(bytes32 _name) public {
45 | // 状态变量通过其名称访问,而不是通过例如 this.owner.
46 | // 这也适用于函数,特别是在构造函数中,你只能那样调用他们("内部调用"),
47 | // 因为合约本身还不存在。
48 | owner = msg.sender;
49 | // 从 `address` 到 `TokenCreator` ,我们做显式的类型转换
50 | // 并且假定调用合约的类型是 TokenCreator,没有真正的检查方法。
51 | creator = TokenCreator(msg.sender);
52 | name = _name;
53 | }
54 |
55 | function changeName(bytes32 newName) public {
56 | // 只有 creator 能够更改名称 -- 因为合约是隐式转换为地址的,
57 | // 所以这里的比较是可能的。
58 | if (msg.sender == address(creator))
59 | name = newName;
60 | }
61 |
62 | function transfer(address newOwner) public {
63 | // 只有当前所有者才能传送权证
64 | if (msg.sender != owner) return;
65 | // 我们还想确认 creator 是否权证转移是正常操作。
66 | // 请注意,这里调用了一个下面定义的合约中的函数。
67 | // 如果调用失败(比如,由于 gas 不足),会立即停止执行。
68 | if (creator.isTokenTransferOK(owner, newOwner))
69 | owner = newOwner;
70 | }
71 | }
72 |
73 | contract TokenCreator {
74 | function createToken(bytes32 name)
75 | public
76 | returns (OwnedToken tokenAddress)
77 | {
78 | // 创建一个新的权证合约并且返回它的地址。
79 | // 从 JavaScript 方面来说,返回类型是简单的 `address` 类型,这是因为
80 | // 这是在 ABI 中最接近的类型。
81 | return new OwnedToken(name);
82 | }
83 |
84 | function changeName(OwnedToken tokenAddress, bytes32 name) public {
85 | // 同样,`tokenAddress` 的外部类型也是 `address` 。
86 | tokenAddress.changeName(name);
87 | }
88 |
89 | function isTokenTransferOK(address currentOwner, address newOwner)
90 | public
91 | view
92 | returns (bool ok)
93 | {
94 | // 检查一些任意的情况。
95 | address tokenAddress = msg.sender;
96 | return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff);
97 | }
98 | }
99 |
100 | .. index:: ! visibility, external, public, private, internal
101 |
102 | .. _visibility-and-getters:
103 |
104 | **********************
105 | 可见性和 getter 函数
106 | **********************
107 |
108 | 由于 Solidity 有两种函数调用(内部调用不会产生实际的 EVM 调用(也称为
109 | 一个“消息调用”)和外部调用),有四种函数可见性类型和状态变量。
110 |
111 | 函数可以指定为 ``external`` ,``public`` ,``internal`` 或者 ``private`` ,
112 | 默认情况下函数类型为 ``public`` 。对于状态变量,不能设置为 ``external`` ,默认
113 | 是 ``internal`` 。
114 |
115 | ``external`` :
116 | 外部函数作为合约接口的一部分,意味着我们可以从其他合约和交易中调用。一个外部函数
117 | ``f`` 不能从内部调用(比如 ``f`` 不起作用,但 ``this.f()`` 可以)。
118 | 当收到大量数据的时候,外部函数有时候会更有效率。
119 |
120 | ``public`` :
121 | 公共函数是合约接口的一部分,可以在内部或通过消息调用。对于公共状态变量,
122 | 会自动生成一个 getter 函数(见下面)。
123 |
124 | ``internal`` :
125 | 这些函数和状态变量只能是内部访问(即从当前合约内部或从它派生的合约访问),不使用 ``this`` 调用。
126 |
127 | ``private`` :
128 | 私有函数和状态变量仅在当前定义它们的合约中使用,并且不能被派生合约使用。
129 |
130 | .. note::
131 | 合约中的所有内容对外部观察者都是可见的。设置一些 ``private`` 类型只能阻止其他合约访问和修改这些信息,
132 | 但是对于区块链外的整个世界它仍然是可见的。
133 |
134 | 可见性的标识符的定义位置,对于状态变量来说是在类型后面,对于函数是在参数列表和返回关键字中间。
135 |
136 | ::
137 |
138 | pragma solidity ^0.4.16;
139 |
140 | contract C {
141 | function f(uint a) private pure returns (uint b) { return a + 1; }
142 | function setData(uint a) internal { data = a; }
143 | uint public data;
144 | }
145 |
146 | 在下面的例子中,``D`` 可以调用 ``c.getData()`` 来获取 ``data`` 的值,但不能调用 ``f`` 。
147 | 合约 ``E`` 继承自 ``C`` ,因此可以调用 ``compute``。
148 |
149 | ::
150 |
151 | // 下面代码编译错误
152 |
153 | pragma solidity ^0.4.0;
154 |
155 | contract C {
156 | uint private data;
157 |
158 | function f(uint a) private returns(uint b) { return a + 1; }
159 | function setData(uint a) public { data = a; }
160 | function getData() public returns(uint) { return data; }
161 | function compute(uint a, uint b) internal returns (uint) { return a+b; }
162 | }
163 |
164 | contract D {
165 | function readData() public {
166 | C c = new C();
167 | uint local = c.f(7); // 错误:成员 `f` 不可见
168 | c.setData(3);
169 | local = c.getData();
170 | local = c.compute(3, 5); // 错误:成员 `compute` 不可见
171 | }
172 | }
173 |
174 | contract E is C {
175 | function g() public {
176 | C c = new C();
177 | uint val = compute(3, 5); // 访问内部成员(从继承合约访问父合约成员)
178 | }
179 | }
180 |
181 | .. index:: ! getter;function, ! function;getter
182 | .. _getter-functions:
183 |
184 | Getter 函数
185 | ================
186 |
187 | 编译器自动为所有 **公有** 状态变量创建 getter 函数。 对于下面给出的合约,编译器会生成一个名为 ``data``
188 | 的函数,该函数不会接收任何参数并返回一个 ``uint`` ,即状态变量 ``data`` 的值。 可以在声明时完成状态
189 | 变量的初始化。
190 |
191 | ::
192 |
193 | pragma solidity ^0.4.0;
194 |
195 | contract C {
196 | uint public data = 42;
197 | }
198 |
199 | contract Caller {
200 | C c = new C();
201 | function f() public {
202 | uint local = c.data();
203 | }
204 | }
205 |
206 | getter 函数具有外部可见性。 如果在内部访问 getter(即没有 ``this.`` ),它被认为一个状态变量。 如果
207 | 它是外部访问的(即用 ``this.`` ),它被认为为一个函数。
208 |
209 | ::
210 |
211 | pragma solidity ^0.4.0;
212 |
213 | contract C {
214 | uint public data;
215 | function x() public {
216 | data = 3; // 内部访问
217 | uint val = this.data(); // 外部访问
218 | }
219 | }
220 |
221 | 下一个例子稍微复杂一些:
222 |
223 | ::
224 |
225 | pragma solidity ^0.4.0;
226 |
227 | contract Complex {
228 | struct Data {
229 | uint a;
230 | bytes3 b;
231 | mapping (uint => uint) map;
232 | }
233 | mapping (uint => mapping(bool => Data[])) public data;
234 | }
235 |
236 | 这将会生成以下形式的函数::
237 |
238 | function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b) {
239 | a = data[arg1][arg2][arg3].a;
240 | b = data[arg1][arg2][arg3].b;
241 | }
242 |
243 | 请注意,因为没有好的方法来提供映射的键,所以结构中的映射被省略。
244 |
245 | .. index:: ! function;modifier
246 |
247 | .. _modifiers:
248 |
249 | ******************
250 | 函数修改器
251 | ******************
252 |
253 | 使用修改器可以轻松改变函数的行为。 例如,它们可以在执行该功能之前自动检查条件。 修改器是合约的可继承属性,
254 | 并可能被派生合约覆盖。
255 |
256 | ::
257 |
258 | pragma solidity ^0.4.11;
259 |
260 | contract owned {
261 | function owned() public { owner = msg.sender; }
262 | address owner;
263 |
264 | // 这个合约只定义一个修改器,但并未使用: 它将会在派生合约中用到。
265 | // 将函数体插入到特殊符号 `_;` 出现的位置。
266 | // 这意味着如果是 owner 调用这个函数,则函数会被执行,否则则会抛出异常。
267 |
268 | modifier onlyOwner {
269 | require(msg.sender == owner);
270 | _;
271 | }
272 | }
273 |
274 | contract mortal is owned {
275 | // 这个合约从 `owned` 继承了 `onlyOwner` 修饰符,并并将其应用于 `close` 函数,
276 | // 只有存储的拥有者调用 `close` 函数,才会生效。
277 |
278 | function close() public onlyOwner {
279 | selfdestruct(owner);
280 | }
281 | }
282 |
283 | contract priced {
284 | // 修改器可以接收参数:
285 | modifier costs(uint price) {
286 | if (msg.value >= price) {
287 | _;
288 | }
289 | }
290 | }
291 |
292 | contract Register is priced, owned {
293 | mapping (address => bool) registeredAddresses;
294 | uint price;
295 |
296 | function Register(uint initialPrice) public { price = initialPrice; }
297 |
298 | // 重要的是这里也应该提供 `payable` 关键字,否则函数会自动拒绝所有发送给它的以太币。
299 | function register() public payable costs(price) {
300 | registeredAddresses[msg.sender] = true;
301 | }
302 |
303 | function changePrice(uint _price) public onlyOwner {
304 | price = _price;
305 | }
306 | }
307 |
308 | contract Mutex {
309 | bool locked;
310 | modifier noReentrancy() {
311 | require(!locked);
312 | locked = true;
313 | _;
314 | locked = false;
315 | }
316 |
317 | // 这个函数受互斥量保护,这意味着 `msg.sender.call` 中的可重入调用不能再次调用 `f` 。
318 | // `return 7` 语句指定返回值为7,但仍然是在修改器中执行语句 `locked = false` 。
319 |
320 | function f() public noReentrancy returns (uint) {
321 | require(msg.sender.call());
322 | return 7;
323 | }
324 | }
325 |
326 | 如果同一个函数有多个修改器,它们之间以空格隔开,修饰器会依次检查执行。
327 |
328 | .. warning::
329 | 在早期的Solidity版本中,有修改器的函数, ``return`` 语句的行为表现不同。
330 |
331 | 从修改器或函数体的显式的 return 语句仅仅跳出当前的修改器和函数体。 返回变量会被赋值,但整个执行
332 | 逻辑会在前一个修改器后面定义的 "_" 后继续执行。
333 |
334 | 修改器的参数可以是任意表达式,在上下文中,所有的函数中引入的符号,在修改器中均可见。在修改器中
335 | 引入的符号在函数中不可见(可能被重载改变)。
336 |
337 | .. index:: ! constant
338 |
339 | ************************
340 | 常量
341 | ************************
342 |
343 | 状态变量可以被声明为 ``constant`` 。这种情况下,必须在编译阶段将他们指定为常量。不允许任何访问 storage,区
344 | 块链数据(例如 ``now``, ``this.balance`` 或者 ``block.number``)或执行数据( ``msg.gas`` )
345 | 或调用外部合约。允许表达式可能会对内存分配产生副作用,但不允许可能会对其他内存对象产生
346 | 副作用。 允许内置的函数,比如 ``keccak256``,``sha256``,``ripemd160``,``ecrecover``,``addmod``
347 | 和 ``mulmod`` (即使他们确实调用外部合约)。
348 |
349 | 允许内存分配,从而带来可能的副作用的原因是因为这将允许构建复杂的对象,比如,查找表。
350 | 此功能尚未完全可用。
351 |
352 | 编译器不会为这些变量预留存储,每个使用的常量都会被对应的常量表达式所替换(也许优化器会直接替换为常量表达式的结果值)
353 |
354 | 不是所有的类型都支持常量,当前支持的仅有值类型和字符串。
355 |
356 | ::
357 |
358 | pragma solidity ^0.4.0;
359 |
360 | contract C {
361 | uint constant x = 32**22 + 8;
362 | string constant text = "abc";
363 | bytes32 constant myHash = keccak256("abc");
364 | }
365 |
366 | .. index:: ! functions
367 |
368 | .. _functions:
369 |
370 | *********
371 | 函数
372 | *********
373 |
374 | .. index:: ! view function, function;view
375 |
376 | .. _view-functions:
377 |
378 | View 函数
379 | ==============
380 |
381 | 可以将函数声明为 ``view`` 类型,这种情况下要保证不修改状态变量。
382 |
383 | 下面的语句被认为是修改状态:
384 |
385 | #. 写状态变量.
386 | #. :ref:`发送事件 `。
387 | #. :ref:`创建其它合约 `。
388 | #. 使用 ``selfdestruct``。
389 | #. 通过调用发送以太币。
390 | #. 调用任何没有标记为 ``view`` 或者 ``pure`` 的函数.
391 | #. 使用低级调用。
392 | #. 使用包含特定操作码的内联汇编。
393 |
394 | ::
395 |
396 | pragma solidity ^0.4.16;
397 |
398 | contract C {
399 | function f(uint a, uint b) public view returns (uint) {
400 | return a * (b + 42) + now;
401 | }
402 | }
403 |
404 | .. note::
405 | ``constant`` 是 ``view`` 的别名。
406 |
407 | .. note::
408 | Getter 方法被标记为 ``view``。
409 |
410 | .. warning::
411 | 编译器没有强制 ``view`` 方法不能修改状态变量。
412 |
413 | .. index:: ! pure function, function;pure
414 |
415 | .. _pure-functions:
416 |
417 | pure 函数
418 | ==============
419 |
420 | 函数可以声明为 ``pure`` ,在这种情况下,承诺不读取或修改状态。
421 |
422 | 除了上面解释的状态修改语句列表之外,以下被认为是从状态中读取:
423 |
424 | #. 读取状态变量。
425 | #. 访问 ``this.balance`` 或者 ``.balance``。
426 | #. 访问 ``block``,``tx``, ``msg`` 中任意成员 (除 ``msg.sig`` 和 ``msg.data`` 之外)。
427 | #. 调用任何未标记为 ``pure`` 的函数。
428 | #. 使用包含某些操作码的内联汇编。
429 |
430 | ::
431 |
432 | pragma solidity ^0.4.16;
433 |
434 | contract C {
435 | function f(uint a, uint b) public pure returns (uint) {
436 | return a * (b + 42);
437 | }
438 | }
439 |
440 | .. warning::
441 | 编译器没有强制 ``pure`` 方法不能读取状态。
442 |
443 | .. index:: ! fallback function, function;fallback
444 |
445 | .. _fallback-function:
446 |
447 | Fallback 函数
448 | =================
449 |
450 | 合约可以有一个未命名的函数。这个函数不能有参数也不能有返回值。
451 | 如果合约中没有与给定的函数标识符匹配的函数,将调用未命名函数(或者如果根本没有提供数据)。
452 |
453 | 此外,当合约收到以太币(没有任何数据),这个函数就会执行。 此外,为了接收以太币,fallback 函数
454 | 必须标记为 ``payable``。 如果不存在这样的函数,则合约不能通过常规交易接收以太币。
455 |
456 | 在这种上下文中,函数调用通常只消耗很少的 gas(准确地说,2300 个 gas ),所以重要的是使 fallback 函数尽可能便宜。
457 | 请注意,调用 fallback 函数的交易(而不是内部呼叫)所需的 gas 要高得多,因为每次交易都会额外收取 21000 gas 或更多的费用,
458 | 用于签名检查等事情。
459 |
460 | 特别的,以下操作会消耗比 fallback 函数更多的 gas:
461 |
462 | - 写入存储
463 | - 创建合约
464 | - 调用消耗大量 gas 的外部函数
465 | - 发送以太币
466 |
467 |
468 | 请确保您在部署合约之前彻底测试您的 fallback 函数,以确保执行成本低于 2300 个 gas 。
469 |
470 | .. note::
471 | 即使 fallback 函数不能有参数,仍然可以使用 ``msg.data`` 来获取随调用提供的任何有效负载。
472 |
473 | .. warning::
474 | 一个没有定义 fallback 函数的合约,直接接收以太币(没有函数调用,即使用 ``send`` 或 ``transfer``)会抛出一个异常,
475 | 返还以太币(在Solidity v0.4.0之前行为会有所不同)。 所以如果你想让你的合约接收以太币,必须实现 fallback 函数。
476 |
477 | .. warning::
478 |
479 | 一个没有可支付的 fallback 函数的合约,可以作为 `coinbase transaction` (又名 `miner block reward` )的接收者或者作为 ``selfdestruct`` 的目的地来接收以太币。
480 | 对这种以太币转移合约不能作出反应,因此也不能拒绝它们。 这是 EVM 的设计选择,而且 Solidity 无法解决这个问题。
481 | 这也意味着 ``this.balance`` 可以高于合约中实现的一些手工记帐的总和(即,在 fallback 函数中更新的计数器)。
482 | ::
483 |
484 | pragma solidity ^0.4.0;
485 |
486 | contract Test {
487 | // 发送到这个合约的所有消息都会调用此函数(因为该合约没有其它函数)。
488 | // 向这个合约发送以太币会导致异常,因为 fallback 函数没有 `payable` 修饰符
489 | function() public { x = 1; }
490 | uint x;
491 | }
492 |
493 |
494 | // 这个合约会保留所有发送给它的以太币,没有办法返还。
495 | contract Sink {
496 | function() public payable { }
497 | }
498 |
499 | contract Caller {
500 | function callTest(Test test) public {
501 | test.call(0xabcdef01); // 不存在的哈希
502 | // 导致 test.x 变成 == 1。
503 |
504 | // 以下将不会编译,但如果有人向该合约发送以太币,交易将失败并拒绝以太币。
505 | // test.send(2 ether);
506 | }
507 | }
508 |
509 | .. index:: ! overload
510 |
511 | .. _overload-function:
512 |
513 | 函数重载
514 | ====================
515 |
516 | 合约可以具有多个不同参数的同名函数。这也适用于继承函数。 以下示例展示了合约 ``A`` 中的重载函数 ``f``。
517 |
518 | ::
519 |
520 | pragma solidity ^0.4.16;
521 |
522 | contract A {
523 | function f(uint _in) public pure returns (uint out) {
524 | out = 1;
525 | }
526 |
527 | function f(uint _in, bytes32 _key) public pure returns (uint out) {
528 | out = 2;
529 | }
530 | }
531 |
532 | 重载函数也存在于外部接口中。 如果两个外部可见函数接收的 Solidity 类型不同但是外部类型相同会导致错误。
533 |
534 | ::
535 |
536 | // This will not compile
537 | pragma solidity ^0.4.16;
538 |
539 | contract A {
540 | function f(B _in) public pure returns (B out) {
541 | out = _in;
542 | }
543 |
544 | function f(address _in) public pure returns (address out) {
545 | out = _in;
546 | }
547 | }
548 |
549 | contract B {
550 | }
551 |
552 | 以上两个 ``f`` 函数重载都接受了 ABI 的地址类型,虽然它们在 Solidity 中被认为是不同的。
553 |
554 | 重载解析和参数匹配
555 | -----------------------------------------
556 |
557 | 通过将当前范围内的函数声明与函数调用中提供的参数相匹配,可以选择重载函数。如果所有参数都可以隐式地转换为预期类型,
558 | 则选择函数作为重载候选项。如果没有一个候选,解析失败。
559 |
560 | .. note::
561 | 返回参数不作为重载解析的依据。
562 |
563 | ::
564 |
565 | pragma solidity ^0.4.16;
566 |
567 | contract A {
568 | function f(uint8 _in) public pure returns (uint8 out) {
569 | out = _in;
570 | }
571 |
572 | function f(uint256 _in) public pure returns (uint256 out) {
573 | out = _in;
574 | }
575 | }
576 |
577 | 调用 ``f(50)`` 会导致类型错误,因为 ``50`` 既可以被隐式转换为 ``uint8`` 也可以被隐式转换为 ``uint256``。
578 | 另一方面,调用 ``f(256)`` 则会解析为 ``f(uint256)`` 重载,因为 ``256`` 不能隐式转换为 ``uint8``。
579 |
580 | .. index:: ! event
581 |
582 | .. _events:
583 |
584 | ******
585 | 事件
586 | ******
587 |
588 | 通过事件可以方便地使用 EVM 日志记录工具,在一个dapp的接口中,它可以反过来 "调用" Javascript 的监听事件的回调。
589 |
590 | 事件在合约中可被继承。 当他们被调用时,会触发参数存储到交易的日志中 - 一种区块链中的特殊数据结构。
591 | 这些日志与地址相关联,被并入区块链中,只要区块可以访问就一直存在(至少 Frontier,Homestead 是这样,但 Serenity 也许不是这样)。
592 | 日志和事件在合约内不可直接被访问(甚至是创建日志的合约也不能访问)。
593 |
594 | 日志的 SPV 验证是可能的,如果一个外部的实体提供了这样验证的合约,它可以实际检查日志在区块链中是否存在。
595 | 但需要留意的是,由于合约中仅能访问最近的 256 个区块哈希,所以还需要提供区块头信息。
596 |
597 | 可以最多有三个参数被设置为 ``indexed``,来设置是否被索引:在用户界面上可以按索引参数的特定值来过滤。
598 |
599 | 如果数组(包括 ``string`` 和 ``bytes``)类型被标记为索引项,则它存储的 Keccak-256 哈希值作为主题索引。
600 |
601 | 除非你用 ``anonymous`` 说明符声明事件,否则事件签名的哈希值是主题之一。同时也意味着对于匿名事件无法通过名字来过滤。
602 |
603 | 所有非索引参数都将存储在日志的数据部分中。
604 |
605 | .. note::
606 | 索引参数不会自行存储。 你只能按值进行搜索,但不可能检索值本身。
607 |
608 | ::
609 |
610 | pragma solidity ^0.4.0;
611 |
612 | contract ClientReceipt {
613 | event Deposit(
614 | address indexed _from,
615 | bytes32 indexed _id,
616 | uint _value
617 | );
618 |
619 | function deposit(bytes32 _id) public payable {
620 | // 任何对这个函数的调用(甚至是深度嵌套)都可以过滤被调用的 `Deposit` 来被 JavaScript API 检测到。
621 |
622 | Deposit(msg.sender, _id, msg.value);
623 | }
624 | }
625 |
626 | 在 JavaScript API 的用法如下:
627 |
628 | ::
629 |
630 | var abi = /* abi as generated by the compiler */;
631 | var ClientReceipt = web3.eth.contract(abi);
632 | var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */);
633 |
634 | var event = clientReceipt.Deposit();
635 |
636 | // 监视变化
637 | event.watch(function(error, result){
638 | // 结果包括对 `Deposit` 的调用参数在内的各种信息。
639 |
640 | if (!error)
641 | console.log(result);
642 | });
643 |
644 | // 或者通过回调立即开始观察
645 | var event = clientReceipt.Deposit(function(error, result) {
646 | if (!error)
647 | console.log(result);
648 | });
649 |
650 | .. index:: ! log
651 |
652 | 日志的底层接口
653 | ===========================
654 |
655 | 通过函数 ``log0``,``log1``, ``log2``, ``log3`` 和 ``log4`` 可以访问日志机制的底层接口。
656 | ``logi`` 表示总共有带 ``i + 1`` 个 ``bytes32`` 类型的参数。其中第一个参数会被用来做为日志的数据部分,
657 | 其它的会做为主题。上面的事件调用可以以相同的方式执行。
658 |
659 | ::
660 |
661 | pragma solidity ^0.4.10;
662 |
663 | contract C {
664 | function f() public payable {
665 | bytes32 _id = 0x420042;
666 | log3(
667 | bytes32(msg.value),
668 | bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
669 | bytes32(msg.sender),
670 | _id
671 | );
672 | }
673 | }
674 |
675 | 长十六进制数等于 ``keccak256("Deposit(address,hash256,uint256)")``,即事件的签名。
676 |
677 | 了解事件的其他资源
678 | ==============================================
679 |
680 | - `Javascript 文档 `_
681 | - `事件使用例程 `_
682 | - `如何在 js 中访问它们 `_
683 |
684 | .. index:: ! inheritance, ! base class, ! contract;base, ! deriving
685 |
686 | ***********
687 | 继承
688 | ***********
689 |
690 | 通过复制包括多态的代码,Solidity 支持多重继承。
691 |
692 | 所有的函数调用都是虚拟的,这意味着最远的派生函数会被调用,除非明确给出合约名称。
693 |
694 | 当一个合约从多个合约继承时,在区块链上只有一个合约被创建,所有基类合约的代码被复制到创建的合约中。
695 |
696 | 总的继承系统与 `Python's `_, 非常
697 | 相似,特别是多重继承方面。
698 |
699 | 下面的例子进行了详细的说明。
700 |
701 | ::
702 |
703 | pragma solidity ^0.4.16;
704 |
705 | contract owned {
706 | function owned() { owner = msg.sender; }
707 | address owner;
708 | }
709 |
710 | // 使用`is`从另一个合约派生。派生合约可以访问所有非私有成员,包括
711 | // 内部函数和状态变量。 不过,这些不可能通过 `this` 来外部访问。
712 |
713 | contract mortal is owned {
714 | function kill() {
715 | if (msg.sender == owner) selfdestruct(owner);
716 | }
717 | }
718 |
719 | // 这些抽象合约仅用于给编译器提供接口。注意函数没有函数体。如果一个合约没有实现所有函数,则只能用作接口。
720 |
721 | contract Config {
722 | function lookup(uint id) public returns (address adr);
723 | }
724 |
725 | contract NameReg {
726 | function register(bytes32 name) public;
727 | function unregister() public;
728 | }
729 |
730 | // 可以多重继承。 请注意,`owned` 也是 `mortal` 的基类,但只有一个 `owned` 实例(如C ++中的虚拟继承)。
731 | contract named is owned, mortal {
732 | function named(bytes32 name) {
733 | Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
734 | NameReg(config.lookup(1)).register(name);
735 | }
736 |
737 | // 函数可以被另一个具有相同名称和相同数量/类型输入的函数重载。如果重载函数有不同类型的输出参数,会导致错误。
738 | // 本地和基于消息的函数调用都会考虑这些重载。
739 | function kill() public {
740 | if (msg.sender == owner) {
741 | Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
742 | NameReg(config.lookup(1)).unregister();
743 | // 仍然可以调用特定的重载函数。
744 | mortal.kill();
745 | }
746 | }
747 | }
748 |
749 | // 如果构造函数接受参数,则需要在头文件中提供(或修改器调用样式)派生合约的构造函数(见下文)。
750 | contract PriceFeed is owned, mortal, named("GoldFeed") {
751 | function updateInfo(uint newInfo) public {
752 | if (msg.sender == owner) info = newInfo;
753 | }
754 |
755 | function get() public view returns(uint r) { return info; }
756 |
757 | uint info;
758 | }
759 |
760 | 请注意,我们调用 ``mortal.kill()`` 来调用父合约的销毁请求。这样做法是有问题的,就像
761 | 在下面的例子中看到::
762 |
763 | pragma solidity ^0.4.0;
764 |
765 | contract owned {
766 | function owned() public { owner = msg.sender; }
767 | address owner;
768 | }
769 |
770 | contract mortal is owned {
771 | function kill() public {
772 | if (msg.sender == owner) selfdestruct(owner);
773 | }
774 | }
775 |
776 | contract Base1 is mortal {
777 | function kill() public { /* do cleanup 1 */ mortal.kill(); }
778 | }
779 |
780 | contract Base2 is mortal {
781 | function kill() public { /* do cleanup 2 */ mortal.kill(); }
782 | }
783 |
784 | contract Final is Base1, Base2 {
785 | }
786 |
787 | 调用 ``Final.kill()`` 会调用 最远的派生重载函数 ``Base2.kill``,但是会绕过 ``Base1.kill``,
788 | 基本上因为它甚至不知道 ``Base1``。解决这个问题的方法是使用 ``super``::
789 |
790 | pragma solidity ^0.4.0;
791 |
792 | contract owned {
793 | function owned() public { owner = msg.sender; }
794 | address owner;
795 | }
796 |
797 | contract mortal is owned {
798 | function kill() public {
799 | if (msg.sender == owner) selfdestruct(owner);
800 | }
801 | }
802 |
803 | contract Base1 is mortal {
804 | function kill() public { /* do cleanup 1 */ super.kill(); }
805 | }
806 |
807 |
808 | contract Base2 is mortal {
809 | function kill() public { /* do cleanup 2 */ super.kill(); }
810 | }
811 |
812 | contract Final is Base1, Base2 {
813 | }
814 |
815 | 如果 ``Base2`` 调用 ``super`` 的函数,它不会简单在其基类合约上调用该函数。 相反,它
816 | 在最终的继承关系图谱的下一个基类合约中调用这个函数,所以它会调用 ``Base1.kill()`` (注意
817 | 最终的继承序列是 -- 从最远派生合约开始:Final, Base2, Base1, mortal, ownerd)。
818 | 在类中使用 super 调用的实际函数在当前类的上下文中是未知的,尽管它的类型是已知的。 这与普通的
819 | 虚拟方法查找类似。
820 |
821 | .. index:: ! constructor
822 |
823 | 基类构造函数的参数
824 | ===============================
825 |
826 | 派生合约需要提供基类构造函数需要的所有参数。这可以通过两种方式来完成::
827 |
828 | pragma solidity ^0.4.0;
829 |
830 | contract Base {
831 | uint x;
832 | function Base(uint _x) public { x = _x; }
833 | }
834 |
835 | contract Derived is Base(7) {
836 | function Derived(uint _y) Base(_y * _y) public {
837 | }
838 | }
839 |
840 | 一种方法直接在继承列表中调用基类构造函数(``is Base(7)``)。另一种方法是像修改器使用方法一样,
841 | 作为派生合约构造函数定义头的一部分,(``Base(_y * _y)``)。
842 | 如果构造函数参数是常量并且定义或描述了合约的行为,使用第一种方法比较方便。如果基类构造函数的参数依赖于派生合约,那么
843 | 必须使用第二种方法。如果,像这个简单的例子一样,两个地方都用到了,优先使用修改器风格的参数。
844 |
845 | .. index:: ! inheritance;multiple, ! linearization, ! C3 linearization
846 |
847 | 多重继承与线性化
848 | ======================================
849 |
850 | 编程语言实现多重继承需要解决几个问题。一个问题是 `钻石问题 `_。
851 | Solidity 借鉴了 Python 的方式并且使用 "`C3 线性化 `_" 强制将基类合约转换一个有向无环图(DAG)
852 | 的特定顺序。这导致了我们所希望的单调性,但是却禁止了某些继承图。特别是,基类在 ``is`` 后面的顺序很重要。在下面的代码中,Solidity 将会报错
853 | "Linearization of inheritance graph impossible" 。
854 |
855 | ::
856 |
857 | // 下面代码编译出错
858 |
859 | pragma solidity ^0.4.0;
860 |
861 | contract X {}
862 | contract A is X {}
863 | contract C is A, X {}
864 |
865 | 原因是 ``C`` 请求 ``X`` 重写 ``A`` (因为定义的顺序是 ``A, X``),但是 ``A``本身要求重写
866 | ``X``,无法解决这种冲突。
867 |
868 | 一个指定基类合约的继承顺序的简单原则是从 "most base-like" 到 "most derived"。
869 |
870 | 继承有相同名字的不同类型成员
871 | ======================================================
872 |
873 | 一种错误情况是继承导致一个合约同时存在相同名字的修改器和函数时。另一种错误情况是继承导致的事件和修改器重名,函数和修改器重名。
874 | 有一种例外情况,状态变量的 getter 可以覆盖一个公有函数。
875 |
876 | .. index:: ! contract;abstract, ! abstract contract
877 |
878 | .. _abstract-contract:
879 |
880 | ******************
881 | 抽象合约
882 | ******************
883 |
884 | 合约函数可以缺少实现,如下例所示(请注意函数声明头由 ``;`` 结尾)
885 | ::
886 | pragma solidity ^0.4.0;
887 |
888 | contract Feline {
889 | function utterance() public returns (bytes32);
890 | }
891 |
892 | 这些合约无法成功编译(即使它们除了未实现的函数还包含其他已经实现了的函数),但他们可以用作基类合约::
893 |
894 | pragma solidity ^0.4.0;
895 |
896 | contract Feline {
897 | function utterance() public returns (bytes32);
898 | }
899 |
900 | contract Cat is Feline {
901 | function utterance() public returns (bytes32) { return "miaow"; }
902 | }
903 |
904 | 如果合约继承自抽象合约,并且不通过重写实现所有未实现的函数,那么它本身就是抽象的。
905 |
906 | .. index:: ! contract;interface, ! interface contract
907 |
908 | **********
909 | 接口
910 | **********
911 |
912 | 接口类似于抽象合约,但是它们不能实现任何函数。还有进一步的限制:
913 |
914 | #. 无法继承其他合约或接口。
915 | #. 无法定义构造函数。
916 | #. 无法定义变量。
917 | #. 无法定义结构体
918 | #. 无法定义枚举。
919 |
920 | 将来可能会解除这些限制。
921 |
922 | 接口基本上仅限于合约 ABI 可以表示的内容,并且 ABI 和接口之间的转换应该不会丢失任何信息。
923 |
924 | 接口由它们自己的关键字表示:
925 |
926 | ::
927 |
928 | pragma solidity ^0.4.11;
929 |
930 | interface Token {
931 | function transfer(address recipient, uint amount) public;
932 | }
933 |
934 | 就像继承其他合约一样,合约可以继承接口。
935 |
936 | .. index:: ! library, callcode, delegatecall
937 |
938 | .. _libraries:
939 |
940 | ************
941 | 库
942 | ************
943 |
944 | 库与合约类似,但其用途是在指定的地址仅部署一次,并且代码被使用 EVM 的 ``DELEGATECALL`` (Homestead 之前使用 ``CALLCODE`` 关键字)特性。
945 | 这意味着如果库函数被调用,它的代码在调用合约的上下文中执行,即 ``this`` 指向调用合约,特别是可以访问调用合约的存储。
946 | 因为一个合约是一个独立的代码块,它仅可以访问调用合约明确提供的状态变量(否则无法命名它们)。 如果不修改状态变量(即,如果是 ``view`` 或者 ``pure`` 函数),
947 | 库函数只能被直接调用(即不使用 ``DELEGATECALL`` 关键字),因为库被假定为无状态的。特别是,除非绕过 Solidity 类型系统,否则库不可能破坏。
948 |
949 | 使用库的合约,可以认为库是隐式的基类合约。虽然它们在继承关系中不会显式可见,但调用库函数与调用显式的基类合约十分类似(如果 ``L`` 是库的话,
950 | 使用 ``L.f()`` 调用库函数)。此外,就像库是基类一样,对所有使用库的合约,库的 ``internal`` 函数都是可见的。当然,需要使用内部调用约定
951 | 来调用内部函数,这意味着所有所有内部类型,内存类型都是通过引用而不是复制来传递。为了在 EVM 中实现这些,内部库函数的代码和从其中调用的所有
952 | 函数都在编译阶段被拉取到调用合约中,然后使用一个 ``JUMP`` 调用来代替 ``DELEGATECALL``。
953 |
954 | .. index:: using for, set
955 |
956 | 下面的示例说明如何使用库(但是请务必检查 :ref:`using for ` 有一个实现 set 更好的例子)。
957 |
958 | ::
959 |
960 | pragma solidity ^0.4.16;
961 |
962 | library Set {
963 | // 我们定义了一个新的结构体数据类型,用于在调用合约中保存数据。
964 | struct Data { mapping(uint => bool) flags; }
965 |
966 | // 注意第一个参数是 "storage reference" 类型,因此在调用中参数传递的只是它的存储地址而不是内容。
967 | // 这是库函数的一个特性。如果该函数可以被视为对象的方法,则习惯称第一个参数为 `self`。
968 | function insert(Data storage self, uint value)
969 | public
970 | returns (bool)
971 | {
972 | if (self.flags[value])
973 | return false; // 已经存在
974 | self.flags[value] = true;
975 | return true;
976 | }
977 |
978 | function remove(Data storage self, uint value)
979 | public
980 | returns (bool)
981 | {
982 | if (!self.flags[value])
983 | return false; // 不存在
984 | self.flags[value] = false;
985 | return true;
986 | }
987 |
988 | function contains(Data storage self, uint value)
989 | public
990 | view
991 | returns (bool)
992 | {
993 | return self.flags[value];
994 | }
995 | }
996 |
997 | contract C {
998 | Set.Data knownValues;
999 |
1000 | function register(uint value) public {
1001 | // 不需要库的特定实例就可以调用库函数,因为当前合约就是 "instance"。
1002 | require(Set.insert(knownValues, value));
1003 | }
1004 | // 如果我们愿意,我们也可以在这个合约中直接访问 knownValues.flags
1005 | }
1006 |
1007 | 当然,你不必按照这种方式去使用库:它们也可以在不定义结构数据类型的情况下使用。函数也不需要任何存储
1008 | 引用参数,库可以出现在任何位置并且可以有多个存储引用参数。
1009 |
1010 | 调用 ``Set.contains``, ``Set.insert`` 和 ``Set.remove`` 都被编译为外部调用( ``DELEGATECALL`` )。
1011 | 如果使用库,请注意实际执行的是外部函数调用。
1012 | ``msg.sender``, ``msg.value`` 和 ``this`` 在调用中将保留它们的值,(在 Homestead 之前,
1013 | 因为使用了 ``CALLCODE``,改变了 ``msg.sender`` 和 ``msg.value``)。
1014 |
1015 | 以下示例显示如何使用库的内存类型和内部函数来实现自定义类型,无需外部函数调用的开销:
1016 |
1017 | ::
1018 |
1019 | pragma solidity ^0.4.16;
1020 |
1021 | library BigInt {
1022 | struct bigint {
1023 | uint[] limbs;
1024 | }
1025 |
1026 | function fromUint(uint x) internal pure returns (bigint r) {
1027 | r.limbs = new uint[](1);
1028 | r.limbs[0] = x;
1029 | }
1030 |
1031 | function add(bigint _a, bigint _b) internal pure returns (bigint r) {
1032 | r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length));
1033 | uint carry = 0;
1034 | for (uint i = 0; i < r.limbs.length; ++i) {
1035 | uint a = limb(_a, i);
1036 | uint b = limb(_b, i);
1037 | r.limbs[i] = a + b + carry;
1038 | if (a + b < a || (a + b == uint(-1) && carry > 0))
1039 | carry = 1;
1040 | else
1041 | carry = 0;
1042 | }
1043 | if (carry > 0) {
1044 | // 太差了,我们需要增加一个 limb
1045 | uint[] memory newLimbs = new uint[](r.limbs.length + 1);
1046 | for (i = 0; i < r.limbs.length; ++i)
1047 | newLimbs[i] = r.limbs[i];
1048 | newLimbs[i] = carry;
1049 | r.limbs = newLimbs;
1050 | }
1051 | }
1052 |
1053 | function limb(bigint _a, uint _limb) internal pure returns (uint) {
1054 | return _limb < _a.limbs.length ? _a.limbs[_limb] : 0;
1055 | }
1056 |
1057 | function max(uint a, uint b) private pure returns (uint) {
1058 | return a > b ? a : b;
1059 | }
1060 | }
1061 |
1062 | contract C {
1063 | using BigInt for BigInt.bigint;
1064 |
1065 | function f() public pure {
1066 | var x = BigInt.fromUint(7);
1067 | var y = BigInt.fromUint(uint(-1));
1068 | var z = x.add(y);
1069 | }
1070 | }
1071 |
1072 | 由于编译器无法知道库的部署位置,链接器需要填入这些地址必的最终字节码(请参阅 :ref:`commandline-compiler` 以了解如何使用连接器的命令行工具)。 如果这些地址没有作为参数传递给编译器,
1073 | 编译后的十六进制代码将包含 ``__Set______`` 形式的占位符(其中 ``Set`` 是库的名称)。可以手动填写地址来
1074 | 替换库中十六进制编码的所有40个符号。
1075 |
1076 | 与合约相比,库的限制:
1077 |
1078 | - 没有状态变量
1079 | - 不能够继承或被继承
1080 | - 不能接受以太币
1081 |
1082 | (将来有可能会解除这些限制)
1083 |
1084 | 库的调用保护
1085 | =============================
1086 |
1087 | 正如介绍中所述,除调用 ``view`` 或者 ``pure`` 库函数之外,通过 ``CALL`` 而不是 ``DELEGATECALL``
1088 | 或者 ``CALLCODE`` 的库的代码,将会恢复。
1089 |
1090 | EVM 没有为合约提供检测是否使用 ``CALL`` 的直接方式,但是合约可以使用 ``ADDRESS`` 操作码找出正在运行
1091 | 的“位置”。生成的代码通过比较这个地址和构造时的地址来确定调用模式。
1092 |
1093 | 更具体地说,库的运行时代码总是由 push 指令启用,它在编译时是 20 字节的零。当部署代码运行时,这个常数
1094 | 被内存中的当前地址替换,修改后的代码存储在合约中。在运行时,这导致部署时地址是第一个被 push 到堆栈上的常数,
1095 | 对于任何 non-view 和 non-pure 函数,调度器代码都将对比当前地址与这个常数是否一致。
1096 |
1097 | .. index:: ! using for, library
1098 |
1099 | .. _using-for:
1100 |
1101 | *********
1102 | Using For
1103 | *********
1104 |
1105 | 指令 ``using A for B;`` 可用于附加库函数(从库 ``A``)到任何类型(``B``)。
1106 | 调用对象将作为这些函数的第一个参数(像 Python 的 ``self`` 变量)。
1107 |
1108 | ``using A for *;`` 的效果是,库 ``A`` 中的函数被附加在任意的类型上。
1109 |
1110 | 在这两种情况下,所有函数,即使那些与对象类型不匹配的第一参数类型的函数,也被附加上了。
1111 | 函数调用和重载解析时才会做类型检查。
1112 |
1113 | ``using A for B;`` 指令仅在当前作用域有效,仅限于在当前合约中,后续可能提升到全局范围。
1114 | 通过引入一个模块,不需要再添加代码就可以使用包括库函数在内的数据类型。
1115 |
1116 | 让我们用这种方式将 :ref:`libraries` 中的 set 例子重写::
1117 |
1118 | pragma solidity ^0.4.16;
1119 |
1120 | // 这是和之前一样的代码,只是没有注释。
1121 | library Set {
1122 | struct Data { mapping(uint => bool) flags; }
1123 |
1124 | function insert(Data storage self, uint value)
1125 | public
1126 | returns (bool)
1127 | {
1128 | if (self.flags[value])
1129 | return false; // 已经存在
1130 | self.flags[value] = true;
1131 | return true;
1132 | }
1133 |
1134 | function remove(Data storage self, uint value)
1135 | public
1136 | returns (bool)
1137 | {
1138 | if (!self.flags[value])
1139 | return false; // 不存在
1140 | self.flags[value] = false;
1141 | return true;
1142 | }
1143 |
1144 | function contains(Data storage self, uint value)
1145 | public
1146 | view
1147 | returns (bool)
1148 | {
1149 | return self.flags[value];
1150 | }
1151 | }
1152 |
1153 | contract C {
1154 | using Set for Set.Data; // 这是关键的修改
1155 | Set.Data knownValues;
1156 |
1157 | function register(uint value) public {
1158 | // 这里,Set.Data 类型的所有变量都有对应的成员函数。
1159 | // 以下函数调用与 `Set.insert(knownValues, value)` 效果相同。
1160 | require(knownValues.insert(value));
1161 | }
1162 | }
1163 |
1164 | 也可以像这样扩展基本类型::
1165 |
1166 | pragma solidity ^0.4.16;
1167 |
1168 | library Search {
1169 | function indexOf(uint[] storage self, uint value)
1170 | public
1171 | view
1172 | returns (uint)
1173 | {
1174 | for (uint i = 0; i < self.length; i++)
1175 | if (self[i] == value) return i;
1176 | return uint(-1);
1177 | }
1178 | }
1179 |
1180 | contract C {
1181 | using Search for uint[];
1182 | uint[] data;
1183 |
1184 | function append(uint value) public {
1185 | data.push(value);
1186 | }
1187 |
1188 | function replace(uint _old, uint _new) public {
1189 | // 执行库函数调用
1190 | uint index = data.indexOf(_old);
1191 | if (index == uint(-1))
1192 | data.push(_new);
1193 | else
1194 | data[index] = _new;
1195 | }
1196 | }
1197 |
1198 | 注意,所有库调用都是实际的 EVM 函数调用。这意味着如果传递内存或值类型,将执行一个拷贝副本,即使是 ``self`` 变量。
1199 | 使用存储引用变量是唯一不会发生拷贝的情况。
1200 |
--------------------------------------------------------------------------------