Перейти к основному содержанию

Рекомендации по обеспечению безопасности смарт-контрактов

Solidity
смарт-контракты
безопасность
Intermediate
Trailofbits
6 сентября 2020 г.
4 минута прочтения

Следуйте этим общим рекомендациям для создания более защищенных смарт-контрактов.

Руководство по дизайну

Разработку контракта следует обсуждать заранее, ещё до написания кода.

Документация и спецификации

Документация может быть написана на разных уровнях и должна обновляться в процессе реализации контрактов:

  • Описание системы на простом английском языке, описывающее, что делают контракты, и любые допущения по кодовой базе.
  • Схемы и архитектурные диаграммы, включая взаимодействия контрактов и конечный автомат системы. Принтеры 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) для проверки иерархии контрактов. Принтер наследования поможет вам проверить размер иерархии.

События

  • Записывайте в журнал все важные операции. События помогут отладить контракт во время разработки и отслеживать его работу после развертывания.

Избегайте известных подводных камней

Зависимости

  • Используйте хорошо протестированные библиотеки. Импорт кода из хорошо протестированных библиотек снизит вероятность написания кода с ошибками. Если вы хотите написать контракт 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 г.

Было ли это руководство полезным?