블록체인 학습
0 XP

Solidity 에러의 종류

스마트 컨트랙트는 잘못된 입력이나 비정상 상태를 만나면 거래를 되돌려(revert) 자산과 데이터를 지켜야 합니다. 일반 프로그래밍 언어의 try/throw 와 달리, 이더리움에서 거래가 되돌려지면 그 거래에서 일어난 모든 상태 변경이 원자적으로(all-or-nothing) 취소됩니다. 절반만 처리되어 잔액이 새어나가는 일이 없다는 뜻입니다.

Solidity 는 이 되돌리기를 표현하는 도구로 require, revert, assert 세 가지를 제공합니다. 셋은 역할이 서로 다릅니다.

입력과 조건을 검증하는 require

함수의 입력값이나 호출 조건이 올바른지 확인할 때 사용합니다. 조건이 거짓이면 즉시 되돌립니다. 가장 흔하게 쓰이는 도구로, 사용자가 보낸 값이나 권한을 가장 먼저 검사하는 자리에 둡니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract Wallet {
    function withdraw(uint256 amount) public pure {
        require(amount > 0, "amount must be positive");
        // ... 출금 로직
    }
}

직접 되돌릴 때 쓰는 revert

복잡한 조건문 안에서 직접 거래를 되돌릴 때 사용합니다. if 와 함께 자주 쓰이고, 가스를 아끼는 커스텀 에러(revert ErrorName())를 발생시킬 수 있는 유일한 통로이기도 합니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract Profile {
    function setAge(uint256 age) public pure {
        if (age > 150) {
            revert("age is unrealistic");
        }
    }
}

내부 불변식을 검사하는 assert

"절대 일어나면 안 되는" 내부 상태를 검사합니다. 코드가 정상이라면 결코 실패하지 않아야 하는 곳에만 씁니다. 0.8 부터 assert 실패는 일반 Error(string) 가 아니라 Panic(uint256) 타입으로 되돌려집니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
contract Math {
    function half(uint256 x) public pure returns (uint256) {
        uint256 result = x / 2;
        assert(result * 2 <= x); // 정상이라면 절대 깨지지 않는 불변식
        return result;
    }
}

0.8 부터는 세 도구 모두 실패 시 남은 gas 를 호출자에게 환불합니다. 다만 assert 는 Error(string) 이 아니라 Panic(uint256) 을 발생시켜 "코드에 버그가 있다"는 신호를 남깁니다. 그래서 assert 는 사용자 입력이 아니라 내부 버그 탐지용으로만 제한적으로 씁니다.

사용자 입력을 검증할 때는 require, 복잡한 분기 끝에서 직접 되돌릴 때는 revert(특히 커스텀 error), 내부 불변식을 보증할 때는 assert 를 씁니다. 이렇게 역할을 나눠 기억하세요.

Code Editor
에디터를 불러오는 중...
실행 결과

Run 버튼을 눌러 코드를 실행하세요.