Аудит безопасности смарт-контрактов: критерии оценки кода и уязвимостей
Сканер может вернуть чистый отчет по контракту, в котором цена залога читается из спотового пула, ликвидность пополняется в рамках одной транзакции, а решение governance опирается на моментальный снимок состояния.

Ни один модуль по отдельности не обязан содержать очевидный баг. Уязвимость возникает на стыке: атакующий изменяет цену, использует заемный капитал и совершает действие до восстановления исходного состояния. Такой composition failure статический анализ обычно не видит.
Поэтому аудит безопасности смарт-контрактов и критерии оценки кода должны охватывать архитектуру протокола, бизнес-инварианты и последовательность транзакций. Рабочий отчет привязан к конкретному commit, содержит воспроизводимый путь эксплуатации и позволяет проверить, закрыла ли remediation исходную уязвимость.
Гибридная архитектура аудита
Полноценная проверка контракта состоит из автоматического анализа, ручного ревью, формальной верификации отдельных свойств и проверки эксплойтов. Эти слои решают разные задачи и потому не взаимозаменяемы.
| Слой проверки | Что он выявляет | Граница применения |
|---|---|---|
| Slither | Известные паттерны уязвимостей, зависимости данных, граф вызовов, особенности inheritance и visibility | Не понимает полный бизнес-контекст и пропускает логические ошибки |
| MythX | Поведение контракта по модели, потоки данных, нарушения заданных свойств | Качество вывода зависит от модели и допущений анализатора |
| Ручное ревью | Инварианты, полномочия, порядок обновления состояния, экономические edge cases | Требует времени и высокой квалификации аудитора |
| Формальная верификация | Достижимость состояний и сохранение свойств в ограниченной модели | Доказывает свойство только внутри заданных границ модели |
| Proof of Concept | Фактическую достижимость эксплойта и его последствия | Требует корректного окружения и воспроизведения состояния |
По данным отраслевой практики, на ручной анализ приходится около 60–70% трудозатрат комплексного аудита. Это естественно: статический анализ хорошо локализует дефекты с известной сигнатурой, но бизнес-логика остается зоной ответственности человека.
Ручное ревью начинается с модели протокола. Аудитор восстанавливает роли, полномочия, допустимые переходы состояния и источники внешних данных. Затем проверяются call trace, порядок обновления storage, обработка revert, взаимодействие с прокси и зависимости от других контрактов. Только после этого дефекты из отчетов Slither и MythX классифицируются: часть находок оказывается ложными срабатываниями, часть объединяется с общей первопричиной.
Сканер показывает, где код похож на известную ошибку. Аудит устанавливает, можно ли нарушить инвариант протокола.
Типичная ошибка заказчика — оценивать аудит по числу страниц или количеству findings. Показательнееcoverage: какие модули проверялись, какие сценарии невозможны без внешней инфраструктуры и какие предположения лежат в основе каждой критической находки.
Стандарты верификации: SCSVS, SCWE и OWASP Top 10
Единого общемирового юридического или отраслевого норматива аудита смарт-контрактов не существует. Проекты строят внутренние процедуры на основе OWASP, SWC и отраслевых методик. Поэтому название «аудит» само по себе не задает глубину проверки.
В SCSVS v0.0.1 предусмотрено 35 контролей, распределенных по 11 категориям. Это удобная матрица покрытия: аудитор показывает, какие контроли выполнены, какие дали отрицательный результат, какие признаны неприменимыми и какие вынесены за границы scope. Простой итог «проверено 100%» здесь бесполезен. Нужны ссылки на конкретные проверки, коммиты и артефакты.
SCWE содержит 156 слабостей, а реестр SWC помогает сопоставлять находки с известными классами дефектов. Эти классификации решают задачу обмена информацией между аудиторами, но не определяют серьезность каждого инцидента.
В OWASP Smart Contract Top 10, представленном категориями SC01–SC10, отдельно выделены риски манипуляции ценовыми оракулами, использования флеш-займов и нарушений контроля доступа. Для рабочего аудита полезно разделять четыре сущности:
1. Контроль отвечает на вопрос, что именно требуется проверить.
2. Слабость описывает общий класс ошибки.
3. Finding фиксирует конкретную уязвимость в конкретной реализации.
4. Severity ранжирует риск для текущей архитектуры и бизнес-процесса.
Эти четыре уровня часто смешивают. Отчет может содержать сотню findings, при этом не покрывать критические категории SCSVS. И наоборот: один аккуратно описанный дефект в upgradeable-контракте опаснее десятка замечаний о читаемости кода.
Критические векторы угроз
Контроль доступа и инициализация
Ошибка доступа часто находится в жизненном цикле контракта, а не в его основной логике. Проверяются конструктор и initializer, состояние proxy, первоначальный admin, порядок вызовов при деплое, а также возможность повторной инициализации.
Отдельный класс находок связан с привилегированными функциями: изменение реализации proxy, настройка oracle, смена параметров, начисление вознаграждений, приостановление операций. Здесь нужна матрица ролей: кто может вызвать функцию, через какой адрес или multisig, существует ли timelock и как изменяется набор полномочий.
Централизация сама по себе редко является багом. Если владелец контролирует вывод средств по замыслу, это риск доверия и компрометации ключа. Дефектом это становится, когда документация обещает ограниченные полномочия, а код предоставляет расширенные.
Манипуляция ценовыми оракулами
Цена, взятая из спотового пула, является рыночной наблюдаемой величиной с конкретными границами ликвидности. Внутри одной транзакции она может быть кратно сдвинута внесением капитала, выводом ликвидности или исполнением крупного свопа.
Аудит должен проследить путь цены: источник, агрегатор, задержка обновления, обработка устаревших данных, точность decimals и поведение при недоступности источника. Отдельно проверяются fallback-сценарии и возможность использовать цену до обновления oracle.
TWAP и другие механизмы усреднения снижают зависимость от одного момента, но добавляют задержку и собственные допущения. Если протокол использует такой механизм, аудитору нужен анализ задержки, допустимого отклонения цены и поведения при резком изменении рынка.
Флеш-займы
Флеш-займ — не уязвимость, а усилитель экономических атак. Капитал доступен в рамках одной транзакции и должен быть возвращён до её завершения. Эта атомарность позволяет влиять на голосование, залог, ликвидацию или цену актива без длительного удержания позиции.
Проверяются сценарии, где значимая доля голосов зависит от временного баланса, collateral оценивается по изменяемой цене, ликвидация запускается при манипулируемом коэффициенте, либо экономическая целесообразность свопа зависит от заемных средств. Полезно также учитывать порядок исполнения транзакций в мемпуле и влияние private order flow.
PoC для такого класса должен показывать полный цикл: получение капитала, манипуляцию, выгодное действие, погашение займа и итоговый profit или loss. Демонстрация одного аномального значения цены недостаточна.
Reentrancy и порядок внешних вызовов
Реентранси остается классической уязвимостью, хотя с 2016 года, после атаки The DAO, разработчики активно применяют checks-effects-interactions и reentrancy guards. На уровне отдельных функций ошибка может выглядеть безобидно: внешний вызов происходит раньше обновления состояния, а callback успевает вернуться в исходный контекст.
Проверяются межфункциональная reentrancy, повторные входы через произвольный target, callbacks токенов с нестандартной логикой и ошибки, возникающие при частичном revert внешнего вызова. В call trace аудитор ищет конкретный путь, который нарушает инвариант до фиксации нового состояния.
Инварианты и композиционность
Сложные протоколы редко падают из-за одной неверной формулы. Ошибка возникает на пересечении депозита, mint, redemption, collateral ratio, liquidation, rewards и rounding. Например, локально корректное округление может позволить многократно извлечь остаток аккаунта или начислить вознаграждение без достаточного объёма залога.
Composability добавляет внешний контур доверия. Если контракт вызывает DEX, lending protocol или oracle, их код может лежать вне scope. Аудит фиксирует границу: проверяется интерфейс, предполагаемое поведение зависимости и обработка неожиданного ответа. Риск последующей эксплуатации чужого контракта остаётся резидуальным.
| Вектор | Артефакт аудита | Что он должен доказать |
|---|---|---|
| Контроль доступа | Матрица ролей и transition diagram | Кто способен изменить состояние, стоимость и цену привилегии |
| Оракул | Карта источников цены | Насколько свежа, защищена и устойчива к отказам цена |
| Флеш-займ | Экономическая трассировка сценария | Достижима ли атака при атомарном капитале |
| Reentrancy | Call trace с callback | Нарушается ли инвариант до обновления state |
| Инварианты | Набор проверяемых свойств | Сохраняются ли платёжеспособность и корректность расчётов |
Критический вектор возникает там, где протокол принимает внешнее значение за доверенное.
Матрица серьёзности дефектов
Оценка строится по трём осям: Impact, Likelihood и Exploitability. Такой подход связывает техническую находку с эксплуатационным риском и не позволяет объявлять Critical любую ошибку, найденную формальным анализатором.
Impact охватывает потерю средств, изменение полномочий, нарушение платёжеспособности, блокировку операций, порчу состояния и другие последствия. Likelihood зависит от достижимости состояния, необходимых полномочий, рыночных условий, доступного капитала и порядка транзакций. Exploitability показывает сложность атаки, число шагов, зависимость от race condition, flash loan или внешнего оракула.
| Градация | Impact | Likelihood и Exploitability | Ожидаемое подтверждение |
|---|---|---|---|
| Critical | Невосстановимая потеря средств, захват контроля, критическое нарушение инварианта | Путь достижим при реалистичных условиях, эксплуатация воспроизводима | Полный PoC, состояние до и после, оценка потерь |
| High | Существенный ущерб с ограниченной областью действия | Условия атаки достижимы, но требуют ресурсов или подготовки | PoC либо детальная трассировка с обоснованием эксплуатации |
| Medium | Ограниченное влияние на отдельные сценарии или пользователей | Эксплуатация зависит от дополнительных условий | Воспроизводимая последовательность действий |
| Low | Незначительное влияние без прямого нарушения безопасности | Сложная или маловероятная эксплуатация | Описание состояния и последствий |
| Informational | Проблема качества, документации или наблюдаемости без прямого security impact | Неприменимо | Рекомендация без привязки к атаке |
| Gas Optimization | Избыточный overhead, потенциальное удорожание или локальная потеря доступности | Зависит от модели использования и нагрузки | Бенчмарк или расчёт overhead |
Gas Optimization следует держать отдельно от эксплуатируемых уязвимостей. Неоптимальный расход газа сам по себе не равен потере средств, хотя плохое распределение газа способно блокировать вызовы.
Finding высокой серьёзности должен содержать предусловия, точные шаги, ожидаемое и фактическое состояние, затронутые функции и рекомендуемое исправление. Если PoC отсутствует, аудитор должен явно объяснить, почему воспроизведение нецелесообразно или невозможно в текущем scope.
Жизненный цикл проверки и приёмка отчёта
Для комплексного аудита контракта среднего масштара типичный таймлайн составляет 2–4 недели. Это ориентир для планирования, а не гарантия срока: количество ролей, внешних интеграций и моделируемых состояний способно изменить трудоёмкость.
1. Scoping. Фиксируются commit, compiler, зависимости, адреса, chain ID, proxy, deploy-конфигурация, права первоначального admin и внешние зависимости. Отдельно оценивается, соответствует ли проверяемый source задеплоенному bytecode.
2. Архитектурная модель. Описываются роли, trust boundaries, state machine, источники цены и критические инварианты. Этот артефакт нужен до запуска сканеров.
3. Автоматический анализ. Slither и MythX обрабатывают исходный код и граф зависимостей. Результаты переводятся в инженерные гипотезы, а не копируются в итоговый отчёт.
4. Ручное ревью. Построчно и по call path проверяются переходы состояния, контроль доступа, порядок вызовов и экономические допущения.
5. Классификация и PoC. Находки ранжируются по Impact, Likelihood и Exploitability. Для критических и высоких рисков подтверждается эксплуатационный путь.
6. Remediation. Разработчик вносит исправления. Аудитор проверяет diff, полноту исправления и отсутствие регрессий.
7. Fix verification. Изменённый commit повторно прогоняется через релевантные тесты и ручные сценарии. Финальный отчёт фиксирует статус каждой находки.
Приёмка результата аудита проводится по артефактам, а не по обещаниям. В пакете должны быть:
- неизменяемый scope с commit hash, версией компилятора и перечнем исключений;
- матрица покрытия SCSVS с обоснованием статуса каждого контроля;
- модель ролей, trust boundaries и проверяемых инвариантов;
- findings со ссылками на строки или участки кода, root cause и серьёзностью;
- PoC либо техническая трассировка для критических и высоких находок;
- описание remediation, diff и результат повторной проверки;
- перечень остаточных рисков, включая composability, внешние oracle и компрометацию административных ключей.
Вердикт. Для production Web3-приложения приемлемая базовая конфигурация аудита сочетает автоматический анализ, ручное ревью, проверку PoC и верификацию исправлений. Один только отчет сканера не покрывает бизнес-логику и композиционные атаки. Для небольшого контракта можно сократить глубину формальной верификации и число моделируемых сценариев, сохранив ручной разбор.
Успешный аудит не гарантирует 100% отсутствие уязвимостей. Его вывод относится к согласованному commit, зафиксированной конфигурации и обозначенной модели угроз. Изменение кода, деплой с другими параметрами, компрометация oracle, изменение рынка или новая уязвимость во внешнем протоколе создают новый контур риска. Поэтому аудит снижает неопределённость на конкретной версии системы; репутация команды и заверения маркетинга эту неопределённость не устраняют.