以太坊智能合约Solidity的0.5

Solidity v0.5.0重大变化

注意
使用Solidity v0.5.0编译的合约仍然可以与合约甚至是使用旧版本编译的库进行交互,而无需重新编译或重新部署它们。更改接口以包括数据位置和可见性以及可变性说明符就足够了。

仅语义更改

本节列出了仅语义的更改,因此可能隐藏现有代码中的新行为和不同行为。

• 有符号右移现在使用适当的算术移位,即向负无穷大舍入,而不是向零舍入。有符号和无符号的转换将在君士坦丁堡有专用的操作码,目前由Solidity仿效。
• 循环中的continue语句do…while现在跳转到条件,这是这种情况下的常见行为。它曾经跳到循环体。因此,如果条件为假,则循环终止。
• 该功能.call(),.delegatecall()并.staticcall()给出一个时,不要垫了bytes参数。
• 现在使用操作码调用纯函数和视图函数,STATICCALL 而不是CALL如果EVM版本是拜占庭或更高版本。这不允许EVM级别的状态更改。
• 现在,msg.data当在外部函数调用中使用时,ABI编码器正确地填充来自calldata(和外部函数参数)的字节数组和字符串abi.encode。对于无衬垫编码,请使用 abi.encodePacked。
• ABI解码器在函数的开头还原, abi.decode()如果传递的则是calldata太短或超出界限。请注意,仍然会忽略脏的高阶位。
• 从Tangerine Whistle开始,通过外部函数调用转发所有可用气体。

语义和句法变化

本节重点介绍影响语法和语义的更改。

