Solidity 0.8부터 산술 연산은 오버플로와 언더플로에서 revert합니다. 끄려면 unchecked { ... } 블록으로 직접 밝혀야 합니다. Rust는 반대입니다. 디버그 빌드는 panic이 나지만 --release로 빌드하면 기본값이 2의 보수 감싸기입니다. Cargo 프로필에 overflow-checks = true를 넣어야 릴리스에서도 검사합니다. C는 부호 있는 오버플로가 미정의 동작이라 컴파일러가 사후 검사를 아예 지워 버리기도 합니다.
잔고를 옮기는 코드라면 Solidity 쪽 기본값이 맞다고 봅니다. 감싸진 결과는 틀린 잔고로 저장됩니다. revert는 트랜잭션 전체를 되돌립니다. 틀린 숫자가 영구히 남는 것보다 실패가 낫습니다.
그런데 둘 다 같은 구멍이 있습니다. Solidity에서 명시적 형 변환은 검사 모드에서도 잘라 냅니다. uint128(x)는 revert하지 않습니다. Rust의 as도 조용히 자릅니다. 검사한 덧셈 뒤에 좁히는 캐스트가 붙으면 사실상 검사하지 않은 것과 같습니다.
그래서 규칙을 이렇게 정했습니다. 금액 계산에는 unchecked를 쓰지 않습니다. Rust는 릴리스 프로필에서도 검사를 켭니다. 금액 캐스트는 try_from으로만 합니다. 혹시 릴리스 빌드에 overflow-checks를 켜 두신 분 계십니까? 비용이 눈에 띄는지 궁금합니다.