Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions 30_TryCatch/TryCatch.sol
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

contract OnlyEven{
contract OnlyEven {
constructor(uint a){
require(a != 0, "invalid number");
assert(a != 1);
}

function onlyEven(uint256 b) external pure returns(bool success){
function onlyEven(uint256 b) external pure returns (bool success){
// 输入奇数时revert
require(b % 2 == 0, "Ups! Reverting");
success = true;
}
}

contract OnlyEven2 {
constructor(uint a){
require(a != 0, "invalid number");
assert(a != 1);
}

function onlyEven(uint256 b) external pure returns (uint256 success){
// 输入奇数时revert
require(b % 2 == 0, "Ups! Reverting");
success = b;
}
}

contract TryCatch {
// 成功event
event SuccessEvent();
Expand All @@ -27,12 +40,12 @@ contract TryCatch {
constructor() {
even = new OnlyEven(2);
}

// 在external call中使用try-catch
// execute(0)会成功并释放`SuccessEvent`
// execute(1)会失败并释放`CatchEvent`
function execute(uint amount) external returns (bool success) {
try even.onlyEven(amount) returns(bool _success){
try even.onlyEven(amount) returns (bool _success){
// call成功的情况下
emit SuccessEvent();
return _success;
Expand All @@ -47,7 +60,7 @@ contract TryCatch {
// executeNew(1)会失败并释放`CatchByte`
// executeNew(2)会成功并释放`SuccessEvent`
function executeNew(uint a) external returns (bool success) {
try new OnlyEven(a) returns(OnlyEven _even){
try new OnlyEven(a) returns (OnlyEven _even){
// call成功的情况下
emit SuccessEvent();
success = _even.onlyEven(a);
Expand All @@ -59,4 +72,32 @@ contract TryCatch {
emit CatchByte(reason);
}
}

// 调用非合约的方法,这里无法被try-catch捕获,会导致revert
function executeRevert() external {
try OnlyEven(address(0)).onlyEven(1){
// call成功的情况下
emit SuccessEvent();
} catch Error(string memory reason){
// catch revert("reasonString") 和 require(false, "reasonString")
emit CatchEvent(reason);
} catch (bytes memory reason){
// catch失败的assert assert失败的错误类型是Panic(uint256) 不是Error(string)类型 故会进入该分支
emit CatchByte(reason);
}
}

// 调用返回值不一致的方法,这里无法被try-catch捕获,会导致revert
function executeRevert2() external returns (bool success){
address onlyEven2 = address(new OnlyEven2(2));
uint256 amount = 2;
try OnlyEven(onlyEven2).onlyEven(amount) returns (bool _success){
// call成功的情况下
emit SuccessEvent();
return _success;
} catch Error(string memory reason){
// call不成功的情况下
emit CatchEvent(reason);
}
}
}
40 changes: 40 additions & 0 deletions 30_TryCatch/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,46 @@ function executeNew(uint a) external returns (bool success) {

![30-5](./img/30-5.png)

但是`try-catch`并不是万能的,有两种情况`try-catch`也无法捕获

1.在try中调用的非合约地址的方法,即codesize为0
```solidity
// 调用非合约地址的方法,这里无法被try-catch捕获,会导致revert
function executeRevert() external {
//将0地址强制转换为OnlyEven合约地址,模拟调用非合约地址的方法
try OnlyEven(address(0)).onlyEven(1){
// call成功的情况下
emit SuccessEvent();
} catch Error(string memory reason){
// catch revert("reasonString") 和 require(false, "reasonString")
emit CatchEvent(reason);
} catch (bytes memory reason){
// catch失败的assert assert失败的错误类型是Panic(uint256) 不是Error(string)类型 故会进入该分支
emit CatchByte(reason);
}
}
```
![30-6](./img/30-6.png)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个相关图片是不是没有在这个pr中


2.函数返回值与期望的不一致
```solidity
// 调用返回值不一致的方法,这里无法被try-catch捕获,会导致revert
function executeRevert2() external returns (bool success){
address onlyEven2 = address(new OnlyEven2(2));
uint256 amount = 2;
//OnlyEven2的返回值是 uint256,而这里期望的是bool,会导致revert
try OnlyEven(onlyEven2).onlyEven(amount) returns (bool _success){
// call成功的情况下
emit SuccessEvent();
return _success;
} catch Error(string memory reason){
// call不成功的情况下
emit CatchEvent(reason);
}
}
```
![30-7](./img/30-7.png)

## 总结

在这一讲,我们介绍了如何在`Solidity`使用`try-catch`来处理智能合约运行中的异常:
Expand Down