1. unchecked란?

unchecked는 Solidity 0.8.0부터 도입된 키워드로, 수학 연산에서 오버플로우(Overflow) 및 언더플로우(Underflow) 검사를 비활성화하는 역할을 합니다. Solidity 0.8.0부터 기본적으로 uint256int256 같은 정수형 연산에서 자동으로 오버플로우 및 언더플로우 검사가 활성화되었기 때문에, 특정 상황에서 성능 최적화를 위해 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 + buint256의 최대값(2³²⁵ - 1)을 초과하면, 자동으로 오버플로우 예외(revert) 가 발생합니다.


3. unchecked를 사용하여 검사를 비활성화하는 방법

unchecked 키워드를 사용하면, 오버플로우 및 언더플로우 검사를 생략하여 가스 비용을 절약할 수 있습니다.

contract UncheckedExample {
    function addUnchecked(uint256 a, uint256 b) public pure returns (uint256) {
        unchecked {
            return a + b;  // 오버플로우가 발생해도 revert되지 않음
        }
    }
}

위 코드에서 a + buint256의 최대값을 초과해도 예외(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 사용하지 말아야 하는 경우

사용 추천

  1. 반복문에서 카운터 증가 (i++) 연산이 수행될 때
  2. 값이 오버플로우될 가능성이 없는 경우 (ex: 이미 검증된 데이터)
  3. 낮은 가스 비용이 중요한 경우

사용 지양

  1. 외부 입력 값을 직접 연산할 때 (사용자가 임의의 값을 입력할 경우)
  2. 오버플로우 또는 언더플로우가 발생할 가능성이 높은 연산
  3. 보안이 중요한 금융 및 토큰 컨트랙트

8. 정리

  • unchecked는 Solidity 0.8.0 이후에 추가된 키워드로 오버플로우 및 언더플로우 검사를 비활성화할 수 있다.
  • 가스 절감 효과가 있지만, 버그 가능성이 증가하므로 주의해서 사용해야 한다.
  • 반복문 내의 카운터 증가 등 예측 가능한 연산에서 unchecked를 활용하면 최적화에 도움이 된다.
  • 외부 입력을 직접 다루거나 금융 관련 로직에서는 오버플로우/언더플로우 검사가 필요하므로 사용을 지양해야 한다.

+ Recent posts