Harry Liu avatar

智能合约开发 | Solidity依然是对开发者最友好的语言,不过有些开发技巧有点反常识

ljyxxzj

Published: 13 Nov 2018 › Updated: 13 Nov 2018智能合约开发 | Solidity依然是对开发者最友好的语言,不过有些开发技巧有点反常识

智能合约开发 | Solidity依然是对开发者最友好的语言,不过有些开发技巧有点反常识

Solidity是一种类似于JavaScript的语言,用来编写区块链智能合约。目前来看,Solidity依然是全球最受欢迎的智能合约开发语言,它支持静态类型,继承和库等特性,加上周围开发生态的支持,如truffle和web3,让开发和部署一个DApp简单了很多。一个有经验的JavaScript开发者可以很快上手Solidity开发,但如果要用好Solidity就必须要了解Solidity和区块链的特性,而有些特性有点”反常识“,下面让我们来一起学习一下。

计算很贵

这点是开发dapp的最需要牢记的一点了,因为区块链是全网共识,也就是说每次修改一个状态一个变量都需要全网的节点达成一致,这是很昂贵的操作,所以当我们要修改变量的状态时,先想想这一点。

慎用循环

想象这样一个游戏场景:一个游戏中有3个队伍,每个用户可以投入一定的eth加入任意一个队伍,游戏结束时拥有最多用户的队伍将获胜,根据用户投入的多少瓜分10eth的奖金。

开发者会遇到的问题是,游戏结束的时候如何给用户结算用户赢得了多少eth?

你可能会说我可以这样做:

  1. 定义三个数组,对应三个队伍,然后用数组记录参与此队伍的用户地址
  2. 游戏结束的时候找到数组长度(length)最长的一个数组,对应的这个队伍就是获胜的队伍
  3. 然后再用for循环遍历这个数组,将用户赢得的eth算出来,写入到用户的合约账户中
  4. 用户可以随时提币

第三点中涉及到了一个for循环和写入操作,如果有10个用户的话,相当于循环10次修改合约状态10次。如果这个量级增加到几千的话,那就有点可怕了,因为这整个操作消耗的gas可能会超过一个区块的gas limit,从 https://etherscan.io/blocks 这个网站我们可以看到最近的几个区块的gas limit大概是8,000,000 gas/block,如果超过这个数字则你的写入操作都会失败。从用户角度来说,获胜的用户永远无法得到自己应得的eth,结果用户骂娘走人,游戏死掉。

2018-11-13 at 10.25 PM.png

所以记住,慎用循环,最好不要使用未知循环次数的循环

mapping and iteration

mappingsolidity中非常常用的一种数据类型, 是一种类似于 K->V hashmap的结构。不但可以定义一个mapping,甚至可以定义mapping of mapping以及mapping of mapping of mapping的多重嵌套,不过就本码农看来,定义1-3级mapping(mapping出现4次)的场景比较多,超过4级(mapping出现4次)的就不是很多了。

mapping (address => Player) public mapAddrToPlayer; // 1级
mapping (uint => mapping (address => mapping (uint => mapping (uint => uint)))) public mapPlayerEthByTree;  // 4级

虽然mapping很常用,可以却不能遍历mapping的所有key,拿mapAddrToPlayer这个结构来说,key是用户的地址,如果我想遍历所有的地址,拿到用户信息,是做不到的。如果想遍历,需要单独维护一个数组来存储所有用户的地址(key)。

now其实不是now

我们一般写代码时,获得的now就是当时的时间,而在solidity中获得的now却不是真正的now,而是区块链上最新一个区块的时间。

过程是这样的,我在当前时间向一个合约发送了一次查询,想要得到当前的now,得到这次请求的节点会去查询最近一个区块被打包的时间,把这个时间返回给我,这个值就是我想要的now了。如果这个区块是在10秒前被打包成功的,那我得到的值是会比真实世界的now少10秒的。

所以now不可靠,在使用的时候一定要注意着一点。

不支持浮点数

solidity中不支持浮点数,所以处理浮点数的时候要通过整数来表示。另外做除法的时候结果也不会出现浮点数,除法1/2结果是0,除法5/2结果是2

因为uint类型有溢出的问题,所以在处理数学的加减乘乘方以及根号的运算时,我们通常用safemath来处理。

foo.add(bar)    // 加法
foo.mul(bar)    // 乘法
foo.sub(bar)    // 减法

你在开发过程中遇到了哪些坑?欢迎留言。

Leave 智能合约开发 | Solidity依然是对开发者最友好的语言,不过有些开发技巧有点反常识 to:

Written by

Read more #blockchain posts


Best Posts From Harry Liu

We have not curated any of ljyxxzj's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From Harry Liu