Solidity v0.7.0 更改说明

本节重点介绍 Solidity v0.7.0 版本中引入的主要更改说明,以及变更背后的原因和如何更新受影响的代码。有关完整列表,请查看 发行说明.

语义的静默变更

  • 字面量的指数和移位运算符使用非字面量(例如 1 << x2 ** x)始终使用 uint256(对于非负字面量)或 int256(对于负字面量)类型执行运算。以前,运算是在移位量/指数的类型中执行的,这可能会产生误解。

语法变更

  • 在外部函数和合约创建调用中,以太币和 gas 现在使用新的语法指定:x.f{gas: 10000, value: 2 ether}(arg1, arg2)。旧语法 - x.f.gas(10000).value(2 ether)(arg1, arg2) - 将会导致错误。

  • 全局变量 now 已弃用,应改用 block.timestamp。单个标识符 now 对于全局变量来说过于笼统,可能会给人一种它在交易处理过程中发生变化的印象,而 block.timestamp 正确地反映了它只是区块的一个属性。

  • 变量上的 NatSpec 注释仅允许用于公共状态变量,而不能用于局部或内部变量。

  • 标记 gwei 现在是一个关键字(用于指定,例如 2 gwei 作为数字),不能用作标识符。

  • 字符串字面量现在只能包含可打印的 ASCII 字符,这也包括各种转义序列,例如十六进制 (\xff) 和 Unicode 转义序列 (\u20ac)。

  • Unicode 字符串字面量现在已得到支持,以适应有效的 UTF-8 序列。它们由 unicode 前缀标识:unicode"Hello 😃"

  • 状态可变性:函数的状态可变性现在可以在继承期间受到限制:默认状态可变性的函数可以被 pureview 函数覆盖,而 view 函数可以被 pure 函数覆盖。同时,公共状态变量被认为是 view 甚至 pure,如果它们是常量。

内联汇编

  • 不允许内联汇编中使用用户定义的函数和变量名称中的 .。如果您以 Yul 仅模式使用 Solidity,它仍然有效。

  • 存储指针变量 x 的插槽和偏移量分别通过 x.slotx.offset 访问,而不是 x_slotx_offset

删除未用或不安全的特性

存储外部的映射

  • 如果结构体或数组包含映射,则它只能在存储中使用。以前,映射成员在内存中被静默跳过,这会造成混淆和错误。

  • 如果存储中的结构体或数组包含映射,则对其进行赋值将不起作用。以前,映射在复制操作期间被静默跳过,这会导致误解和错误。

函数和事件

  • 构造函数不再需要可见性 (public / internal):要防止创建合约,可以将其标记为 abstract。这使得构造函数的可见性概念过时。

  • 类型检查器:不允许库函数使用 virtual:由于无法从库继承,因此库函数不应该为虚拟函数。

  • 不允许在同一继承层次结构中使用具有相同名称和参数类型的多个事件。

  • using A for B 仅影响它所提到的合约。以前,这种影响是会继承的。现在,您必须在使用此特性的所有派生合约中重复 using 语句。

表达式

  • 不允许使用带符号类型进行移位。以前,允许使用负数进行移位,但在运行时会回滚。

  • 已删除 finneyszabo 面额。它们很少使用,并且不会使实际金额一目了然。相反,可以使用显式值,例如 1e20 或非常常见的 gwei

声明

  • 关键字 var 现在不能再使用。以前,此关键字会解析但会导致类型错误,并建议使用哪种类型。现在,它会导致解析器错误。

接口变更

  • JSON AST:用 kind: "hexString" 标记十六进制字符串字面量。

  • JSON AST:从 JSON 输出中删除值为 null 的成员。

  • NatSpec:构造函数和函数具有一致的用户文档输出。

如何更新您的代码

本节提供了有关如何更新每个更改说明的先前代码的详细说明。

  • x.f.value(...)() 更改为 x.f{value: ...}()。类似地,将 (new C).value(...)() 更改为 new C{value: ...}(),并将 x.f.gas(...).value(...)() 更改为 x.f{gas: ..., value: ...}()

  • now 更改为 block.timestamp

  • 将移位运算符中右操作数的类型更改为无符号类型。例如,将 x >> (256 - y) 更改为 x >> uint(256 - y)

  • 如果需要,在所有派生合约中重复 using A for B 语句。

  • 从每个构造函数中删除 public 关键字。

  • 从每个构造函数中删除 internal 关键字,并向合约添加 abstract(如果尚未存在)。

  • 将内联汇编中的 _slot_offset 后缀分别更改为 .slot.offset