Solidity v0.6.0中断更改

本节重点介绍Solidity版本0.6.0中引入的主要突破性更改,以及更改背后的推理以及如何更新受影响的代码。对于完整列表检查 the release changelog .

编译器可能不会警告的更改

本节列出了代码行为可能会发生变化而编译器不会告诉您的更改。

  • 求幂的结果类型是基的类型。它曾经是最小的类型,可以同时包含基类型和指数类型,就像对称操作一样。此外,允许有符号类型作为求幂的基。

明确性要求

本节列出了代码现在需要更显式的更改,但语义没有更改。对于大多数主题,编译器将提供建议。

  • 函数现在只能在使用标记时重写 virtual 关键字或在接口中定义。必须标记接口外没有实现的函数 virtual . 重写函数或修饰符时,new关键字 override 必须使用。重写在多个并行基中定义的函数或修饰符时,所有基都必须列在关键字后面的括号中,如下所示: override(Base1, Base2) .

  • 会员访问 length 阵列的现在始终是只读的,即使对于存储阵列也是如此。再也不可能通过为存储阵列的长度指定新值来调整存储阵列的大小。使用 push()push(value)pop() 或者指定一个完整的数组,这当然会覆盖现有的内容。这背后的原因是为了防止大型存储阵列的存储冲突。

  • 新关键字 abstract 可用于将合同标记为抽象。如果合同没有实现其所有功能,就必须使用它。不能使用 new 运算符,并且不可能在编译期间为它们生成字节码。

  • 类库必须实现其所有功能,而不仅仅是内部功能。

  • 在内联程序集中声明的变量名称可能不再以结尾 _slot_offset .

  • 内联程序集中的变量声明可能不再隐藏内联程序集块外的任何声明。如果名称包含一个点,它的前缀直到点可能不会与内联程序集块之外的任何声明冲突。

  • 现在不允许状态变量隐藏。派生协定只能声明状态变量 x ,如果它的任何基中没有同名的可见状态变量。

语义和句法变化

本节列出了您必须修改代码并在之后执行其他操作的更改。

  • 从外部函数类型转换为 address 现在是不允许的。相反,外部函数类型有一个名为 address ,与现有 selector 成员。

  • 函数 push(value) 因为动态存储阵列不再返回新的长度(它不返回任何内容)。

  • 通常称为“回退函数”的未命名函数被拆分为使用 fallback 关键字和使用 receive 关键字。

    • 如果存在,则每当调用数据为空时(无论是否接收到乙醚),都将调用receive ether函数。此函数是隐式的 payable .

    • 当没有其他函数匹配时,将调用新的回退函数(如果receive ether函数不存在,则包括调用数据为空的调用)。你可以做这个功能 payable 或者不是。如果不是的话 payable 然后,与发送值的任何其他函数不匹配的事务将恢复。只有在遵循升级或代理模式时,才需要实现新的回退功能。

新特点

本节列出了在Solidity 0.6.0之前不可能实现或更难实现的事情。

  • 这个 try/catch statement 允许您对失败的外部呼叫作出反应。

  • structenum 类型可以在文件级别声明。

  • 例如,数组切片可以用于calldata数组 abi.decode(msg.data[4:], (uint, uint)) 是对函数调用有效负载进行解码的低级方法。

  • Natspec支持开发人员文档中的多个返回参数,强制执行与 @param .

  • Yul和内联程序集有一个名为 leave 退出当前函数。

  • 转换自 addressaddress payable 现在可以通过 payable(x) 在哪里 x 必须是类型 address .

接口更改

本节列出与语言本身无关但对编译器接口有影响的更改。这些可能会改变你在命令行上使用编译器的方式,你如何使用它的可编程接口,或者你如何分析它产生的输出。

新错误报告器

引入了一个新的错误报告器,旨在在命令行上生成更易访问的错误消息。默认情况下启用,但传递 --old-reporter 返回到弃用的旧错误报告器。

元数据哈希选项

编译器现在附加 IPFS 默认情况下,将元数据文件哈希到字节码末尾(有关详细信息,请参阅 contract metadata ). 在0.6.0之前,编译器将 Swarm 默认情况下,为了仍然支持这种行为,新的命令行选项 --metadata-hash 介绍。它允许您通过传递 ipfsswarm 作为对 --metadata-hash 命令行选项。传递值 none 完全删除哈希。

这些更改也可以通过 Standard JSON Interface 并影响编译器生成的元数据JSON。

读取元数据的推荐方法是读取最后两个字节,以确定CBOR编码的长度,并对该数据块执行正确的解码,如中所述 metadata section .

Yul优化器

与旧式字节码优化器一起, Yul 现在,使用调用编译器时,优化器现在默认情况下处于启用状态 --optimize 。可以通过使用以下命令调用编译器来禁用它 --no-optimize-yul 。这主要影响使用ABI编码器v2的代码。

C API更改

使用的C API的客户端代码 libsolc 现在控制编译器使用的内存。为了使这种变化保持一致, solidity_free 重命名为 solidity_reset ,功能 solidity_allocsolidity_free 添加和 solidity_compile 现在返回一个必须通过显式释放的字符串 solidity_free() .

如何更新代码

本节详细说明了如何为每次中断更改更新先前的代码。

  • 变化 address(f)f.address 对于 f 属于外部功能类型。

  • 替换 function () external [payable] {{ ... }} 由任何一个 receive() external payable {{ ... }}fallback() external [payable] {{ ... }} 或者两者兼而有之。更喜欢使用 receive 尽可能只起作用。

  • 变化 uint length = array.push(value)array.push(value); . 新长度可以通过 array.length .

  • 变化 array.length++array.push() 增加,使用 pop() 减小存储阵列的长度。

  • 函数的 @dev 文档定义 @return 包含参数名称作为第一个单词的项。E、 g.如果你有功能 f() 定义为 function f() public returns (uint value) 和A @dev 对其进行注释,记录其返回参数,如下所示: @return value The return value. . 您可以混合命名和未命名的返回参数文档,只要通知按照它们在元组返回类型中出现的顺序排列。

  • 为内联程序集中与内联程序集块外的声明不冲突的变量声明选择唯一标识符。

  • 添加 virtual 对于每个要重写的非接口函数。添加 virtual 所有没有外部接口实现的函数。对于单一继承,添加 override 到每个重写函数。对于多重继承,添加 override(A, B, ..) ,其中在括号中列出定义重写函数的所有协定。当多个基定义同一个函数时,继承契约必须覆盖所有冲突函数。