매개변수 있는 커스텀 에러
커스텀 에러는 함수처럼 매개변수 를 받습니다. 되돌림이 일어날 때 "왜 실패했는지"를 설명하는 실제 값을 함께 실어 보낸다는 뜻입니다. "insufficient balance" 같은 문자열 하나를 던지는 것보다 훨씬 많은 정보를 담으면서, 가스는 오히려 덜 듭니다.
매개변수 선언과 전달
선언부에 타입을 적고, revert 할 때 실제 값을 넘깁니다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// 요청 금액과 현재 잔액을 함께 알려주는 에러
error InsufficientBalance(uint256 requested, uint256 available);
contract Token {
mapping(address => uint256) public balanceOf;
function transfer(address to, uint256 amount) public {
uint256 bal = balanceOf[msg.sender];
if (amount > bal) {
revert InsufficientBalance(amount, bal);
}
balanceOf[msg.sender] = bal - amount;
balanceOf[to] += amount;
}
}거래가 되돌려질 때 requested 와 available 값이 선택자 뒤에 인코딩되어 호출 측(프런트엔드, 테스트, 다른 컨트랙트)으로 전달됩니다. 덕분에 "얼마를 요청했고 잔액이 얼마였는지"를 정확히 알 수 있습니다.
문자열 메시지보다 나은 점
문자열은 사람이 읽기엔 좋지만 동적인 값(숫자, 주소)을 끼워 넣기 어렵고 가스도 더 듭니다. 커스텀 에러는 타입이 있는 값을 그대로 전달하므로, 호출 측에서 코드로 분기하기도 쉽습니다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
error AccessDenied(address caller);
contract AdminOnly {
address public admin = msg.sender;
function doAdminThing() public view {
if (msg.sender != admin) revert AccessDenied(msg.sender);
}
}에러 매개변수에는 진단에 도움이 되는 값을 담으세요. 예: 요청값과 한도, 호출자 주소, 남은 마감 시간 등.
매개변수가 많아질수록 인코딩 비용이 조금씩 늘어납니다. 디버깅에 꼭 필요한 값만 담으세요.