ReasonJun

Solidity : try / catch 본문

Blockchain/Solidity

Solidity : try / catch

ReasonJun 2023. 10. 17. 18:17
728x90

The try / catch statement in Solidity is used to handle errors in external function calls and contract creation. It is similar to the try / catch statement in other programming languages, but there are some important differences.

 

How to use try / catch

 

To use the try / catch statement, you first need to wrap the external function call or contract creation in a try block. The try block will be executed as usual, but if an error occurs, the execution will jump to the catch block.

The catch block can be used to handle the error in any way you want. For example, you can log the error, revert the transaction, or retry the call.

 

Example

The following code shows how to use the try / catch statement to handle an error in an external function call:

contract Example {
    function callExternalFunction() public {
        try otherContract.someFunction() {
            // do something
        } catch Error(string memory reason) {
            // handle the error
        } catch Panic(uint errorCode) {
            // handle the error
        }
    }
}

In this example, the callExternalFunction() function calls the someFunction() function on the otherContract contract. The someFunction() function is an external function, so it could potentially throw an error.

 

If the someFunction() function throws an error, the execution will jump to the catch block. The catch block can be used to handle the error in any way you want.

 

Tips for using try / catch effectively

 

Here are some tips for using the try / catch statement effectively:

  • Only use the try / catch statement for external function calls and contract creation. The try / catch statement cannot be used to handle errors in internal function calls.
  • Handle errors in the catch block in a consistent and predictable way. This will make your code more robust and easier to maintain.

Conclusion

The try / catch statement is a powerful tool that can be used to improve the error handling, readability, and maintainability of Solidity code. By understanding how to use the try / catch statement effectively, you can write better and more robust contracts.

 

 

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract Error_1 {
    event ErrorReason1(string reason);
    event ErrorReason2(uint errorCode);
    event ErrorReason3(bytes lowLevelData);

    function output5(uint _num) public pure returns (uint) {
        if(_num >= 6) {
            revert("_num should be 5");
        }
        if(_num <= 4) {
            assert(false);
        }
        return 5;
    }

    function output5WithTryCatch(uint _num) public returns(uint256, bool) {
        
        try this.output5(_num) returns (uint256 value) {
            return(value, true);
        } catch Error (string memory reason) {
            emit ErrorReason1(reason);
            return(0, false);
        } catch Panic(uint errorCode) {
            emit ErrorReason2(errorCode);
            return(0, false);
        } catch (bytes memory lowLevelData) {
            emit ErrorReason3(lowLevelData);
            return(0, false);
        }
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract Adult {
    uint public age;
    constructor(uint _age) {
        require(_age > 19, "Should be more than 19 years old");
        age = _age;
    }
}

contract trycatch{
    event Information(string _error);

    function instantiate(uint _age) public returns(uint) {
        try new Adult(_age) returns(Adult adult) {
            emit Information("Success");
            return (adult.age());
        } catch {
            emit Information("Failed : the default age is 20");
            Adult adult = new Adult(20);
            return(adult.age());
        }
    }
}

external 

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

// external function + try / catch

contract Math {
    function division(uint _num1, uint _num2) public pure returns(uint) {
        return _num1/_num2;
    }
}

contract external_try {
    event Information(string _error);
    Math math = new Math();

    function divisionWithTryCatch(uint _num1, uint _num2) public returns(uint) {
        try math.division(_num1, _num2) returns (uint result) {
            emit Information("Success");
            return(result);
        } catch {
            emit Information("Failure");
            return (0);
        }
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

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;
    //The output of the decode function shows that the value of the foo variable is the address of a deployed Foo contract: 0x09Db51206dd025Ec527746b19690fDC22B483DC7.

    constructor() {
        foo = new Foo(msg.sender);
    }

    function tryCatchExternalCall(uint _i) public {
        try foo.myFunc(_i) returns (string memory result) {
            emit Log(result);
        } catch {
            emit Log("external call failed");
        }
    }

    function tryCatchNewContract(address _owner) public {
        try new Foo(_owner) returns (Foo foo) {
            emit Log("Foo created");
        } catch Error(string memory reason) {
            emit Log(reason);
        } catch (bytes memory reason) {
            emit LogBytes(reason);
    }
    }

}
728x90

'Blockchain > Solidity' 카테고리의 다른 글

Solidity : send()  (0) 2023.10.18
Solidity : payable  (0) 2023.10.18
Solidity : require  (0) 2023.10.17
Solidity : revert  (0) 2023.10.17
Solidity : assert  (0) 2023.10.17
Comments