Только в образовательных целях; не является инвестиционным советом или инвестиционной рекомендацией. Инвестиции могут привести к убыткам.
Краткий ответ
Аудит смарт-контракта — ограниченная по времени проверка заданных требований, исходного кода, входных данных сборки, логики развертывания и допущений безопасности. Рецензенты сочетают разные методы, чтобы найти дефекты, показать пути эксплуатации, оценить последствия и проверить предложенные исправления. Вывод относится только к снимку проекта и доказательствам, описанным в отчете.
Снимок должен фиксировать репозиторий и commit либо tree hash, submodule и lock-файлы зависимостей, компилятор и настройки, сгенерированный код, скрипты развертывания, целевые сети и адреса, proxy, implementation либо beacon, данные constructor или initializer, библиотеки, администраторов, timelock и блок либо время. Исключения не менее важны: frontend, keeper, oracle, bridge, governance или внесетевой подписант могут определять риск, оставаясь вне аудита.
Для аудита нужны модель угроз и спецификация. Определите активы, участников, привилегированные роли, границы доверия, возможности атакующего, допущения о порядке и реорганизациях, внешние зависимости, переходы состояния и точные свойства безопасности и живучести. Инвариант без единиц, предусловий, кванторов и исключений может безупречно проверять или доказывать неверное поведение.
Ведите четыре реестра: область и идентичность сборки и развертывания; требования, угрозы и инварианты; находки, доказательства и повторные проверки; остаточный риск, его принятие и раскрытие. Отсутствие находки critical не является сертификатом безопасности, статус resolved не означает развертывание исправления, а доказательство покрывает лишь закодированное свойство, модель и допущения.
Как это работает
Ручная проверка прослеживает архитектуру, движение средств, состояние между функциями и экономический замысел. Статический анализ находит шаблоны и потоки данных, но дает ложноположительные и ложноотрицательные результаты. Модульные, интеграционные, fork- и дифференциальные тесты сравнивают конкретное поведение. Stateful fuzz- и invariant-тесты исследуют сгенерированные последовательности, однако результат зависит от handlers, selectors, seeds, corpus, runs, depth и модели окружения.
Символьное исполнение и формальная верификация могут установить выбранные утверждения в поддерживаемой семантике и при заданных допущениях. Результат решателя unknown, timeout или неподдерживаемое поведение не являются доказательством. Даже доказанное свойство может не учитывать экономику oracle, governance, конфигурацию развертывания, поведение сети или фактическое требование команды. За спецификацию и интерпретацию отвечает человек; наблюдение, созданное ИИ, не является отдельным методом обеспечения надежности.
Для каждой находки указывают затронутый артефакт и развертывание, предусловие, минимальное доказательство, путь эксплуатации, достижимость, привилегии, капитал атакующего, повторяемость, экономический эффект, метод оценки серьезности и рекомендацию. Эксплуатируемость или вероятность и влияние — разные измерения. Теоретический максимум, название уязвимости или метка инструмента не доказывают исполнимый убыток.
Статусы open, acknowledged, risk accepted, partially fixed, resolved и retested не стандартизованы. Обоснованное закрытие связывает исходную проблему с точным commit исправления, фиксирует проверенные измененные и соседние пути и сообщает, кто, что и когда повторно проверил. Принятый риск остается риском, а ограниченная повторная проверка не расширяет исходную область на весь новый код.
Обновляемые развертывания требуют отдельной сверки. Определите proxy, implementation либо beacon и admin slots; проверьте initializer и reinitializer, блокировку implementation, совместимость storage, авторизацию upgrade, timelock или аварийный обход, migration и rollback. Воспроизведите creation и runtime bytecode из проверенной сборки, затем сравните связанные библиотеки, параметры, роли и инициализированное состояние в каждой сети.
Итоговый отчет должен называть редакцию, аудиторов и даты, точную область, методы и конфигурации, ограничения, находки, доказательства, статус исправлений, нерешенные или принятые риски и условия раскрытия. После выпуска отслеживайте implementation hashes, роли, параметры, зависимости и инциденты. Любое существенное изменение создает новую дельту для проверки; значок старого отчета не переносится на будущий код.
Используйте такой процесс:
- Зафиксируйте манифест проекта: репозиторий, commit, зависимости, компилятор и настройки, сгенерированный код и код развертывания, сети, адреса, proxy stack, параметры, блок, редакцию отчета, включения и исключения.
- Определите активы, участников, привилегированные роли, границы доверия, возможности атакующего, жизненный цикл, допущения о порядке и живучести, внешние зависимости и измеримые инварианты.
- Воспроизведите сборку и сопоставьте архитектуру, storage, данные, средства и управление; сверьте исходники, артефакты, библиотеки, creation/runtime bytecode, initializer, роли и живое развертывание.
- Примените взаимодополняющие ручные, статические, модульные, интеграционные, fork-, differential-, fuzz-, invariant-, symbolic- или formal-методы, записав версии инструментов, конфигурации, seeds, corpus, coverage, timeout и неопределенные результаты.
- Запишите для каждой проблемы артефакт, предусловие, доказательство, эксплуатируемость, влияние, метод серьезности, подверженность развертывания, рекомендацию и конфиденциальные материалы, не подменяя суждение меткой инструмента.
- Зафиксируйте commit исправления и повторно проверьте проблему, соседние пути и инварианты; проверьте proxy storage, initialization, migration, rollback, воспроизводимую сборку и receipts развертывания, затем присвойте подтвержденный статус.
- Опубликуйте область, методы, ограничения и остаточные риски; сверьте проверенные артефакты со всеми работающими сетями и обновляйте мониторинг, раскрытие, реагирование и bug bounty по мере изменений.
Примеры
- Для инфляционной атаки на vault нужен полный реестр. Атакующий вносит
1 assetчерез ветвь первого депозита и получает1 share, затем передает1,000,000 assets; итог —1,000,001 assetsи1 share. Жертва вносит500,000 assets, а небезопасное округление даетfloor(500,000 * 1 / 1,000,001) = 0 shares. Если депозит с нулем долей принимается, в vault оказывается1,500,001 assets; атакующий погашает их и получает500,000 assetsсверх вклада1,000,001-asset. Если реализация отклоняет нулевой результат, этот путь потерь не исполняется. - Покрытие файлов не равно покрытию развертывания. В манифесте есть
24 source units,4 deployment scriptsи3 keeper services, всего31 items. В область входят20 source unitsи2 scripts, поэтому покрытие по количеству равно22 / 31 = 70.96774194%, а9 itemsисключены. Если живой proxy указывает на implementation из исключенной единицы, покрытие этой реализации равно0%, несмотря на заголовок70.96774194%. - Наблюдения fuzzing не доказывают отсутствие дефекта. Stateful-запуск выполняет
2,000 sequences * 64 calls = 128,000 calls; инвариант нарушен в3 sequences, то есть в наблюдаемых3 / 2,000 = 0.15%сгенерированных последовательностей. После исправления10,000 sequences * 64 calls = 640,000 callsне дают отказов. Это ноль в данном corpus, не доказательство; при учебном допущении независимости и неизменного генератора приблизительная верхняя граница rule of three с95%равна3 / 10,000 = 0.03%на последовательность. - Закрытие находки и идентичность развертывания независимы. В отчете
12 findings:2 critical,3 high,4 mediumи3 low. Повторная проверка закрывает2 + 2 + 3 + 2 = 9, поэтому доля закрытия9 / 12 = 75%; остаются одна high, одна medium и одна low. Проверенный runtime hash —H1, а живая implementation —H2, поэтому сверка развертывания не проходит при любой доле закрытия. Замена на точныйH1и совпадение proxy slot, initializer и ролей доказывают идентичность лишь на проверенном блоке.
Риски
- Репозиторий, commit, submodule или сгенерированный исходник устарел либо неоднозначен.
- Версия компилятора, optimizer settings, библиотеки или зависимости не зафиксированы.
- Скрипты развертывания, constructor data, initializer или CREATE2 salt исключены.
- Проверяется неверная сеть, адрес, proxy, beacon или implementation.
- Исходник, artifact, creation bytecode и runtime bytecode не согласуются.
- Модель угроз пропускает участника, привилегию, актив или границу доверия.
- Спецификация или инвариант содержит неверные единицы, предусловия или исключения.
- Пропущены пути admin, guardian, timelock, pause, upgrade или migration.
- Нарушаются допущения об oracle, token, bridge, keeper, governance или сети.
- Статический анализ дает неразобранный ложноположительный результат.
- Ручная проверка, тестирование или fuzzing пропускает несгенерированный путь.
- Fuzz harness, selector, seed, corpus, depth или модель состояния смещены.
- Timeout решателя, неподдерживаемая семантика или
unknownприняты за доказательство. - Корректное доказательство формализует неверное требование или неполную систему.
- Серьезность выводится из названия уязвимости, а не эксплуатируемости и влияния.
- Теоретическая сумма риска принимается за достижимый убыток или прибыль атакующего.
- Исправление создает соседнюю регрессию или нарушает экономический инвариант.
- Proxy storage, initializer, upgrade или migration повреждает живое состояние.
- Значок аудита скрывает принятую, открытую или частично исправленную проблему.
- Отчет воспринимается как страховка, сертификат, компенсация или бессрочное покрытие.
Распространенные заблуждения
- «Нет критических находок — контракт безопасен». Это описание обнаруженного в ограниченных области, времени и методах, а не всех возможных дефектов.
- «Высокое покрытие тестами или ноль fuzz-сбоев доказывают отсутствие ошибок». Это измерения выбранного кода и сгенерированных путей, а не доказательства отсутствия.
- «Формальная верификация доказывает безопасность всего протокола». Она доказывает закодированные свойства модели при допущениях; спецификация и окружение могут быть неверны.
- «Resolved означает, что исправлены все живые развертывания». Для закрытия нужны независимая повторная проверка и сверка сборки, bytecode, proxy, параметров и ролей каждого развертывания.
- «Авторитетный аудитор гарантирует компенсацию или будущие обновления». Ответственность определяется договором, пользователи могут не быть его бенефициарами, а последующий код и конфигурация не входят в старый снимок.
Связанные темы
Источники
- OWASP Smart Contract Security Verification Standard (SCSVS) - OWASP (дата обращения: 2026-08-13)
- Security Considerations - Solidity (дата обращения: 2026-08-13)
- Slither, the smart contract static analyzer - Crytic (дата обращения: 2026-08-13)
- Invariant Testing - Foundry (дата обращения: 2026-08-13)
- Certora User’s Guide - Certora (дата обращения: 2026-08-13)
- ERC-1967: Proxy Storage Slots - Ethereum Improvement Proposals (дата обращения: 2026-08-13)
- Writing Upgradeable Contracts - OpenZeppelin (дата обращения: 2026-08-13)
- Contract Metadata - Solidity (дата обращения: 2026-08-13)