Solidity 0.5 的一些新变化

  • Ashton
  • 更新于 2019-03-06 10:43
  • 阅读 3351

Solidity 0.5 的一些新变化

没接触过 Solidity 的,能把这篇文章读完的话,我由衷的佩服你。

0x00 为啥要关注新变化

因为以前用 Solidity 写的合约在带有最新编译器的 IDE 显示是下面这个样子的。左边每一个小红叉都代表编译不通过。也难怪负责合约的小伙伴会经常在身边发出各种疑问。

Solidity 从 0.5.0 开始做了很多变化,这些变化基本上都可以说是改进。下面只是摘几个经常碰到的变化聊聊。

0x01 更严格的语法限制

  1. 强制函数的可见性描述 之前这样定义函数是可以的,默认可见性就是 public
function transfer(address _to, uint256 _value) returns (bool success);

现在必须显示声明可见性为 public/private/internal/external

function transfer(address _to, uint256 _value) public returns (bool success);

对于回退函数(fallback function),接口里的函数必须声明为 external,以表明这两类函数都只能被外部调用。

这些约束,让代码量看起来更多了,但也使代码的可读性增强很多,看代码的人再也不用费脑细胞去分析和猜测这些函数的作用范围了。

  1. 对于结构体、数组、映射这些类型必须显示声明数据位置是 storage 还是 memory,不管这些类型出现在函数体内还是函数的参数与返回值中。 以前这样的代码是可以的:
uint[] x = m_x

现在必须写为

uint[] storage x = m_x

对于可见性为 external 的函数,上面提到的这些类型的数据位置必须是 calldata。calldata 和 memory 会有啥区别呢?有知道的同学帮忙留言说明一下呗。

  1. 构造函数必须用 constructor 以前一直还支持与合约名称同名函数即为构造函数这个方式

  2. throw 被废弃,强制使用 require/assert 下面这种方式成为历史。

if (expiry > 1000000) throw;

应该使用 require。

require(expiry <= 100000)
  1. 将合约与地址强制区分开 现在如果要调用只在地址而非合约上存在的方法,比如 transfer,send 等,都需要将合约显式转换为地址类型。
this.balance

要转换为下面这种方式才成

address(this).balance

其实发现上面这些改完代码基本上就可以在 Solidity 0.5.x 的编译器编译通过了。

0x02 地址分为 address 和 address payable 两种类型

最主要的作用是用来区分合约是否可以接受转账。 下面的代码,需要 Wallet 合约必须带有 payable fallback 函数,否则就会报 transfer 函数不存在的编译错误。

 function withdraw() public {
       Wallet w = new Wallet();
       address(w).transfer(1);
   }

在通过参数传入一个地址接受转账时,地址参数也必须声明为 payable 的

 function withdraw(address payable wallet) public {
       wallet.transfer(1);
   }

这也影响到 selfdestruct 的使用,下面这样的代码不再有效

 function kill() public {
       selfdestruct(this);
   }

需要转换一下

 function kill() public {
       selfdestruct(address(uint160(address(this))));
   }

访问 msg.value 也必须在 payable 的函数中进行。

0x03 其它

还有很多其它的变化,比如下面的位移运算,之前结果是 -1,现在结果是 -2。

-5 >> 2

之后碰到值得记录的再记吧,记下来的,无非使自己印象更深一些。

点赞 0
收藏 0
分享

0 条评论

请先 登录 后评论
Ashton
Ashton
专注于 EVM 和比特币生态的区块链开发者