스마트 계약의 형식 검증과 AI 보조 감사
스마트 계약 감사에서의 형식 검증
형식 검증은 수학적 및 논리 기반 기술을 사용하여 스마트 계약의 정확성과 보안을 증명하는 것을 의미합니다. 실제로 이는 속성 기반 퍼즈 테스트와 심볼릭 실행부터 엄격한 정리 증명 및 모델 체킹에 이르기까지 다양한 방법론을 포함합니다. 목표는 계약이 명세를 충족하고 모든 가능한 입력과 상태에 걸쳐 악용 가능한 버그가 없음을 보장하는 것입니다. DeFi 프로토콜에 수십억 달러가 예치되어 있는 높은 위험을 고려할 때, 형식적 방법은 이더리움 및 기타 블록체인 플랫폼에서 점점 더 중요해지고 있습니다.
전통적인 접근 방식: 이더리움을 위한 초기 형식적 방법에는 Oyente 및 Mythril과 같은 심볼릭 실행 도구와 Slither 및 Securify와 같은 정적 분석기가 포함되었습니다. 심볼릭 실행은 심볼릭 입력을 사용하여 프로그램 경로를 탐색하여 재진입, 정수 오버플로우 등의 문제를 감지하는 반면, 정적 분석은 규칙 기반 패턴 매칭을 사용합니다. 이러한 도구들은 성공을 거두었지만 한 계도 있었습니다. 예를 들어, Oyente는 간단한 계약에서도 많은 오탐을 발생시켰고, Slither의 패턴 기반 탐지기는 여러 오탐을 생성할 수 있습니다. 더욱이 2023년 한 연구에 따르면, 악용 가능한 계약 버그의 80% 이상 (특히 복잡한 "비즈니스 로직" 버그)이 현재 도구들로는 발견되지 못했다는 사실은 더 강력한 검증 기술의 필요성을 강조합니다.
완전 검증의 가능성과 과제: 이론적으로, 형식 검증은 모든 상태에 대한 불변성을 철저히 확인함으로써 버그가 없음을 증명할 수 있습니다. Certora Prover나 이더리움 재단의 KEVM 프레임워크와 같은 도구들은 스마트 계약을 형식 명세에 대해 수학적으로 검증하는 것을 목표로 합니다. 예를 들어, Certora의 "자동화된 수학적 감사기"는 명세 언어 (CVL)를 사용하여 사용자가 정의한 규칙을 증명하거나 반증합니다. 그러나 실제로는 실제 계약에서 속성을 완전히 증명하는 것은 종종 불가능하거나 매우 노동 집약적입니다. 코드를 검증을 위해 단순화된 형태로 다시 작성해야 할 수도 있고, 맞춤형 명세를 작성해야 하며, 루프와 복잡한 산술은 수동으로 경계를 설정하거나 추상화해야 할 수 있으며, SMT 솔버는 복잡한 로직에서 자주 시간 초과됩니다. Trail of Bits 엔지니어들이 언급했듯이, *“버그가 없음을 증명하는 것은 일반적으로 중요하지 않은 코드베이스에서는 달성 불가능”*하며, 이를 달성하기 위해서는 사용자의 많은 개입과 전문 지식이 필요합니다. 이 때문에 형식 검증 도구는 전통적으로 전체 계약을 종단 간으로 검증하기보다는 토큰의 불변성이나 합의 알고리즘 검증과 같은 중요한 코드 조각에 드물게 사용되 어 왔습니다.
Foundry의 퍼즈 테스트와 불변성 테스트
최근 몇 년 동안, 속성 기반 테스트가 완전한 형식 증명의 실용적인 대안으로 부상했습니다. 인기 있는 이더리움 개발 프레임워크인 Foundry는 퍼즈 테스트와 불변성 테스트를 내장 지원합니다. 이 기술들은 테스트 커버리지를 크게 향상시키며 경량 형식 검증으로 볼 수 있습니다. Foundry의 퍼즈 테스트는 지정된 속성을 위반하려는 다수의 입력을 자동으로 생성하며, 불변성 테스트는 이를 상태 변경 작업의 시퀀스로 확장합니다:
-
퍼즈 테스트: 특정 입력에 대한 단위 테스트를 작성하는 대신, 개발자는 모든 입력에 대해 유지되어야 하는 속성이나 불변성을 지정합니다. 그러면 Foundry는 수백 또는 수천 개의 무작위 입력을 생성하여 함수를 테스트하고 속성이 항상 유지되는지 확인합니다. 이는 개발자가 수동으로 테스트할 생각을 하지 못할 수 있는 엣지 케이스를 잡는 데 도움이 됩니다. 예를 들어, 퍼즈 테스트는 함수의 반환 값이 항상 음수가 아니거나 특정 사후 조건이 입력에 관계없이 참임을 주장할 수 있습니다. Foundry의 엔진은 지능적인 휴리스틱을 사용합니다. 함수 시그니처를 분석하고 엣지 케이스 값 (0, max uint 등)을 도입하여 속성을 깨뜨릴 가능성이 있는 코너 케이스를 공략합니다. 만약 단언문이 실패하면, Foundry는 속 성을 위반하는 반례 입력을 보고합니다.
-
불변성 테스트: Foundry의 불변성 테스트 (또는 상태 기반 퍼징)는 한 걸음 더 나아가 여러 함수 호출과 상태 전환을 순차적으로 실행합니다. 개발자는 계약의 수명 주기 동안 항상 참이어야 하는 불변성 함수를 작성합니다 (예: 총자산 = 사용자 잔액의 합). 그러면 Foundry는 무작위 호출 시퀀스 (무작위 입력 포함)를 생성하여 가능한 많은 사용 시나리오를 시뮬레이션하고, 주기적으로 불변성 조건이 계속 참인지 확인합니다. 이는 특정 작업 시퀀스 후에만 나타나는 복잡한 버그를 발견할 수 있습니다. 본질적으로, 불변성 테스트는 계약의 상태 공간을 더 철저히 탐색하여 유효한 트랜잭션 시퀀스가 명시된 속성을 위반할 수 없음을 보장합니다.
Foundry가 중요한 이유: Foundry는 이러한 고급 테스트 기술을 쉽게 사용할 수 있도록 만들었습니다. 퍼징 및 불변성 기능은 개발자 워크플로우에 내재되어 있어 특별한 하네스나 외부 도구가 필요 없으며, 테스트는 단위 테스트와 함께 솔리디티로 작성됩니다. Rust 기반 엔진 덕분에 Foundry는 수천 개의 테스트를 신속하게 (병렬 처리하여) 실행하고 모든 불변성 위반에 대한 상세한 실패 추적을 제공할 수 있습니다. 개발자들은 Foundry의 퍼저가 사용하기 쉽고 성능이 뛰어나며, 반복 횟수를 설정하거나 입력을 제한하기 위한 가정을 추가하는 등 약간의 구성만 필요하다고 보고합니다. Foundry 문서의 간단한 예는 divide(a,b)
함수에 대한 퍼즈 테스트로, vm.assume(b != 0)
을 사용하여 사소한 유효하지 않은 입력을 피하고 result * b <= a
와 같은 수학 적 사후 조건을 단언합니다. 이러한 테스트를 수천 개의 무작위 (a,b)
쌍으로 실행함으로써 Foundry는 수동 추론으로는 찾기 어려운 엣지 케이스 (예: 오버플로우 경계)를 신속하게 발견할 수 있습니다.
비교: Foundry의 접근 방식은 커뮤니티의 이전 작업을 기반으로 합니다. Trail of Bits의 Echidna 퍼저는 이더리움을 위한 초기 속성 기반 테스트 도구였습니다. Echidna도 마찬가지로 불리언을 반환하는 솔리디티 함수로 표현된 불변성 위반을 찾기 위해 무작위 트랜잭션을 생성합니다. 이는 "지능적인" 입력 생성 (커버리지 기반 퍼징 포함)으로 알려져 있으며 많은 버그를 찾는 데 사용되었습니다. 실제로 보안 연구원들은 Echidna의 엔진이 매우 효과적이라고 언급합니다. “Trail of Bits의 Echidna는 지능적인 난수 선택 덕분에 최고의 퍼저입니다” – 하지만 Foundry의 통합된 워크플로우는 개발자가 테스트를 더 간단하게 작성할 수 있게 해줍니다. 실제로 Foundry의 퍼즈 테스트는 종종 안전한 솔리디티 개발을 위한 새로운 **“최소한의 기본 요건”**으로 간주되며, 전통적인 단위 테스트를 보완합니다. 이는 무작위적이고 철저하지 않기 때문에 버그가 없음을 증명할 수는 없지만, 방대한 범위의 입력과 상태 조합을 커버함으로써 신뢰도를 크게 높입니다.
퍼징을 넘어: 형식 증명과 고급 도구
퍼징과 불변성이 많은 문제를 잡아내지만, 더 강력한 형식적 방법이 사용되는 경우도 있습니다. 모델 체킹과 정리 증명은 원하는 속성을 형식 논리로 명시하고 자동화된 증명기를 사용하여 계약 코드에 대해 이를 확인하는 것을 포함합니다. Certora Prover (최근 오픈소스화)는 이 범주에서 두드러진 도구입니다. 개발자는 도메인 특화 언어 (CVL)로 규칙을 작성한 다음, 계약이 해당 규칙을 위반하는지 자동으로 확인할 수 있습니다. Certora는 MakerDAO 및 Compound와 같은 프로토콜에서 중요한 불변성을 검증하는 데 사용되었습니다. 예를 들어, MakerDAO에서 4년 동안 발견되지 않았던 "DAI 부채 불변성" 버그 (미묘한 회계 불일치)를 식별했습니다. 주목할 점은 Certora의 엔진이 이제 여러 플랫폼 (EVM, 솔라나의 VM, eWASM)을 지원하며, 2025년에 오픈소스화함으로써 이더리움, 솔라나, 스텔라에서 산업 등급의 형식 검증을 무료로 사용할 수 있게 되었다는 것입니다. 이 움직임은 형식 증명이 자금이 풍부한 팀만의 사치가 되어서는 안 된다는 인식을 반영합니다.
다른 형식 도구에는 런타임 검증 접근 방식 (예: 이더리움의 KEVM 시맨틱 또는 Move 기반 체인을 위한 Move Prover)이 포함됩니다. 특히 Move Prover는 Move 언어 (앱토스 및 수이 블록체인에서 사용)에 내장되어 있습니다. 이를 통해 코드와 함께 형식 명세를 작성하고, 린터나 타입 체커와 유사한 사용자 경험으로 특정 속성을 자동으로 증명할 수 있습니다. 이러한 긴밀한 통합은 해당 플랫폼의 개발자들이 개발의 일부로 형식 검증을 사용하는 장벽을 낮춥니다.
요약: 오늘날의 스마트 계약 감사는 이러한 방법론들을 혼합합니다. 퍼징 및 불변성 테스 트 (Foundry 및 Echidna가 대표적)는 사용 용이성과 일반적인 버그를 잡는 효과 때문에 널리 채택되고 있습니다. 심볼릭 실행 및 정적 분석기는 여전히 알려진 취약점 패턴을 신속하게 스캔하는 데 사용됩니다 (Slither와 같은 도구는 종종 CI 파이프라인에 통합됨). 한편, 형식 검증 도구는 성숙해지고 여러 체인으로 확장되고 있지만, 복잡성 때문에 일반적으로 특정 중요 속성이나 전문 감사 회사에서 사용됩니다. 실제로 많은 감사는 이러한 접근 방식을 결합합니다. 예를 들어, 퍼저를 사용하여 런타임 오류를 찾고, 정적 도구를 사용하여 명백한 실수를 표시하고, "토큰 잔액이 총 공급량을 초과하지 않음"과 같은 주요 불변성에 대해 형식 명세 검사를 사용합니다.
대규모 언어 모델을 이용한 AI 보조 감사
OpenAI의 GPT-3/4 (ChatGPT) 및 Codex와 같은 대규모 언어 모델 (LLM)의 등장은 스마트 계약 분석을 위한 새로운 패러다임을 도입했습니다. 방대한 양의 코드와 자연어로 훈련된 이 모델들은 프로그램 행동에 대해 추론하고, 코드를 설명하며, 패턴 인식과 "상식" 지식을 통해 특정 취약점을 탐지할 수도 있습니다. 문제는 AI가 스마트 계약 감사를 보강하거나 심지어 자동화할 수 있는가 하는 것입니다.