Solidity 0.6.0 改动一览

一、编译器可能不会警告的改动

​现在乘方(求幂)的类型是底数类型,它将使用能同时容纳底数和乘方结果的最小数值类型,作为对称操作,有符号数也可以作为底数。

二、显式需求

​本节主要列出了那些在代码中需要显式标记或者申明但语法又没有改变的内容。在大多数情况下,编译器会给出建议。

  1. 函数现在只有被标记为virtual或者在接口中定义才能被重写。未实现的外部接口函数必须标记为virtual,在重写函数和修辞符时,需要使用override关键字。当重写多个基类的函数或者修辞符时,所有基类必须依次放在括号中,例如:override(Base1, Base2)

  2. 数组的成员length现在是只读属性了,甚至该数组为storage数组。这就意味着不能再通过将length重新赋值来改变数组大小了。作为替代,你只能使用push()、push(value)、pop(),或者重新赋值为一个新数组,不过它会改写已经存在的内容。改动原因是为了防止庞大的storage数组造成存储冲突。

  3. 一个新的关键字abstract用来标记那些含有未实现函数的合约。

  4. 库必须实现它所有的函数,并不仅仅是内部的。

  5. 内联汇编中定义的变量名不再以 _slot 或 _offset 结尾。

  6. 内联汇编中定义的变量不再隐藏包含该汇编块的外部代码的同名变量。如果名称中包括圆点,它的前缀不会和外部的任何变量冲突。

  7. 状态变量隐藏现在被取消了,现在子类不能定义任何父类中已经定义的可见的同名变量。

三、语义或者语法改变

  1. 从外部函数类型到地址类型的转换被隐藏了,取代的是外部函数有一个成员叫address,和selector成员类型。
  2. 对动态storage数组来说,push(value)不再返回数组新的长度,实际上它不返回任何值。
  3. 未命名的通常作为回调函数使用的函数现在分成了两个函数,一个新的回调函数使用fallback关键字和一个接收ether的函数使用receive关键字。
    • 如果存在,当调用数据(calldata)为空时,总是会调用接收ether的函数,无论是否接收到ether,当然,该函数隐式的是payable。
    • 新的回调函数在未匹配到相应的函数时调用(调用数据为空并且接收ether函数不存在时也属于这种情况)。你可以将它设置为payable(可支付)或者不设置。当为不可支付时,未匹配到对应的函数并且又随调用发送了ether,此时会重置交易。你只有在遵循升级或者代理模式时才需要实现新的回调函数。

四、新的特性

  1. try/catch 语句允许和失败的外部调用交互。
  2. 结构和枚举类型可以在文件作用域被定义。
  3. 数组切片可以应用于calldata数组。示例:abi.decode(msg.data[4:], (uint, uint)) 就是一个低等级的解码函数调用数据的方法。
  4. Natspec注释支持在开发者文档里使用多个返回参数,和@param使用相同的强制命名检查。
  5. Yul和内联汇编现在一个新的语句leave用来退出当前的函数。
  6. 从普通地址(address)到可支付地址的转换(payable address)现在可以使用payable(x),x必须为一个地址。

五、接口变化

​本节列出的变化并不是语言本身的变化,而是和编译器接口相关。它们可能影响你在命令行上使用编译器、程序化接口或者解析输出等。

  1. 新的错误报告接口。使用了一个新的错误报告接口,它用来将使用命令行时错误报告更加易读,它现在是默认的,你也可以使用 --old-reporter 来使用旧的接口。
  2. 元数据哈希选项。编译器现在默认会在字节码的最后附加元数据文件的IPFS哈希。在0.6.0之前,附加的是Swarm哈希,为了仍旧支持该功能,可以使用命令行选项 --metadata-hash 。它可以使你选择附加哪种哈希,你也可以使用 none 来移除这些哈希。
  3. Yul优化。和字节码优化一样,Yul优化在你使用 --optimize 编译选项时已经可用了。你也可以使用 --no-optimize-yul 选项来关掉它。它主要影响使用 ABIEncoderV2的代码。
  4. C API变化。客户端使用 C API的编译器 libsolc 现在可以操作编译器使用的内存了。为了保证变化一致,solidity_free 重命名为 solidity_reset ,增加了函数solidity_alloc 和 solidity_free,solidity_compile 现在返回了一个字符串,它必须通过solidity_free()显式释放。

六、怎样升级你的代码

下面列出了一些升级以前代码的细节:

  1. 如果f是一个外部函数类型,使用f.address来代替address(f)。
  2. 使用receive() external payable { … }或者fallback() external [payable] { … }来代替function () external [payable] { … } ,或者两者同时使用。记住,只要有可能,仅使用receive函数。
  3. 将uint length = array.push(value)改成array.push(value),数组的新长度可以通过length成员获取。
  4. 使用array.push()代替array.length++来增加、使用pop()来减少数组的长度。
  5. 对函数中每一个在@dev 文档中定义的命名的返回参数定义一个单独的@return ,使用它们在返回元组中相同的顺序。
  6. 为内联汇编中的变量取一个唯一的名字以使不和包含它的代码块中的变量相冲突。
  7. 在你计划重写的每个非接口函数定义前增加virtual关键字。对所有未实现的外部接口函数增加virtual关键字。在单个继承时,在每个重写的方法前增加override关键字;有多重继承时,必须在括号中依次列出定义该函数的基类。如果多个基类定义了相同的函数,继承的合约必须重写所有冲突的函数。

水平有限,解释不清或者错误的地方请多查看原文对照。

原文链接 https://solidity.readthedocs.io/en/v0.6.0/060-breaking-changes.html

发布了15 篇原创文章 · 获赞 0 · 访问量 563

猜你喜欢

转载自blog.csdn.net/weixin_39430411/article/details/103747542
今日推荐