• 功能.call(),.delegatecall(),staticcall(), keccak256(),sha256()和ripemd160()现在只接受一个 bytes参数。而且,论证没有填补。这被更改为更明确和清楚如何连接参数。改变每.call()(家庭)的.call(""),每使用(最后一个只适用于价值型)。改变每到 。即使它不是一个重大变化,但建议开发人员 改为。.call(signature, a, b, c).call(abi.encodeWithSignature(signature, a, b, c))keccak256(a, b, c)keccak256(abi.encodePacked(a, b, c))x.call(bytes4(keccak256(“f(uint256)”), a, b)x.call(abi.encodeWithSignature(“f(uint256)”, a, b))
• 功能.call(),.delegatecall()而.staticcall()现在回到 提供访问返回的数据。更改到。(bool, bytes memory)bool success = otherContract.call(“f”)(bool success, bytes memory data) = otherContract.call(“f”)
• Solidity现在为函数局部变量实现C99样式的作用域规则,也就是说,变量只能在声明它们之后才能使用,并且只能在相同或嵌套的作用域中使用。在for循环的初始化块中声明的变量在循环内的任何点都是有效的。

显性要求

本节列出了代码现在需要更明确的更改。对于大多数主题,编译器将提供建议。

• 显式功能可见性现在是强制性的。添加public到每个函数和构造函数,以及external每个尚未指定其可见性的后备或接口函数。
• 现在必须显示struct,array或mapping类型的所有变量的显式数据位置。这也适用于函数参数和返回变量。例如,更改到,并且向 其中是该数据位置,并且可能被替换或 相应。请注意,函数需要数据位置为的参数。uint[] x = m_xuint[] storage x = m_xfunction f(uint[][] x)function f(uint[][] memory x)memorystoragecalldataexternalcalldata
• 合约类型不再包含address成员,以便分隔名称空间。因此,现在需要在使用address成员之前将合约类型的值显式转换为地址 。例如:如果c是一个合约,改变 c.transfer(…)到address©.transfer(…)和c.balance到address©.balance。
• 的address类型被分成address和,其中仅提供了功能。一个 可以直接转换到的,但周围的其他方法是不允许的。转换到经由通过转换是可能的。如果是合约,则只有具有应付回退功能时才会产生结果。如果你使用撤销模式,你很可能不必更改你的代码,因为 它只用于代替存储的地址,而且 是一个。address payableaddress payabletransferaddress payableaddressaddressaddress payableuint160caddress©address payablectransfermsg.sendermsg.senderaddress payable
• 现在不允许在不同大小bytesX和uintY不同大小之间进行转换,因为bytesX右边的uintY填充和左边的填充可能会导致意外的转换结果。现在必须在转换前的类型内调整大小。例如,您可以通过先将变量转换为然后转换为bytes4(4字节)转换为uint64(8字节) 。转换时会得到相反的填充。bytes4bytes8uint64uint32
• 使用msg.value在无抬头功能(或通过改性剂引入它)是不允许的作为安全特征。将函数转换为payable或使用的程序逻辑创建新的内部函数msg.value。
• 为清楚起见,命令行界面现在要求-标准输入用作源。

不推荐使用的元素

本节列出了弃用先前功能或语法的更改。请注意,许多这些更改已在实验模式中启用 v0.5.0。

命令行和JSON接口

• 命令行选项–formal(用于生成Why3输出以进行进一步的正式验证)已弃用,现已删除。通过以下方式启用新的正式验证模块SMTChecker 。pragma experimental SMTChecker;
• 由于将中间语言重命名–julia为,命令行选项已重–yul命名Julia为Yul。
• 该–clone-bin和命令行选项已被删除。–combined-json clone-bin
• 不允许使用空前缀重新映射。
• 该JSON AST领域constant和payable被拆除。该信息现在存在于该stateMutability领域。
• 的JSON AST字段isConstructor的的FunctionDefinition 节点是由一个称为电场置换kind其可以具有值"constructor",“fallback"或"function”。
• 在未链接的二进制十六进制文件中,库地址占位符现在是完全限定库名称的keccak256哈希的前36个十六进制字符,包围 . . . ... ...。以前,只使用了完全限定的库名。这可以避免碰撞的可能性,尤其是在使用长路径时。二进制文件现在还包含从这些占位符到完全限定名称的映射列表。

构造函数

• 现在必须使用constructor关键字定义构造函数。
• 现在不允许调用没有括号的基本构造函数。
• 现在不允许在同一继承层次结构中多次指定基础构造函数参数。
• 现在不允许调用带参数但具有错误参数计数的构造函数。如果您只想在不提供参数的情况下指定继承关系,请不要提供括号。

功能

• callcode现在不允许使用功能(赞成delegatecall)。仍然可以通过内联汇编使用它。
• suicide现在不允许(赞成selfdestruct)。
• sha3现在不允许(赞成keccak256)。
• throw现在不允许(赞成revert,require和 assert)。

转化

• bytesXX现在不允许从十进制文字到类型的显式和隐式转换。
• bytesXX现在不允许从十六进制文字到不同大小的类型的显式和隐式转换。

文字和后缀

• years由于闰年的复杂性和混乱,现在不允许单位面额。
• 现在不允许使用后跟数字的尾随点。
• 现在不允许将十六进制数与单位面额(例如)组合。0x1e wei
• 0X不允许使用十六进制数字的前缀0x。

变量

• 为清楚起见,现在不允许声明空结构。
• 该var关键字现在,不允许有利于明确性。
• 现在不允许具有不同组件数的元组之间的分配。
• 不允许不是编译时常量的常量的值。
• 现在不允许使用不匹配值的多变量声明。
• 现在不允许使用未初始化的存储变量。
• 现在不允许空元组组件。
• 检测变量和结构中的循环依赖性在递归到256时受到限制。
• 现在不允许长度为零的固定大小的数组。

语法

• constant现在不允许使用as函数状态mutability modifier。
• 布尔表达式不能使用算术运算。
• +现在不允许一元运算符。
• abi.encodePacked如果没有事先转换为显式类型,则不能再使用文字。
• 现在不允许具有一个或多个返回值的函数的空返回语句。
• 现在不允许完全禁止“松散组装”语法,即不能再使用跳转标签,跳转和非功能性指令。使用新的while,switch和if构造来代替。
• 没有实现的函数不能再使用修饰符。
• 现在不允许具有命名返回值的函数类型。
• 现在不允许if / while /中的单个语句变量声明用于非块的主体。
• 新关键字:calldata和constructor。
• 新关键字:alias,apply,auto,copyof,define,immutable,implements,macro,mutable,override,partial,promise,reference,sealed, sizeof,supports,typedef和unchecked。

示例

以下示例显示了Solidity v0.5.0的合约及其更新版本,其中包含本节中列出的一些更改。
旧版:

// 这个不能编译
pragma solidity ^0.4.25;
contract OtherContract {
   uint x;
   function f(uint y) external {
      x = y;
   }
   function() payable external {}
}

contract Old {
   OtherContract other;
   uint myNumber;

   //没有提供函数可变性,不是错误。
   function someInteger() internal returns (uint) { return 2; }

//未提供功能可见性,不是错误。
  //没有提供函数可变性,不是错误。
   function f(uint x) returns (bytes) {
      // Var 可以用
      var z = someInteger();
      x += z;
      // Throw 可以用
      if (x > 100)
         throw;
      bytes b = new bytes(x);
      y = -3 >> 1;
      // y =-2
      do {
         x += 1;
         if (x > 10) continue;
         //'继续'会导致无限循环。
      } while (x < 11);
      // 返回bool
      bool success = address(other).call("f");
      if (!success)
         revert();
      else {
         //可以在使用后声明局部变量。
         int y;
      }
      return b;
   }

   //不需要'arr'的显式数据位置
   function g(uint[] arr, bytes8 x, OtherContract otherContract) public {
      otherContract.transfer(1 ether);

//由于uint32(4字节)小于bytes8(8字节),
   //  x的前4个字节将丢失。 这可能会导致
   // 由于bytesX是右填充的意外行为。      
uint32 y = uint32(x);
      myNumber += y + msg.value;
   }
}

新版本:

pragma solidity >0.4.99 <0.6.0;
contract OtherContract {
   uint x;
   function f(uint y) external {
      x = y;
   }
   function() payable external {}
}

contract New {
   OtherContract other;
   uint myNumber;

   //必须指定函数可变性。
   function someInteger() internal pure returns (uint) { return 2; }

  //必须指定功能可见性。
     //必须指定函数可变性。
   function f(uint x) public returns (bytes memory) {
      //现在必须明确给出类型。
      uint z = someInteger();
      x += z;
      // Throw 不允许
      require(x > 100);
      int y = -3 >> 1;
      // y == -2 (正确)
      do {
         x += 1;
         if (x > 10) continue;
         //'继续'跳到下面的条件。
      } while (x < 11);
//调用返回(bool,bytes)。
      // 必须指定数据位置。
      (bool success, bytes memory data) = address(other).call("f");
      if (!success)
         revert();
      return data;
   }

   using address_make_payable for address;
   //必须指定'arr'的数据位置
   function g(uint[] memory arr, bytes8 x, OtherContract otherContract, address unknownContract)
 public payable {
      // 未提供“otherContract.transfer”。
      //由于'OtherContract'的代码是已知的并具有后备
      // function,address(otherContract)的类型为“地址应付”。
      address(otherContract).transfer(1 ether);
    //未提供'unknownContract.transfer'。
//未提供'address(unknownContract).transfer'
//因为'地址(unknownContract)'不是'地址应付'。
//如果该函数采用您要发送的“地址”
//资金到,您可以通过'uint160'将其转换为'地址应付'。
//注意:不建议使用此类型和显式类型
//应尽可能使用“应付地址”。
//为了提高清晰度,我们建议使用库
//转换(在本例中的合同之后提供)。
      address payable addr = unknownContract.make_payable();
      require(addr.send(1 ether));
//由于uint32(4字节)小于bytes8(8字节),
//不允许转换。
//我们需要先转换为通用尺寸:
      bytes4 x4 = bytes4(x); //填充发生在右侧
      uint32 y = uint32(x4); //转换是一致的
//'msg.value'不能用于'非应付'功能。
//我们需要支付功能
      myNumber += y + msg.value;
   }
}
//我们可以定义一个库来显式转换``address``
//将``地址应付款``作为一种解决方法。
library address_make_payable {
   function make_payable(address x) internal pure returns (address payable) {
      return address(uint160(x));
   }
}

以太坊智能合约Solidity的0.5_第1张图片

你可能感兴趣的:(Solidity,以太坊,区块链)