7

探究新的 Solidity 0.8 版本

 3 years ago
source link: https://learnblockchain.cn/article/2119
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何将你的合约升级到Solidity 0.8?

我们离Solidity 1.0的发布越来越近了(当然除非0.9之后是0.10)。 Solidity0.80.7发布 之后仅5个月就发布了!

登链社区正在同步翻译Solidity 0.8 的文档

今天我们就来探讨一下如何把合约迁移升级到 0.8 版本... ...

iuuI7vU.jpg!mobile

0.8新功能和如何使用

我们来看看两个大的新功能:集成的SafeMath和新的错误处理。

1. 集成SafeMath

MNZfYva.jpg!mobile

没错,你不需要再导入Openzeppelin SafeMath 了。 最重要的是,你不需要做任何事情就可以激活Solidity集成的SafeMath。 只要写上 a+b ,就会在溢出时自动回退交易。

你可能会在Remix等工具中看到如下错误提示,因为0.8还没有完全支持。 比如溢出还没有给出确切的原因。

transact to Solidity08.test errored: VM error: revert. revert

但这种情况在未来应该会有所改变。

如果你确实就希望代码能够溢出呢? 还是非常在意Gas费了?

则通过 unchecked 形式包装语句来停用SafeMath:

contract Solidity08 {
    function test() external pure returns(uint256) {
        // 默认使用 SafeMath ,此时会回退
        uint256 x = 0;
        x--;

        return x;
    }
}

contract Solidity08 {
    function test() external pure returns(uint256) {
        // 不使用SafeMath,返回 type(uint256).max

        uint256 x = 0;
        unchecked { x--; }

        return x;
    }
}

2. 无效的操作码被还原取代

到目前为止,某些操作会导致 INVALID 操作码的执行。 这个操作码的问题是,它消耗掉所有剩余的Gas。 这显然是不好的且没必要。 为什么要浪费Gas,把它捐给矿工?

更多细节,在 这里 查看 revertassert 的区别。

现在Solidity使用 revert 操作码。 为了区分常规revert和系统内部错误(panic),Solidity在返回数据前加上一个标识符:

  • 常规Revert错误keccak256(Error(string)) 的前四个字节开始,等于 0x08c379a0
  • **系统内部错误(Panic)**以 keccak256(Panic(uint256)) 的前四个字节开始,等于 0x4e487b71

Panic有一个额外的错误标识。 目前可用的Panic有:

  • 0x01 : 使用 asset
  • 0x11 : SafeMath的溢出。
  • 0x12 : 除以0。
  • 0x21 : 转换为不存在的枚举类型。
  • 0x22 : 存储字节数组编码错误。
  • 0x31 : 在一个空数组上 pop()
  • 0x32 : 索引超长度异常。
  • 0x41 : 分配过多的内存或创建过大的数组。
  • 0x51 : 调用未初始化的内部函数类型的变量。

更多细节请参见文档中新的错误处理部分 这里

如何迁移到Solidity 0.8

在大多数情况下,迁移应该是非常直接的。 只有在一些情况下,你做奇怪的类型转换可能会变得更加困难。

你必须为迁移做出的改变包括:

  • ABIEncoderV2 现在是默认自动激活。 从0.6开始,Encoder就不再是实验性的了,只是因为遗留的原因,保留了 pragma experimental 这个名字。 现在你不需要再加这行了。

  • 移除任何Openzeppelin SafeMath,你不再需要它了。

  • 可能需要进行一些类型转换。

    • msg.sendertx.origin 默认不属于payable类型。 将 msg.sender.transfer 改为 payable(msg.sender).transfer
    • 只有在符合给定类型的情况下,才允许类型转换,所以 uint256(-1) 将不再工作。 使用 type(uint256).max 代替。
    • 当多次改变符号时,类型转换在某些情况下会受到限制,因为类型转换的顺序可能会对结果产生影响。 你现在会看到一个类似TypeError的错误。 不允许从 int256bytes32 进行显示的类型转换,得先手动转换为uint256。
  • 修饰组合

    myContract.functionCall{gas: 10000}{value: 1 ether }()
    myContract.functionCall{gas: 10000, value: 1 ether }()
    
  • x**y**z 改为 (x**y)**z ,因为默认的执行顺序改变了。

  • byte 类型改为 byte1

我省略了一些细节,关于完整的变更日志和所有变更的细节,请查看文档 这里

