Формальная верификация смарт-контрактов и аудит с помощью ИИ
Формальная верификация в аудите смарт-контрактов
Формальная верификация относится к использованию математических и логических методов для доказательства корректности и безопасности смарт-контрактов. На практике это охватывает спектр методологий: от фазз-тестирования на основе свойств и символического выполнения до строгого доказательства теорем и проверки моделей. Цель состоит в том, чтобы гарантировать соответствие контракта его спецификациям и отсутствие в нем эксплуатируемых ошибок при всех возможных входных данных и состояниях. Учитывая высокие ставки (миллиарды долларов заблокированы в DeFi-протоколах), формальные методы становятся все более важными для Ethereum и других блокчейн-платформ.
Традиционные подходы: Ранние формальные методы для Ethereum включали инструменты символического выполнения, такие как Oyente и Mythril, и статические анализаторы, такие как Slither и Securify. Символическое выполнение исследует пути программы с символическими входными данными для обнаружения проблем (например, реентрабельности, переполнения целых чисел), в то время как статический анализ использует сопоставление с образцом на основе правил. Эти инструменты имели успех, но также и ограничения: например, Oyente выдавал много ложных срабатываний даже на простых контрактах, а детекторы Slither, основанные на шаблонах, могли давать несколько ложных срабатываний. Более того, исследование 2023 года показало, что более 80% эксплуатируемых ошибок в контрактах (особенно сложных ошибок «бизнес-логики») были пропущены существующими инструментами, что подчеркивает необходимость более надежных методов верификации.
Перспективы и проблемы полной верификации: Теоретически, формальная верификация может доказать отсутствие ошибок путем исчерпывающей проверки инвариантов для всех состояний. Такие инструменты, как Certora Prover или фреймворк KEVM от Ethereum Foundation, направлены на математическую верификацию смарт-контрактов в соответствии с формальной спецификацией. Например, «автоматический математический аудитор» Certora использует язык спецификаций (CVL) для доказательства или опровержения правил, определенных пользователем. Однако на практике полное доказательство свойств для реальных контрактов часто недостижимо или очень трудоемко. Код может потребовать переписывания в упрощенные формы для верификации, должны быть написаны пользовательские спецификации, циклы и сложная арифметика могут потребовать ручных ограничений или абстракций, а SMT-солверы часто превышают время ожидания при сложной логике. Как отметили инженеры Trail of Bits, «доказательство отсутствия ошибок обычно недостижимо» для нетривиальных кодовых баз, и его достижение часто требует значительного вмешательства пользователя и экспертных знаний. Из-за этого инструменты формальной верификации традиционно использовались редко для критически важных частей кода (например, для верификации инварианта токена или алгоритма консенсуса), а не для целых контрактов от начала до конца.
Фазз-тестирование и тестирование инвариантов Foundry
В последние годы тестирование на основе свойств стало практической альтернативой полным формальным доказательствам. Foundry, популярный фреймворк для разработки Ethereum, имеет встроенную поддержку фазз-тестирования и тестирования инвариантов — методов, которые значительно улучшают покрытие тестами и могут рассматриваться как облегченная формальная верификация. Фазз-тестирование Foundry автоматиче ски генерирует большое количество входных данных, чтобы попытаться нарушить заданные свойства, а тестирование инвариантов распространяет это на последовательности операций, изменяющих состояние:
-
Фазз-тестирование: Вместо написания модульных тестов для конкретных входных данных разработчик указывает свойства или инварианты, которые должны выполняться для любых входных данных. Foundry затем генерирует сотни или тысячи случайных входных данных для тестирования функции и проверяет, что свойство всегда выполняется. Это помогает выявить граничные случаи, которые разработчик мог бы не догадаться протестировать вручную. Например, фазз-тест может утверждать, что возвращаемое значение функции всегда неотрицательно или что определенное постусловие истинно независимо от входных данных. Движок Foundry использует интеллектуальные эвристики — он анализирует сигнатуры функций и вводит граничные значения (0, максимальное uint и т. д.) — для охвата граничных случаев, которые, вероятно, нарушат свойство. Если утверждение не выполняется, Foundry сообщает входной контрпример, кот орый нарушает свойство.
-
Тестирование инвариантов: Тестирование инвариантов Foundry (также называемое фаззингом с учетом состояния) идет дальше, выполняя множественные вызовы функций и переходы состояний последовательно. Разработчик пишет инвариантные функции, которые должны оставаться истинными на протяжении всего срока службы контракта (например, общие активы = сумма балансов пользователей). Foundry затем случайным образом генерирует последовательности вызовов (со случайными входными данными) для имитации множества возможных сценариев использования, периодически проверяя, что условия инвариантов остаются истинными. Это может выявить сложные ошибки, которые проявляются только после определенной последовательности операций. По сути, тестирование инвариантов более тщательно исследует пространство состояний контракта, гарантируя, что ни одна последовательность действительных транзакций не может нарушить заявленные свойства.
Почему Foundry важен: Foundry сделал эти передовые методы тестирования доступными. Функции фаззинга и инвариантов