-
에러 핸들러Block-Chain/Solidity 2023. 3. 7. 16:25
Solidity의 에러 핸들링 방법에 대해 정리하였습니다.
< assert, revert, require >
세 가지 에러 핸들러(assert, revert, require)는 정의된 조건에 부합하지 않으면, 에러를 발생시키는 함수입니다.
- assert : 특정한 조건에 부합하지 않으면(false일 때) 에러를 발생시키고, gas를 다 소비한다 : 테스트용으로 사용
- 형태 : assert(조건문) - revert : 조건없이 에러를 발생시키고, gas를 환불 시켜준다.
- 형태 : revert("에러 메세지") - require : 특정한 조건에 부합하지 않으면(false일 때) 에러를 발생시키고, gas를 환불 시켜준다.
- 형태 : require(조건문, "에러 메세지")
< 솔리디티 내의 함수 실행 프로세스 >
1. 특정 함수 선택 및 실행
2. 솔리디티가 "함수 실행을 위해, 이만큼의 가스를 지불해라" 라고 요구
3. 가스 비용을 지불
4. 함수 실행 중, 에러가 발생한다면 에러 이후의 실행안된 함수 내용 만큼, gas를 환불
하지만 assert의 경우 함수를 다 돌고 나서, assert를 체크하기 때문에 gas를 다 소비함.※ solidity 0.8.X 버전부터 assert는 오직 내부적 에러 테스트 용도 및 불변성 체크 용도로 사용하라고 나와있음.
그래서 assert 실행 시 revert로 실행되고, 가스 환불됨.
Ex)
function assertNow() public pure { assert(false): } function onlyAdults1uint256 _age) public pure returns(string memory) { if (_age < 19) { revert("You are not allowed to pay for the cigarette"); } return "" } function onlyAdults2uint256 _age) public pure returns(string memory) { require(_age > 19, "You are not allowed to pay for the cigarette"); return "" }
< try/catch >
try/catch 문법은 try문에서 에러를 잡아 catch문으로 넘긴 후, 그 안에서 에러 핸들링 코드를 작성함으로써 프로그램이 죽는 걸 방지하고 에러를 핸들링할 수 있습니다.
Catch에는 3가지 종류가 있습니다.
- catch Error(string memory reason) { ... } : revert나 require을 통해 생성된 에러
- catch Panic(uint errorCode) { ... } : assert를 통해 생성된 에러
- catch (bytesmemorylowLevelData) { ... } : 로우 레벨에러
-> 굳이 구분하지 않고 그냥 catch { ... } 만 사용해 에러 핸들링 코드 넣어도 됨.
Ex 1 : 외부 스마트컨트랙트의 함수 호출
contract math { function division(uint256 _num1, uint256 _num2) public pure returns (uint256) { require (_num1 < 10, "num1 should not be more than 10"); return _num1/_num2; } } contract runner { event catchErr(string _name, string _err); event catchPanic(string _name,uint256 _err); event catchLowLevelErr(string _name,bytes _err); math public mathInstance = new math(); function playTryCatch(uint256 _num1,uint256 _num2) public returns (uint256, bool) { try mathInstance.division(_num1, _num2) returns(uint256 value) { return (value, true); } catch Error(string memory _err) { emit catchErr("revert/require",_err); return(0,false); } catch Panic(uint256 _errorCode) { emit catchPanic("assertError/Panic",_errorCode); return(0,false); } catch (bytes memory _errorCode) { emit catchLowLevelErr("LowlevelError",_errorCode); return(0,false); } } }
Ex 2 : 외부 스마트컨트랙트 생성
contract character{ string private name; uint256 private power; constructor(string memory _name, uint256 _power){ name = _name; power = _power; } } contract runner{ event catchOnly(string _name,string _err); function playTryCatch(string memory _name, uint256 _power) public returns(bool successOrFail){ try new character(_name,_power) { return(true); } catch{ emit catchOnly("catch","ErrorS!!"); return(false); } } }
Ex 3 : 스마트컨트랙 내부 함수 호출
contract runner{ function simple() public returns(uint256){ return 4; } event catchOnly(string _name,string _err); function playTryCatch() public returns(uint256,bool){ try this.simple() returns(uint256 _value){ return(_value,true); } catch{ emit catchOnly("catch","ErrorS!!"); return(0,false); } } }
: 여기서 this 키워드는 현재 스마트 컨트랙트를 나타냄.
'Block-Chain > Solidity' 카테고리의 다른 글
Send Ethereum (0) 2023.04.04 Modifier & SPDX (0) 2023.03.22 조건문 & 반복문 (0) 2023.02.15 Mapping & Array & struct(구조체) (0) 2023.01.16 상속 & 이벤트 (0) 2023.01.05 - assert : 특정한 조건에 부합하지 않으면(false일 때) 에러를 발생시키고, gas를 다 소비한다 : 테스트용으로 사용