本翻译由 Cell Network 赞助支持。

我们离Solidity 1.0的发布越来越近了(当然除非0.9之后是0.10)。 Solidity0.80.7发布 之后仅5个月就发布了!

登链社区正在同步翻译Solidity 0.8 的文档

今天我们就来探讨一下如何把合约迁移升级到 0.8 版本... ...

iuuI7vU.jpg!mobile

0.8新功能和如何使用

我们来看看两个大的新功能:集成的SafeMath和新的错误处理。

1. 集成SafeMath

MNZfYva.jpg!mobile

没错,你不需要再导入Openzeppelin SafeMath 了。 最重要的是,你不需要做任何事情就可以激活Solidity集成的SafeMath。 只要写上 a+b ,就会在溢出时自动回退交易。

你可能会在Remix等工具中看到如下错误提示,因为0.8还没有完全支持。 比如溢出还没有给出确切的原因。

transact to Solidity08.test errored: VM error: revert. revert

但这种情况在未来应该会有所改变。

如果你确实就希望代码能够溢出呢? 还是非常在意Gas费了?

则通过 unchecked 形式包装语句来停用SafeMath:

contract Solidity08 {
    function test() external pure returns(uint256) {
        // 默认使用 SafeMath ,此时会回退
        uint256 x = 0;
        x--;

        return x;
    }
}

contract Solidity08 {
    function test() external pure returns(uint256) {
        // 不使用SafeMath,返回 type(uint256).max

        uint256 x = 0;
        unchecked { x--; }

        return x;
    }
}

2. 无效的操作码被还原取代

到目前为止,某些操作会导致 INVALID 操作码的执行。 这个操作码的问题是,它消耗掉所有剩余的Gas。 这显然是不好的且没必要。 为什么要浪费Gas,把它捐给矿工?

更多细节,在 这里 查看 revertassert 的区别。

现在Solidity使用 revert 操作码。 为了区分常规revert和系统内部错误(panic),Solidity在返回数据前加上一个标识符:

  • 常规Revert错误keccak256(Error(string)) 的前四个字节开始,等于 0x08c379a0
  • 系统内部错误(Panic)keccak256(Panic(uint256)) 的前四个字节开始,等于 0x4e487b71

Panic有一个额外的错误标识。 目前可用的Panic有:

  • 0x01 : 使用 asset
  • 0x11 : SafeMath的溢出。
  • 0x12 : 除以0。
  • 0x21 : 转换为不存在的枚举类型。
  • 0x22 : 存储字节数组编码错误。
  • 0x31 : 在一个空数组上 pop()
  • 0x32 : 索引超长度异常。
  • 0x41 : 分配过多的内存或创建过大的数组。
  • 0x51 : 调用未初始化的内部函数类型的变量。

更多细节请参见文档中新的错误处理部分 这里

如何迁移到Solidity 0.8

在大多数情况下,迁移应该是非常直接的。 只有在一些情况下,你做奇怪的类型转换可能会变得更加困难。

你必须为迁移做出的改变包括:

  • ABIEncoderV2 现在是默认自动激活。 从0.6开始,Encoder就不再是实验性的了,只是因为遗留的原因,保留了 pragma experimental 这个名字。 现在你不需要再加这行了。

  • 移除任何Openzeppelin SafeMath,你不再需要它了。

  • 可能需要进行一些类型转换。

    • msg.sendertx.origin 默认不属于payable类型。 将 msg.sender.transfer 改为 payable(msg.sender).transfer
    • 只有在符合给定类型的情况下,才允许类型转换,所以 uint256(-1) 将不再工作。 使用 type(uint256).max 代替。
    • 当多次改变符号时,类型转换在某些情况下会受到限制,因为类型转换的顺序可能会对结果产生影响。 你现在会看到一个类似TypeError的错误。 不允许从 int256bytes32 进行显示的类型转换,得先手动转换为uint256。
  • 修饰组合

    myContract.functionCall{gas: 10000}{value: 1 ether }()
    myContract.functionCall{gas: 10000, value: 1 ether }()
    
  • x**y**z 改为 (x**y)**z ,因为默认的执行顺序改变了。

  • byte 类型改为 byte1

我省略了一些细节,关于完整的变更日志和所有变更的细节,请查看文档 这里

本翻译由 Cell Network 赞助支持。

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK