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 를 씁니다. 이렇게 역할을 나눠 기억하세요.