К основному содержимому

Введите слово из вопроса или названия статьи.

3 · Под капотом

Каталог уязвимостей смарт-контрактов: 12 классических ошибок и защита от них

Обзор частых уязвимостей контрактов: реентерабельность, контроль доступа, переполнение, оракулы, повтор подписей, DoS. С примерами и защитой в эскроу.

4 мин чтенияОбновлено:
В этой статье

Смарт-контракты - публичные программы, хранящие деньги, и потому за ними охотятся. Хорошая новость: бо́льшая часть взломов повторяет одни и те же схемы. Знание каталога - первый шаг и для разработчика, и для того, кто оценивает контракт (как проверить контракт). Для каждой уязвимости мы покажем суть, пример и защиту.

1. Реентерабельность

Суть. Контракт отправляет деньги внешнему адресу до обновления своего состояния. Получатель в ответ повторно вызывает контракт и «снимает» деньги ещё раз.

История. Взлом The DAO (2016, около 60 млн долларов) разделил сеть Ethereum на две.

Защита. Порядок «проверки - изменение состояния - внешние вызовы», защита nonReentrant, платежи «по запросу» (разбор).

2. Нарушенный контроль доступа

Суть. Критичная функция доступна тем, кому не должна: забыт onlyOwner, открыт инициализатор, tx.origin вместо msg.sender.

Защита. Явные проверки, принцип минимальных прав, мультиподпись для владельца (шаблоны).

3. Арифметика: переполнение и усечение

Суть. До Solidity 0.8 числа «переходили через ноль» без ошибки. В 0.8+ это проверяется, но явное приведение типов (uint96(x)) всё ещё обрезает молча.

Защита. Версия 0.8+, проверка диапазона перед приведением, SafeCast, внимательность в unchecked (целые числа).

4. Невыверенные внешние вызовы

Суть. Низкоуровневый вызов (call) возвращает false при ошибке, но не откатывает транзакцию. Если проигнорировать результат, контракт решит, что платёж прошёл.

Защита. Всегда проверять результат, использовать SafeERC20 для токенов, у которых transfer не возвращает значение (особенности токенов).

5. Манипуляция ценой и оракулами

Суть. Контракт берёт цену из источника, который можно исказить, например из текущего состояния пула. Атакующий с помощью флеш-займа (кредит на одну транзакцию) на мгновение сдвигает цену и забирает прибыль. Это стоило протоколам сотни миллионов долларов.

Защита. Надёжные оракулы, усреднённые цены, проверка свежести данных (проблема оракулов).

6. Фронтраннинг

Суть. Транзакции видны в mempool до включения в блок. Наблюдатель может вставить свою транзакцию перед вашей и заработать на этом.

Защита. Ограничения проскальзывания, схемы commit-reveal, приватные пулы транзакций (MEV).

7. Повтор и подделка подписей

Суть. Подпись, проверенная без nonce, срока и привязки к сети, может быть использована повторно или в другой сети. Подпись также «изменяема» (подписи).

Защита. EIP-712, nonce, deadline, chainId, библиотечная проверка.

8. Ошибки делегирования и прокси

Суть. delegatecall исполняет чужой код с хранилищем вызывающего. Несовпадение раскладок, незащищённый инициализатор или самоуничтожаемая библиотека приводят к катастрофе. В 2017 году из-за ошибки в библиотеке кошельков Parity заблокировали около 150 млн долларов в ETH.

Защита. Проверенные паттерны, защита инициализации, тесты раскладки (прокси).

9. Отказ в обслуживании (DoS)

Суть. Один «плохой» участник блокирует всех. Классика: цикл по списку получателей, где один отклоняет платёж, и вся операция откатывается. Либо неограниченный цикл, на который не хватает газа.

Защита. Модель «забери сам» (pull), ограничение газа на внешние вызовы, отсутствие неограниченных циклов.

В эскроу. Если выплата получателю не прошла (адрес заблокирован эмитентом токена или контракт не принимает ETH), сумма записывается ему как кредит, а сделка закрывается. Один проблемный получатель не блокирует остальных. Вызов получателя ограничен 50 000 газа (разбор).

10. Принудительная отправка эфира

Суть. Любой может отправить ETH контракту, даже если у него нет приёма (через selfdestruct или как получатель награды за блок). Если логика опирается на address(this).balance, её можно сломать.

Защита. Вести собственный учёт, а не полагаться на баланс. В эскроу учёт ведётся через reserved, а лишние поступления попадают в категорию «неучтённых» и не влияют на сделки.

11. Зависимость от времени и случайности

Суть. block.timestamp может отклоняться на секунды, а «случайные» значения из блока (хеши, время) предсказуемы и манипулируемы валидатором.

Защита. Не использовать время для ответственных проверок с малым допуском; случайность - только из надёжных источников.

В эскроу. Сроки измеряются сутками и более, секундная погрешность ни на что не влияет.

12. Ложные предположения о токенах

Суть. Контракт считает, что токен ведёт себя как эталонный ERC-20, а он берёт комиссию, меняет балансы, блокирует адреса или имеет ошибку.

Защита. Белый список токенов, сверка фактически полученной суммы с заявленной (токены). Эскроу принимает только разрешённые токены и отклоняет несоответствие сумм (AmountMismatch).

Бонус: данные «приватных» переменных читаемы

Любой слот хранилища публичен, даже у private переменной (раскладка хранилища). Секреты в контракте хранить нельзя.

Как эскроу применяет защиту: сводка

УгрозаМера
РеентерабельностьnonReentrant, состояние обновляется до выплат
Контроль доступапроверки сторон сделки, Ownable2Step, пауза только новых сделок
Усечение числаявная проверка AmountTooLarge
DoS через получателякредиты и ограничение газа
Принудительная отправкаучёт reserved вместо баланса
Нестандартные токеныбелый список, проверка полученной суммы

Не вся безопасность - в коде

Уязвимости бывают и вне контракта: взломанные ключи, подмена интерфейса, ошибочные подписи людей. Крупнейший взлом 2025 года (биржа Bybit, около 1,5 млрд долларов) начался с компрометации интерфейса, который показывал подписантам мультиподписи не те данные. Поэтому важны и личные правила, и аудит.

Что почитать дальше

Узнайте, как проверяют контракты перед запуском: аудиты и баг-баунти. Или как их защищают тестами: тестирование смарт-контрактов.

Упоминается в статьях

Готовы попробовать?

Создайте первую сделку за пару минут. Деньги блокируются в смарт-контракте и выплачиваются по правилам, которые видны заранее.