时间单位
Solidity使用自己的本地时间单位。通过变量now返回当前的unix时间戳(自1970年1月1日以来经过的秒数)。
Tips:Unix时间默认使用一个32位的整数进行存储,这导致了著名的“2038年问题”,在此基础上如果使用64位整数表示时间,则会消耗更多的gas。
Solidity还包含秒(seconds),分钟(minutes),小时(hours),天(days),周(weeks)和年(years)等时间单位。它们都会转换成对应的秒数放入uint中。所以1分钟就是60,1小时是3600,1天是86400,以此类推。
时间单位示例
将结构体作为参数传入
结构体的存储指针可以以参数的方式传递给一个private或internal的函数,因此结构体可以在多个函数之间相互传递。这样可以把结构体中的饮用直接传递给一个函数,而不是通过参数传入结构体中的元素再以此为参数去查找。
公有函数和安全性
在函数运行过程中,必须要注意的是声明为public和external的函数,排除被用户滥用的可能,谨防安全漏洞。如果没有特殊的修饰符限制,用户能够利用各种可能的参数去调用函数。如果想要防止漏洞,最简单的方法就是设其可见性为internal。
带参数的函数修饰符
在Solidity中,函数修饰符可以带参数。
带参数的函数修饰符示例
在这个例子中,olderThan修饰符可以像函数一样接收参数,通过driveCar把参数传递给修饰符。
利用‘View’函数节省Gas
当用户从外部调用view函数,不需要支付gas。这是因为view函数不会改变区块链上的任何数据,它们只是读取。因此使用view标记一个函数,意味着运行函数只需要查询本地的以太坊节点,而不需要在区块链上创建一个事务(事务需要运行在每个节点上,因此花费gas)。
Tips:如果一个view函数在另一个函数的内部被调用,而调用函数与view函数的不属于同一个合约,也会产生调用成本。这是因为如果主调函数在以太坊创建了一个事务,它仍然需要逐个节点去验证。所以标记为view的函数只有在外部调用时才是免费的。
存储非常昂贵
Solidity使用storage(存储)是相当昂贵的,“写入”操作尤其贵。这是因为无论是写入还是更改一段数据,这都将永久性地写入区块链。需要在全球数千个节点的硬盘上存入这些数据,随着区块链的增长,拷贝份数更多,存储量也就越大。这需要大量的成本。
为了降低成本,不到万不得已,避免将数据写入存储。这也会导致效率低下的编程逻辑,比如每次调用一个函数,都需要在memory(内存)中重建一个数组,而不是简单地将上次计算的数组给存储下来以便快速查找。
在大多数编程语言中,遍历大数据集合都是昂贵的。但是在Solidity中,使用一个标记了external view的函数,遍历比storage要便宜太多,因为view函数不会产生任何花销。
在内存中声明数组
在数组后面加上memory关键字表明这个数组是仅仅在内存中创建,不需要写入外部存储,并且在函数调用结束时它就消失了。与在程序结束时把数据保存进storage的做法相比,内存运算可以大大节省gas开销。
内存数组示例
Tips:内存数组必须用长度参数(本例中为3)创建。目前不支持array.push()之类的方法调整数组大小。
For循环
Solidity的函数中使用的数组是运行时在内存中通过for循环实时构建,而不是预先建立在存储中的。for循环的语法在Solidity和JavaScript中类似。
在这个例子中,将会返回一个[2,4,6,8,10]的数组。
Leave a Reply