Solidity 0.8.0 新特性
- safe math
- custom errors
- functions outside contract
- import "合约文件" as 别名
1、safe math
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// safe math
contract SafeMath {
    // 执行此函数会 revert,因为 0 减 1 会溢出
    function testUnderflow() public pure returns (uint) {
        uint x = 0;
        x--;
        return x;
    }
    // 执行此函数会正常输出,但是 0 减 1 会溢出,输出结果为 2^256
    function testUncheckUnderflow() public pure returns (uint) {
        uint x = 0;
        // unchecked : 不检查是否溢出
        unchecked {
            x--;
        }
        return x;
    }
}
2、custom error
- 自定义错误,减少消耗 gas
- 自定义错误可以定义在合约外部或内部,定义在外部,可以让多个合约调用
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// 自定义错误可以定义在合约外部或内部,定义在外部,可以让多个合约调用
error Unauthorized2(address caller);
contract VendingMachine {
    address payable owner = payable(msg.sender);
    error Unauthorized(address caller);
    function withdraw() public {
        if (msg.sender != owner)
            // 23642 gass
            // revert("error");
            // 23678 gass
            // revert("error error error error error error error error error error error error");
            // 23388 gas
            // revert Unauthorized(msg.sender);
            revert Unauthorized2(msg.sender);
        owner.transfer(address(this).balance);
    }
}
3、functions outside contract
- 函数定义在合约之外,类似库类(library),但是只能进行简单操作
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// functions outside contract
function helper(uint x) view returns (uint) {
    return x * 2;
}
contract TestHelper {
    function test() external view returns (uint) {
        return helper(123);
    }
}
4、import "合约文件" as 别名
- 创建文件 OtherContract.sol 包含一个合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// OtherContract.sol
pragma solidity ^0.8.0;
contract OtherContract {
    uint256 public value;
    
    function setValue(uint256 newValue) external {
        value = newValue;
    }
}
- 在主合约中导入 OtherContract.sol 并为合约起别名:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./OtherContract.sol" as Other;
contract MyContract {
    Other.OtherContract public otherContract;
    
    constructor() {
        // 创建别名合约实例
        otherContract = new Other.OtherContract();
    }
    
    function setOtherContractValue(uint256 newValue) external {
        // 使用别名合约实例调用函数
        otherContract.setValue(newValue);
    }
}