在Solidity0.4.10之前,错误处理模式是以if...throw形式展现,普遍用于判断一个条件是否满足,如果不满足则中断运行,但触发throw后它会撤回所有的状态更改,消耗剩余的所有gas,所以这并不是一个好的操作。之后,assert(), require(), revert() 三个函数代替了if...throw的功能,对gas有了更好的处理,提高了合约代码的可读性,但区分它们可能会有点混乱。

实验目的

1.明白require(),assert(),revert()三者的区别与作用。

实验要求

1. 请查看示例1中的两个函数。ShouldBeEven:这个函数用了require语句来检查传入的参数值是奇数还是偶数。如果传入值为偶数,继续往下执行下一个语句,否则抛出异常。再看第二个函数ValidUint8。请你补充代码,也用require语句来检查传入的值的范围是否在uint8的范围内。

2. 请查看示例2中的代码,函数validUint8对传入的数值进行了加20的操作,最后返回一个Uint8类型的值。思考当你调用函数validUint8传入的值为236-255范围内的任意值时,最后函数的返回值会是多少?如果结果有误,请你用assert语句补充好代码,在整型溢出时抛出异常。

3. 请查看示例3中的代码,调用函数validUint8,分别传入三个数值-1,125,256。查看三个数值的返回结果。思考solidity中对异常处理的require(),assert(),revert()三者之间的区别以及使用情况。

以下是本次实验所使用到的测试代码,请使用remix编辑器完成该实验

示例1:
// SPDX-License-Identifier: MIT 
pragma solidity ^0.8.0;
contract requireContract {
    function ShouldBeEven(uint _data)  public pure returns(bool){
        require(_data % 2 == 0);
        return true;
}
    function validUint8(int _data) public pure returns(int){
        //请你按要求补充代码
        return _data;
    }
}
示例2:
 // SPDX-License-Identifier: MIT 
pragma solidity ^0.8.0;
contract assertContract {
    function vaildUint8(uint _data) public pure returns(uint8){
        require(_data >= 0);
        require(_data <= 255);
        
        uint8 value = 20;
        //请你按要求在这一行补充好代码
        return uint8(value + _data);
    }
}
示例3:
// SPDX-License-Identifier: MIT 
pragma solidity ^0.8.0;
contract revertContract {
    function validUint8(int _data) public pure returns(int){
        if(_data < 0 || _data > 255) {
            revert();
        }
        return _data;
    }
}

下面是本次实验所配套的视频教程: