Рекомендации по обеспечению безопасности смарт-контрактов
Следуйте этим общим рекомендациям для создания более защищенных смарт-контрактов.
Руководство по дизайну
Разработку контракта следует обсуждать заранее, ещё до написания кода.
Документация и спецификации
Документация может быть написана на разных уровнях и должна обновляться в процессе реализации контрактов:
- Описание системы на простом английском языке, описывающее, что делают контракты, и любые допущения по кодовой базе.
- Схемы и архитектурные диаграммы, включая взаимодействия контрактов и конечный автомат системы. Принтеры Slither (opens in a new tab) могут помочь в создании этих схем.
- Подробная документация кода, для Solidity можно использовать формат Natspec (opens in a new tab).
Ончейн- и офчейн-вычисления
- Старайтесь хранить как можно больше кода вне сети (офчейн). Ончейн-уровень должен быть небольшим. Предварительно обрабатывайте данные с помощью кода офчейн таким образом, чтобы ончейн-проверка была простой. Вам нужен упорядоченный список? Сортируйте список офчейн, а затем просто проверяйте его порядок ончейн.
Возможность обновления
Мы обсуждали различные решения для обновления в нашей статье в блоге (opens in a new tab). Примите осознанное решение о поддержке возможности обновления, прежде чем писать какой-либо код. Это решение повлияет на то, как вы структурируете свой код. В целом мы рекомендуем:
- Отдавайте предпочтение миграции контрактов (opens in a new tab) перед возможностью обновления. Системы миграции имеют многие из тех же преимуществ, что и обновляемые, но лишены их недостатков.
- Используйте шаблон разделения данных вместо шаблона delegatecallproxy. Если в вашем проекте есть четкое разделение абстракций, возможность обновления с использованием разделения данных потребует лишь нескольких корректировок. Шаблон delegatecallproxy требует экспертных знаний EVM и очень подвержен ошибкам.
- Документируйте процедуру миграции/обновления перед развертыванием. Если вам придется реагировать в стрессовой ситуации без каких-либо инструкций, вы совершите ошибки. Заранее опишите процедуру, которой нужно следовать. Она должна включать:
- Вызовы, которые инициируют новые контракты
- Где хранятся ключи и как получить к ним доступ
- Как проверить развертывание! Разработайте и протестируйте скрипт для запуска после развертывания.
Руководство по реализации
Стремитесь к простоте. Всегда используйте самое простое решение, которое соответствует вашей цели. Любой член вашей команды должен быть в состоянии понять ваше решение.
Композиция функций
Структура вашей кодовой базы должна облегчать просмотр вашего кода. Избегайте структуры, которая уменьшает возможность рассуждать о ее правильности.
- Разделяйте логику вашей системы либо с помощью нескольких контрактов, либо путем группировки схожих функций (например, аутентификация, арифметика и т. д.).
- Пишите небольшие функции с четкой целью. Это облегчит проверку и позволит тестировать отдельные компоненты.
Наследование
- Сделайте наследование управляемым. Наследование следует использовать для разделения логики, однако в вашем проекте следует стремиться к минимизации глубины и ширины дерева наследования.
- Используйте принтер наследования Slither (opens in a new tab) для проверки иерархии контрактов. Принтер наследования поможет вам проверить размер иерархии.
События
- Записывайте в журнал все важные операции. События помогут отладить контракт во время разработки и отслеживать его работу после развертывания.
Избегайте известных подводных камней
- Помните о наиболее распространенных проблемах безопасности. Существует множество онлайн-ресурсов для изучения распространенных проблем, таких как Ethernaut CTF (opens in a new tab), Capture the Ether (opens in a new tab) или Not so smart contracts (opens in a new tab).
- Обращайте внимание на разделы с предупреждениями в документации Solidity (opens in a new tab). Разделы с предупреждениями сообщат вам о неочевидном поведении языка.
Зависимости
- Используйте хорошо протестированные библиотеки. Импорт кода из хорошо протестированных библиотек снизит вероятность написания кода с ошибками. Если вы хотите написать контракт ERC20, используйте OpenZeppelin (opens in a new tab).
- Используйте менеджер зависимостей; избегайте копирования и вставки кода. Если вы полагаетесь на внешний источник, вы должны поддерживать его в актуальном состоянии в соответствии с оригинальным источником.
Тестирование и верификация
- Пишите подробные модульные тесты. Обширный набор тестов имеет решающее значение для создания высококачественного программного обеспечения.
- Пишите пользовательские проверки и свойства для Slither (opens in a new tab), Echidna (opens in a new tab) и Manticore (opens in a new tab). Автоматизированные инструменты помогут обеспечить безопасность вашего контракта. Ознакомьтесь с остальной частью этого руководства, чтобы узнать, как писать эффективные проверки и свойства.
- Используйте crytic.io (opens in a new tab). Crytic интегрируется с GitHub, предоставляет доступ к частным детекторам Slither и запускает пользовательские проверки свойств от Echidna.
Solidity
- Отдавайте предпочтение Solidity 0.5 перед 0.4 и 0.6. По нашему мнению, Solidity 0.5 является более безопасным и имеет лучшие встроенные практики, чем 0.4. Solidity 0.6 оказался слишком нестабильным для производственного использования и ему нужно время, чтобы «созреть».
- Используйте стабильный релиз для компиляции; используйте последний релиз для проверки предупреждений. Убедитесь, что ваш код не имеет зарегистрированных проблем с последней версией компилятора. Однако у Solidity быстрый цикл релизов и есть история ошибок компилятора, поэтому мы не рекомендуем использовать последнюю версию для развертывания (см. рекомендацию по версии solc от Slither (opens in a new tab)).
- Не используйте встроенный ассемблер. Ассемблер требует экспертных знаний EVM. Не пишите код для EVM, если вы не освоили «желтую книгу».
Руководство по развертыванию
После разработки и развертывания контракта:
- Отслеживайте свои контракты. Следите за журналами и будьте готовы отреагировать в случае компрометации контракта или кошелька.
- Добавьте свою контактную информацию в blockchain-security-contacts (opens in a new tab). Этот список поможет третьим лицам связаться с вами в случае обнаружения уязвимости в системе безопасности.
- Обезопасьте кошельки привилегированных пользователей. Следуйте нашим лучшим практикам (opens in a new tab), если вы храните ключи в аппаратных кошельках.
- Имейте план реагирования на инциденты. Учитывайте, что ваши умные контракты могут быть скомпрометированы. Даже если в ваших контрактах нет ошибок, злоумышленник может завладеть ключами владельца контракта.
Последнее обновление страницы: 30 сентября 2025 г.