> For the complete documentation index, see [llms.txt](https://chihaolu.gitbook.io/all-in-one-solidity/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://chihaolu.gitbook.io/all-in-one-solidity/part-ii-medium/chapter-9-yi-chang-chu-li-handling-exception/try-catch.md).

# 【Try/Catch】

`try/catch` 用於確認外部執行函數和合約建立時（在一個合約裡面建立另外一個合約時）的錯誤，可以利用類條件式選擇來排除錯誤情況。

#### CATCH

我們有幾種宣告`catch` 的方法：

1. `catch Error (string memory /*reason*/)`：當我們宣告過了 `revert("reasonString")` 或 `require(false, "reasonString")`，且這些異常處理被觸發的話，`catch` 則會被執行。
2. `catch Panic(uint errorCode) { ... }`：此類型的`catch`會在各種`assert`、除以零、異常的陣列取值、運算溢位等情況發生時被執行。
3. `catch (bytes memory /*lowLevelData*/)`：當沒有其他符合的`catch`子句時，或是在decoding錯誤訊息時出現問題、甚至外部呼叫時出現assertion failing，便會執行此類`catch`。
4. 如果我們不在乎任何的Error Data，可以使用`catch { ... }`

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

// External contract used for try / catch examples
contract Foo {
    address public owner;

    constructor(address _owner) {
        require(_owner != address(0), "invalid address");
        assert(_owner != 0x0000000000000000000000000000000000000001);
        owner = _owner;
    }

    function myFunc(uint x) public pure returns (string memory) {
        require(x != 0, "require failed");
        return "my func was called";
    }
}

contract Bar {
    event Log(string message);
    event LogBytes(bytes data);

    Foo public foo;

    constructor() {
        // This Foo contract is used for example of try catch with external call
        foo = new Foo(msg.sender);
    }

    // Example of try / catch with external call
    // tryCatchExternalCall(0) => Log("external call failed")
    // tryCatchExternalCall(1) => Log("my func was called")
    function tryCatchExternalCall(uint _i) public {
        try foo.myFunc(_i) returns (string memory result) {
            emit Log(result);
        } catch {
            emit Log("external call failed");
        }
    }

    // Example of try / catch with contract creation
    // tryCatchNewContract(0x0000000000000000000000000000000000000000) => Log("invalid address")
    // tryCatchNewContract(0x0000000000000000000000000000000000000001) => LogBytes("")
    // tryCatchNewContract(0x0000000000000000000000000000000000000002) => Log("Foo created")
    function tryCatchNewContract(address _owner) public {
        try new Foo(_owner) returns (Foo foo) {
            // you can use variable foo here
            emit Log("Foo created");
        } catch Error(string memory reason) {
            // catch failing revert() and require()
            emit Log(reason);
        } catch (bytes memory reason) {
            // catch failing assert()
            emit LogBytes(reason);
        }
    }
}

```

#### TRY

`try`這個關鍵字必須要根據「外部函式呼叫」或「創建合約」這類的行為來定義，例如：`new ContractName()`。

而其中的`returns`部份是可有可無的，若需要的話，宣告`returns`部份必須要符合外部函式呼叫的回傳型態。

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.1;

interface DataFeed { function getData(address token) external returns (uint value); }

contract FeedConsumer {
    DataFeed feed;
    uint errorCount;
    function rate(address token) public returns (uint value, bool success) {
        // Permanently disable the mechanism if there are
        // more than 10 errors.
        require(errorCount < 10);
        try feed.getData(token) returns (uint v) {
            return (v, true);
        } catch Error(string memory /*reason*/) {
            // This is executed in case
            // revert was called inside getData
            // and a reason string was provided.
            errorCount++;
            return (0, false);
        } catch Panic(uint /*errorCode*/) {
            // This is executed in case of a panic,
            // i.e. a serious error like division by zero
            // or overflow. The error code can be used
            // to determine the kind of error.
            errorCount++;
            return (0, false);
        } catch (bytes memory /*lowLevelData*/) {
            // This is executed in case revert() was used.
            errorCount++;
            return (0, false);
        }
    }
}
```
