1. unchecked란?
unchecked는 Solidity 0.8.0부터 도입된 키워드로, 수학 연산에서 오버플로우(Overflow) 및 언더플로우(Underflow) 검사를 비활성화하는 역할을 합니다. Solidity 0.8.0부터 기본적으로 uint256 및 int256 같은 정수형 연산에서 자동으로 오버플로우 및 언더플로우 검사가 활성화되었기 때문에, 특정 상황에서 성능 최적화를 위해 unchecked를 사용할 수 있습니다.
2. 기본적인 오버플로우 및 언더플로우 검사
Solidity 0.8.0 이후에는 기본적으로 정수형 연산이 자동으로 안전 검사를 수행합니다.
// Solidity 0.8.0 이상에서는 자동으로 오버플로우/언더플로우 체크가 수행됨
contract OverflowExample {
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b; // 오버플로우 발생 시 자동으로 revert
}
}
위 코드에서 a + b가 uint256의 최대값(2³²⁵ - 1)을 초과하면, 자동으로 오버플로우 예외(revert) 가 발생합니다.
3. unchecked를 사용하여 검사를 비활성화하는 방법
unchecked 키워드를 사용하면, 오버플로우 및 언더플로우 검사를 생략하여 가스 비용을 절약할 수 있습니다.
contract UncheckedExample {
function addUnchecked(uint256 a, uint256 b) public pure returns (uint256) {
unchecked {
return a + b; // 오버플로우가 발생해도 revert되지 않음
}
}
}
위 코드에서 a + b가 uint256의 최대값을 초과해도 예외(revert)가 발생하지 않고 값이 wrap-around(순환)되어 0부터 다시 시작됩니다.
4. 언더플로우 예시
언더플로우(Underflow)는 uint256 값이 0보다 작은 값을 가지려 할 때 발생합니다.
contract UnderflowExample {
function subtractChecked(uint256 a, uint256 b) public pure returns (uint256) {
return a - b; // a < b이면 자동으로 revert
}
function subtractUnchecked(uint256 a, uint256 b) public pure returns (uint256) {
unchecked {
return a - b; // a < b이면 언더플로우 발생하여 큰 값으로 wrap-around됨
}
}
}
예를 들어, subtractUnchecked(0, 1)을 호출하면 일반적으로는 revert되지만, unchecked 블록을 사용하면 uint256의 최대값(2³²⁵ - 1)로 변환됩니다.
5. unchecked를 사용할 때의 장점과 단점
| 항목 | 설명 |
|---|---|
| ✅ 장점 | - 연산 비용(가스)를 절약할 수 있음 |
| ✅ 장점 | - 특정 상황에서 불필요한 검사를 줄여 최적화 가능 |
| ❌ 단점 | - 오버플로우 및 언더플로우가 발생해도 예외가 발생하지 않음 |
| ❌ 단점 | - 개발자가 직접 오버플로우를 방지해야 하므로 버그 발생 가능성 증가 |
6. unchecked를 사용할 때의 권장 사항
루프 내에서 가스 절감을 위해 사용
예를 들어, 단순한 카운터 증가 연산에서는 오버플로우가 발생할 가능성이 낮으므로unchecked를 사용하면 가스 비용을 절약할 수 있습니다.contract LoopOptimization { function sum(uint256 n) public pure returns (uint256) { uint256 total; for (uint256 i = 0; i < n; ) { unchecked { total += i; i++; // unchecked 블록을 사용하면 가스 비용 절감 가능 } } return total; } }명확한 범위를 가진 변수에 사용
uint256의 최대값을 초과할 가능성이 없거나, 사용 범위가 확실한 경우unchecked를 활용하여 성능을 최적화할 수 있습니다.예상 가능한 오버플로우가 발생하지 않는 경우
예를 들어, Solidity 컨트랙트에서 토큰 발행량이 이미 검증되었고uint256범위를 초과할 가능성이 없을 때 사용할 수 있습니다.
7. unchecked를 사용해야 하는 경우 vs 사용하지 말아야 하는 경우
✅ 사용 추천
- 반복문에서 카운터 증가 (
i++) 연산이 수행될 때 - 값이 오버플로우될 가능성이 없는 경우 (ex: 이미 검증된 데이터)
- 낮은 가스 비용이 중요한 경우
❌ 사용 지양
- 외부 입력 값을 직접 연산할 때 (사용자가 임의의 값을 입력할 경우)
- 오버플로우 또는 언더플로우가 발생할 가능성이 높은 연산
- 보안이 중요한 금융 및 토큰 컨트랙트
8. 정리
unchecked는 Solidity 0.8.0 이후에 추가된 키워드로 오버플로우 및 언더플로우 검사를 비활성화할 수 있다.- 가스 절감 효과가 있지만, 버그 가능성이 증가하므로 주의해서 사용해야 한다.
- 반복문 내의 카운터 증가 등 예측 가능한 연산에서
unchecked를 활용하면 최적화에 도움이 된다. - 외부 입력을 직접 다루거나 금융 관련 로직에서는 오버플로우/언더플로우 검사가 필요하므로 사용을 지양해야 한다.
'Solidity' 카테고리의 다른 글
| Ether 전송 : transfer() vs call() (0) | 2025.03.19 |
|---|---|
| 예외 처리: require() vs. revert() (0) | 2025.03.19 |
| 재진입공격 방지기법-nonReentrant (0) | 2025.02.21 |
| Solidity 에서 메모리 읽기 - mload() 와 add() (0) | 2025.02.20 |
| 저수준 호출(low-level call) 문법 - call, staticCall, delegateCall (0) | 2025.02.20 |