---
title: "Рекомендації щодо безпеки смарт-контрактів"
description: "Контрольний список рекомендацій щодо безпеки, які слід враховувати під час створення децентралізованого застосунку (dapp)"
author: "Trailofbits"
tags: ["Solidity", "смарт-контракти", "безпека"]
skill: intermediate
breadcrumb: "Рекомендації щодо безпеки"
lang: uk
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) від Слізер).
- **Не використовуйте вбудований асемблер (inline assembly).** Асемблер вимагає глибоких знань 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/), якщо ви зберігаєте ключі в апаратних гаманцях.
- **Майте план реагування на інциденти.** Враховуйте, що ваші смарт-контракти можуть бути скомпрометовані. Навіть якщо ваші контракти не містять помилок, зловмисник може отримати контроль над ключами власника контракту.