블록체인 학습
0 XP

커스텀 에러 (Custom Error)

require(condition, "긴 문자열") 의 문자열 메시지는 그대로 바이트코드에 저장되어 배포 비용을 늘리고, 되돌림이 일어날 때 그 문자열을 인코딩하느라 실행 gas 도 더 씁니다. 검증이 많은 컨트랙트라면 이 비용이 계속 쌓입니다.

Solidity 0.8.4 에 들어온 커스텀 에러(custom error) 가 이 문제를 해결합니다.

선언과 사용

커스텀 에러는 error 키워드로 선언하고, revert 와 함께 발생시킵니다. 컨트랙트 안이나 파일 최상단(전역) 어디에든 선언할 수 있습니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
error Unauthorized();
 
contract Vault {
    address public owner = msg.sender;
 
    function close() public view {
        if (msg.sender != owner) {
            revert Unauthorized();
        }
        // ... 정상 처리
    }
}

커스텀 에러가 더 저렴한 이유

커스텀 에러는 긴 문자열 대신, 에러 시그니처를 해시한 4바이트 선택자(selector) 로 인코딩됩니다. Unauthorized() 라는 의미가 단 4바이트로 압축되어 되돌려지는 것입니다.

문자열이 바이트코드에 들어가지 않으니 배포 크기가 줄고, 되돌림 시 인코딩할 데이터가 작으니 실행 가스도 줄어듭니다. 같은 정보를 더 싸게 전달하는 셈입니다.

커스텀 에러를 발생시키는 revert

커스텀 에러는 revert ErrorName() 형태로 발생시킵니다. Error(string) 으로 되돌리는 require/revert("...") 와는 인코딩 방식 자체가 다릅니다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
 
error DeadlinePassed();
 
contract Auction {
    uint256 public deadline;
 
    function bid() public view {
        if (block.timestamp > deadline) revert DeadlinePassed();
    }
}

커스텀 에러 이름은 PascalCase 로 짓고, 무엇이 잘못됐는지 드러나도록 의미 있게 만드세요. 예: InsufficientBalance, Unauthorized, DeadlinePassed.

커스텀 error 는 보통 revert ErrorName() 형태로만 발생시킵니다. require 의 두 번째 인자로 커스텀 에러를 직접 넘기는 문법은 비교적 최신 컴파일러에서만 지원되므로, 이 과정에서는 if (...) revert ... 패턴을 표준으로 씁니다.

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

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