솔리디티는 오버플로우가 있다.
0.7.x이하 버전에서는 산술 오버플로우를 막을려고 SafeMath라이브러리를 사용해서 오버플로우/언더플로우를 막았고
0.8.x부터는 오버플로우나 언더플로우가 나면 라이브러리 없이 revert내서 트랜잭션을 취소시킨다.
물론 unchecked 블록을 쓰면 오버플로우/언더플로우가 난다. 그치만 이건 예외라서 패스
근데 최근 드림핵문제를 풀면서 오버플로우 관련 배운 개념을 배워서 기록하려고 한다.
일단 솔리디티에서 Value타입은 여러가지 있는데 그중 integer타입은 int 와 uint가 있다.
걍 int는 음수도 표현할 수 있는거고 uint는 양수만 표현할 수 있는 그 차이다.
signed unsigned 차이
그리고 솔리디티는 형변환이 가능하다.
그럼 int256 a = -1을 가정하자
근데 a를 uint256으로 형변환해서 다른 uint256 변수에 저장하면 어떤 일이 일어날까?
chisel로 간단히 살펴보자 :)
❯❯❯ chisel
Welcome to Chisel! Type `!help` to show available commands.
➜ int256 a = -1
➜ uint256 b = uint256(a)
➜ b
Type: uint256
├ Hex: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
├ Hex (full word): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
└ Decimal: 115792089237316195423570985008687907853269984665640564039457584007913129639935
➜ a
Type: int256
├ Hex: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
├ Hex (full word): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
└ Decimal: -1
uint256의 최댓값 즉, \(2^{256}-1\)이 됐다.
왜 그러냐면 int256 a의 경우 2의 보수표현법에 따라 -1은 111111...1111로 저장되는데
이걸 uint256으로 타입 캐스팅이 일어나면 비트는 그대로 유지되서 최댓값인 \(2^{256}-1\)되기 때문이다.
이건 산술오버플로우랑은 다르다. 타입캐스팅에 가까워 보인다.
그치만 0.8.x 버전이라고 오버플로우/언더플로우 생각안하고 코드를 짤때 충분히 버그 터뜨릴 수 있는 케이스인거 같다.
연산과정에서 터지는게 아닌 타입 변환에서 발생해서 revert도 안터지고 오버플로우는 오버플로우 그대로 터진다.
그리고 다른케이스에서도 오버플로우가 충분히 생길듯 예를 들어 비트연산 오류라던가... cetus 사례처럼
SafeMath라이브러리는 결국 덧셈,뺄셈,곱셈의 연산만 오버플로우나면 revert내기 때문이다.
즉 fuzzer나 심볼릭 실행 툴 등을 잘 써서 검증해야할듯하다.
halmos나 등등
'블록체인' 카테고리의 다른 글
| DeFi 담보 및 청산-1 (0) | 2025.06.03 |
|---|---|
| cetus 해킹 사고와 탈중앙화 (0) | 2025.05.31 |
| rust and solana (0) | 2025.05.22 |
| [ethernaut] (16 Preservation) (0) | 2025.05.12 |
| 솔라나 proc_macro2 `source_file` method not found in `Span` 에러 해결 (0) | 2025.05.03 |
내가 보고 내가 참고하려고 만든 블로그
틀린 내용이 있다면 댓글로 알려주시면 감사하겠습니다.