블록체인

[solidity] 에러함수 - require, revert, assert

멍개. 2022. 8. 28. 07:15

olidity는 require, revert, assert가 호출되면 에러를 발생하고 rollback을 수행합니다. rollback이란 함수가 호출되기 전의 상태로 돌아가는 것을 의미합니다.

롤백(rollback)은 데이터베이스 관점에서 매우 중요합니다.

· revert + error

pragma solidity ^0.8.4;

error WowError(uint x, uint y);

contract SimpleStorage {
    uint public storedData;
 
    function set(uint x) public {
        if (x == 3){
            revert WowError(1, x);
        }
        storedData = x;
    }
}

revert()는 호출 됨과 동시에 에러를 발생시켜 rollback 처리합니다. 이때 error로 정의된 함수를 호출하여 커스텀 메시지를 만들 수 있습니다.

solidity에서는 에러를 만드는 방법이 몇가지 있습니다. revert()를 호출하는 방법도 있지만 require을 이용하는 방법도 있습니다.

revert 말고 require, assert도 존재합니다. revert는 require, assert 처럼 나온지는 한참되었습니다. 하지만 error 함수는 0.8.4 버전 이후에 등장했습니다.

revert 함수만 다루면 require과 assert가 섭섭해할테니 간략하게 다뤄보겠습니다.

· require

pragma solidity ^0.8.4;

contract SimpleStorage {
    uint storedData;
 
    function set(uint x) public {
        require(x != 3, "x is not 3");
        storedData = x;
    }
 
    function get() view public returns (uint) {
        return storedData;
    }
}

require은 첫 번째 인자로 boolean을 전달하고 두 번째 인자로 에러 메시지를 전달합니다. 첫 번째 인자가 false인 경우 에러를 발생시키고 두 번째 인자로 전달한 문자열을 알려줍니다.

require()의 두 번째 인자는 옵셔널하기 때문에 꼭 전달하지 않아도 됩니다.

· assert

pragma solidity ^0.8.4;

contract SimpleStorage {
    uint storedData;
 
    function set(uint x) public {
     
        storedData = x;
        
        assert(storedData != 3);
    }
 
    function get() view public returns (uint) {
        return storedData;
    }
}

require: 소유권 검사
revert: 데이터 유효성 검사 및 사전검사(예: 정상적으로 데이터가 들어왔는지, 계산에 필요한 만큼 값을 가지고 있는지)
assert: 연산 후 유효성 검사(예: overflow, underflow 검사)

여기서 assert의 검사를 빼먹는 경우가 종종 있는데 assert를 이용해서 반드시 overflow와 underflow 처리를 해야합니다.

※ overflow와 underflow

pragma solidity ^0.7.4;

contract SimpleStorage {
    uint min = 0;
    uint max = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
    function under() public view returns( uint) {
        return min - 1;
    }
    
    function over() public view returns( uint) {
        return max + 1;
    }
}

over 함수는 연산 결과는 최댓값에서 + 1을 하여 다시 0으로 돌아옵니다. 이를 오버플로우(overflow)라고 부릅니다.

under 함수는 최소값인 0에서 - 1을 하여 최대값이 됩니다. 이를 언더플로우(underflow)라고 합니다.

assert는 overflow, underflow 뿐 아니라 연산 결과가 정확히 나왔는지 검사하는것이 매우 중요하며 앞의 예시는 solidity 0.8.x 이후에선 발생하지 않습니다.

pragma solidity를 통해 다른 버전을 명시한 후 remix에서 컴파일러 버전을 바꿔주면 됩니다.

pragma solidity ^0.8.4;

contract SimpleStorage {
    uint min = 0;
    uint max = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
    function under() public view returns( uint) {
        return min - 1;
    }
    
    function over() public view returns( uint) {
        return max + 1;
    }
}

값에서 overflow, underflow가 일어나면 내부적으로 revert를 발생합니다.