---
title: "Руководство по безопасности смарт-контрактов"
description: "Контрольный список рекомендаций по безопасности, которые следует учитывать при создании вашего dapp"
author: "Trailofbits"
tags:
  - solidity
  - смарт-контракты
  - безопасность
skill: intermediate
breadcrumb: "Руководство по безопасности"
lang: ru
published: 2020-09-06
source: Building secure contracts
sourceUrl: https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/guidelines.md
---

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

## Рекомендации по проектированию {#design-guidelines}

Проектирование контракта следует обсудить заранее, до написания хотя бы одной строчки кода.

### Документация и спецификации {#documentation-and-specifications}

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

- **Описание системы простым языком**, объясняющее, что делают контракты, и любые допущения относительно кодовой базы.
- **Схемы и архитектурные диаграммы**, включая взаимодействия контрактов и машину состояний системы. [Принтеры Слизер](https://github.com/crytic/slither/wiki/Printer-documentation) могут помочь в генерации этих схем.
- **Тщательная документация кода**, для Solidity можно использовать [формат NatSpec](https://docs.soliditylang.org/en/develop/natspec-format.html).

### Вычисления ончейн и офчейн {#onchain-vs-offchain-computation}

- **Держите как можно больше кода офчейн.** Оставляйте ончейн-слой небольшим. Предварительно обрабатывайте данные с помощью кода офчейн таким образом, чтобы проверка ончейн была простой. Вам нужен упорядоченный список? Отсортируйте список офчейн, а затем только проверьте его порядок ончейн.

### Возможность обновления {#upgradeability}

Мы обсуждали различные решения для обновления в [нашем блоге](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/). Сделайте осознанный выбор в пользу поддержки возможности обновления или отказа от нее до написания какого-либо кода. Это решение повлияет на то, как вы структурируете свой код. В целом, мы рекомендуем:

- **Отдавать предпочтение [миграции контрактов](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/), а не возможности обновления.** Системы миграции имеют много тех же преимуществ, что и обновляемые, но без их недостатков.
- **Использовать паттерн разделения данных вместо паттерна delegatecallproxy.** Если в вашем проекте есть четкое разделение абстракций, возможность обновления с использованием разделения данных потребует лишь нескольких корректировок. Использование delegatecallproxy требует глубоких знаний EVM и сопряжено с высоким риском ошибок.
- **Документировать процедуру миграции/обновления до развертывания.** Если вам придется реагировать в стрессовой ситуации без каких-либо инструкций, вы наделаете ошибок. Заранее напишите процедуру, которой следует придерживаться. Она должна включать:
  - Вызовы, которые инициируют новые контракты
  - Где хранятся ключи и как получить к ним доступ
  - Как проверить развертывание! Разработайте и протестируйте скрипт, выполняемый после развертывания.

## Рекомендации по реализации {#implementation-guidelines}

**Стремитесь к простоте.** Всегда используйте самое простое решение, которое соответствует вашей цели. Любой член вашей команды должен быть в состоянии понять ваше решение.

### Композиция функций {#function-composition}

Архитектура вашей кодовой базы должна облегчать проверку кода. Избегайте архитектурных решений, которые снижают возможность рассуждать о его правильности.

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

### Наследование {#inheritance}

- **Сохраняйте наследование управляемым.** Наследование следует использовать для разделения логики, однако ваш проект должен стремиться к минимизации глубины и ширины дерева наследования.
- **Используйте [принтер наследования](https://github.com/crytic/slither/wiki/Printer-documentation#inheritance-graph) Слизер для проверки иерархии контрактов.** Принтер наследования поможет вам оценить размер иерархии.

### События {#events}

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

### Избегайте известных подводных камней {#avoid-known-pitfalls}

- **Знайте о наиболее распространенных проблемах безопасности.** Существует множество онлайн-ресурсов для изучения распространенных проблем, таких как [Ethernaut CTF](https://ethernaut.openzeppelin.com/), [Capture the Ether](https://capturetheether.com/) или [Not so smart contracts](https://github.com/crytic/not-so-smart-contracts/).
- **Обращайте внимание на разделы с предупреждениями в [документации Solidity](https://docs.soliditylang.org/en/latest/).** Разделы с предупреждениями проинформируют вас о неочевидном поведении языка.

### Зависимости {#dependencies}

- **Используйте хорошо протестированные библиотеки.** Импорт кода из хорошо протестированных библиотек снизит вероятность написания кода с ошибками. Если вы хотите написать контракт ERC-20, используйте [ОпенЗеппелин](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20).
- **Используйте менеджер зависимостей; избегайте копирования и вставки кода.** Если вы полагаетесь на внешний источник, вы должны поддерживать его в актуальном состоянии в соответствии с оригиналом.

### Тестирование и верификация {#testing-and-verification}

- **Пишите тщательные модульные тесты.** Обширный набор тестов имеет решающее значение для создания высококачественного программного обеспечения.
- **Пишите пользовательские проверки и свойства для [Слизер](https://github.com/crytic/slither), [Эхидна](https://github.com/crytic/echidna) и [Мантикора](https://github.com/trailofbits/manticore).** Автоматизированные инструменты помогут убедиться в безопасности вашего контракта. Ознакомьтесь с остальной частью этого руководства, чтобы узнать, как писать эффективные проверки и свойства.
- **Используйте [crytic.io](https://crytic.io/).** Crytic интегрируется с GitHub, предоставляет доступ к приватным детекторам Слизер и запускает пользовательские проверки свойств от Эхидна.

### Solidity {#solidity}

- **Отдавайте предпочтение Solidity 0.5 вместо 0.4 и 0.6.** По нашему мнению, Solidity 0.5 более безопасен и имеет лучшие встроенные практики, чем 0.4. Версия Solidity 0.6 оказалась слишком нестабильной для продакшена и требует времени для доработки.
- **Используйте стабильный релиз для компиляции; используйте последний релиз для проверки предупреждений.** Убедитесь, что в вашем коде нет проблем, о которых сообщает последняя версия компилятора. Однако Solidity имеет быстрый цикл выпуска и историю ошибок компилятора, поэтому мы не рекомендуем использовать последнюю версию для развертывания (см. [рекомендации по версии solc](https://github.com/crytic/slither/wiki/Detector-Documentation#recommendation-33) от Слизер).
- **Не используйте встроенный ассемблер.** Ассемблер требует глубоких знаний EVM. Не пишите код для EVM, если вы не _освоили_ желтую книгу.

## Рекомендации по развертыванию {#deployment-guidelines}

После того как контракт был разработан и развернут:

- **Мониторьте свои контракты.** Следите за логами и будьте готовы отреагировать в случае компрометации контракта или кошелька.
- **Добавьте свою контактную информацию в [blockchain-security-contacts](https://github.com/crytic/blockchain-security-contacts).** Этот список помогает третьим лицам связаться с вами в случае обнаружения уязвимости в системе безопасности.
- **Обеспечьте безопасность кошельков привилегированных пользователей.** Следуйте нашим [лучшим практикам](https://blog.trailofbits.com/2018/11/27/10-rules-for-the-secure-use-of-cryptocurrency-hardware-wallets/), если вы храните ключи в аппаратных кошельках.
- **Имейте план реагирования на инциденты.** Учитывайте, что ваши смарт-контракты могут быть скомпрометированы. Даже если в ваших контрактах нет ошибок, злоумышленник может завладеть ключами владельца контракта.