Solidity是一种类似于JavaScript的语言,用来编写区块链智能合约。目前来看,Solidity依然是全球最受欢迎的智能合约开发语言,它支持静态类型,继承和库等特性,加上周围开发生态的支持,如truffle和web3,让开发和部署一个DApp简单了很多。一个有经验的JavaScript开发者可以很快上手Solidity开发,但如果要用好Solidity就必须要了解Solidity和区块链的特性,而有些特性有点“反常识”,下面让我们来一起学习一下。
计算很贵
这点是开发dapp的最需要牢记的一点了,因为区块链是全网共识,也就是说每次修改一个状态一个变量都需要全网的节点达成一致,这是很昂贵的操作,所以当我们要修改变量的状态时,先想想这一点。
慎用循环
想象这样一个游戏场景:一个游戏中有3个队伍,每个用户可以投入一定的eth加入任意一个队伍,游戏结束时拥有最多用户的队伍将获胜,根据用户投入的多少瓜分10eth的奖金。
开发者会遇到的问题是,游戏结束的时候如何给用户结算用户赢得了多少eth?
你可能会说我可以这样做:
定义三个数组,对应三个队伍,然后用数组记录参与此队伍的用户地址
游戏结束的时候找到数组长度(length)最长的一个数组,对应的这个队伍就是获胜的队伍
然后再用for循环遍历这个数组,将用户赢得的eth算出来,写入到用户的合约账户中
用户可以随时提币
第三点中涉及到了一个for循环和写入操作,如果有10个用户的话,相当于循环10次修改合约状态10次。如果这个量级增加到几千的话,那就有点可怕了,因为这整个操作消耗的gas可能会超过一个区块的gas limit,从https://etherscan.io/blocks这个网站我们可以看到最近的几个区块的gas limit大概是8,000,000 gas/block,如果超过这个数字则你的写入操作都会失败。从用户角度来说,获胜的用户永远无法得到自己应得的eth,结果用户骂娘走人,游戏死掉。
所以记住,慎用循环,最好不要使用未知循环次数的循环。
mapping and iteration
是中非常常用的一种数据类型, 是一种类似于的结构。不但可以定义一个,甚至可以定义以及的多重嵌套,不过就本码农看来,定义1-3级(mapping出现4次)的场景比较多,超过4级(mapping出现4次)的就不是很多了。
mapping (address => Player) public mapAddrToPlayer; // 1级mapping (uint => mapping (address => mapping (uint => mapping (uint => uint)))) public mapPlayerEthByTree; // 4级
虽然很常用,可以却不能遍历的所有,拿这个结构来说,是用户的地址,如果我想遍历所有的地址,拿到用户信息,是做不到的。如果想遍历,需要单独维护一个数组来存储所有用户的地址()。
now其实不是now
我们一般写代码时,获得的就是当时的时间,而在中获得的却是未来的某一个时刻的时间,这个时间就是包含当前计算这个交易所在区块的时间。
过程是这样的,我在X的时间发送了一笔交易,交易中有一个计算要得到当前的,之后这个交易在时间Y被打包成区块,最后在时间Z发送到链上。最终的值是Y,它们之间的关系是X
所以不可靠,在使用的时候一定要注意着一点。
不支持浮点数
中不支持浮点数,所以处理浮点数的时候要通过整数来表示。另外做除法的时候结果也不会出现浮点数,除法结果是,除法结果是。
因为类型有溢出的问题,所以在处理数学的加减乘乘方以及根号的运算时,我们通常用来处理。
foo.add(bar) // 加法foo.mul(bar) // 乘法foo.sub(bar) // 减法
你在开发过程中遇到了哪些坑?欢迎留言。
领取专属 10元无门槛券
私享最新 技术干货