From b4bd81e1d54815682e645ff4b6709beeadb33b77 Mon Sep 17 00:00:00 2001 From: Joshua <62268199+minimalsm@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:00:06 +0000 Subject: [PATCH] i18n(ru): translation import part 06 of 13 (23 files) --- .../docs/smart-contracts/anatomy/index.md | 657 ++++++++++++++++++ .../docs/smart-contracts/compiling/index.md | 282 ++++++++ .../smart-contracts/composability/index.md | 76 ++ .../docs/smart-contracts/deploying/index.md | 81 +++ .../formal-verification/index.md | 284 ++++++++ .../developers/docs/smart-contracts/index.md | 112 +++ .../docs/smart-contracts/languages/index.md | 342 +++++++++ .../docs/smart-contracts/libraries/index.md | 117 ++++ .../docs/smart-contracts/naming/index.md | 101 +++ .../docs/smart-contracts/security/index.md | 576 +++++++++++++++ .../docs/smart-contracts/testing/index.md | 310 +++++++++ .../docs/smart-contracts/upgrading/index.md | 165 +++++ .../docs/smart-contracts/verifying/index.md | 113 +++ .../ru/developers/docs/standards/index.md | 59 ++ .../docs/standards/tokens/erc-1155/index.md | 146 ++++ .../docs/standards/tokens/erc-1363/index.md | 213 ++++++ .../docs/standards/tokens/erc-20/index.md | 186 +++++ .../docs/standards/tokens/erc-223/index.md | 198 ++++++ .../docs/standards/tokens/erc-4626/index.md | 227 ++++++ .../docs/standards/tokens/erc-721/index.md | 255 +++++++ .../docs/standards/tokens/erc-777/index.md | 45 ++ .../developers/docs/standards/tokens/index.md | 41 ++ .../ru/developers/docs/storage/index.md | 216 ++++++ 23 files changed, 4802 insertions(+) create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/anatomy/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/compiling/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/composability/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/deploying/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/formal-verification/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/languages/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/libraries/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/naming/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/security/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/testing/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/upgrading/index.md create mode 100644 public/content/translations/ru/developers/docs/smart-contracts/verifying/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/erc-1155/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/erc-1363/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/erc-20/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/erc-223/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/erc-4626/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/erc-721/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/erc-777/index.md create mode 100644 public/content/translations/ru/developers/docs/standards/tokens/index.md create mode 100644 public/content/translations/ru/developers/docs/storage/index.md diff --git a/public/content/translations/ru/developers/docs/smart-contracts/anatomy/index.md b/public/content/translations/ru/developers/docs/smart-contracts/anatomy/index.md new file mode 100644 index 00000000000..a72f4d07126 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/anatomy/index.md @@ -0,0 +1,657 @@ +--- +title: "Подробнее о смарт-контрактах" +description: "Подробный обзор анатомии смарт-контракта – функции, данные и переменные." +lang: ru +--- + +Смарт-контракт - это программа, которая запускается на определенном адресе на Ethereum. Они состоят из данных и функций, которые могут выполняться при получении транзакции. Вот обзор того, что представляет из себя смарт-контракт. + +## Предварительные условия {#prerequisites} + +Сначала убедитесь, что вы прочитали о [смарт-контрактах](/developers/docs/smart-contracts/). Эта статья предполагает, что вы уже знакомы с языками программирования, такими как JavaScript или Python. + +## Данные {#data} + +Любые данные контракта должны быть присвоены местоположению: либо `storage`, либо `memory`. Модифицировать хранилище в смарт контракте - дорогостоящая операция, поэтому вам необходимо подумать заранее, где ваши данные должны храниться. + +### Хранилища {#storage} + +Постоянные данные называются хранилищем и представлены переменными состояния. Эти значения постоянно хранятся в блокчейне. Вам необходимо объявить тип, чтобы контракт мог отслеживать, сколько пространства в блокчейне ему потребуется при компиляции. + +```solidity +// Пример Solidity +contract SimpleStorage { + uint storedData; // Переменная состояния + // ... +} +``` + +```python +Пример на Vyper +``` + +Если вы уже программировали объектно-ориентированные языки, то вы, скорее всего, будете знакомы с большинством типов. Однако, `address` может быть для вас в новинку, если вы новичок в разработке на Ethereum. + +Тип `address` может содержать адрес Ethereum, который равен 20 байтам или 160 битам. Он возвращается в шестнадцатеричной нотации с лидирующим значением 0x. + +Другие типы включают: + +- логический +- целое число +- числа с фиксированной точкой +- байтовые массивы фиксированного размера +- массивы байтов динамического размера +- рациональные и целочисленные литералы +- строковые литералы +- шестнадцатеричные литералы +- перечисления + +Для более подробного объяснения, ознакомьтесь с документацией: + +- [Смотрите типы Vyper](https://docs.vyperlang.org/en/v0.1.0-beta.6/types.html#value-types) +- [Смотрите типы Solidity](https://docs.soliditylang.org/en/latest/types.html#value-types) + +### Память {#memory} + +Значения, которые хранятся только на время выполнения контрактной функции, называются переменными памяти. Поскольку они не хранятся постоянно в блокчейне, их использование намного дешевле. + +Узнайте больше о том, как EVM хранит данные (хранилище, память и стек) в [документации Solidity](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#storage-memory-and-the-stack). + +### Переменные среды {#environment-variables} + +В дополнение к переменным, которые вы определяете по вашему контракту, есть некоторые специальные глобальные переменные. Они в основном используются для предоставления информации о блокчейне или текущей транзакции. + +Примеры: + +| **Свойство** | **Переменная состояния** | **Описание** | +| ----------------- | ------------------------ | -------------------------------------------------------- | +| `block.timestamp` | uint256 | Текущая метка времени начала блоков | +| `msg.sender` | адрес | Отправитель сообщения (текущий вызов) | + +## Функции {#functions} + +В наиболее упрощенных терминах функции могут получать информацию или устанавливать информацию в ответ на входящие транзакции. + +Существует два типа вызовов функций: + +- `internal` – не создают вызов EVM + - К внутренним функциям и переменным состояния можно получить доступ только изнутри (т. е. из текущего контракта или контрактов, производных от него) +- `external` – создают вызов EVM + - Внешние функции являются частью контрактного интерфейса, что означает, что они могут быть вызваны из других контрактов и через сделки. Внешняя функция `f` не может быть вызвана внутренне (т. е. `f()` не работает, но `this.f()` работает). + +Они также могут быть `public` или `private` + +- Функции `public` можно вызывать внутренне из контракта или внешне с помощью сообщений +- Функции `private` видны только для контракта, в котором они определены, и не видны в производных контрактах + +Функции и переменные состояний могут быть общедоступными или частными + +Вот функция обновления переменной состояния по контракту: + +```solidity +// Пример солидарности +function update_name(string value) public { + dapp_name = value; +} +``` + +- Параметр `value` типа `string` передается в функцию: `update_name` +- Она объявлена как `public`, что означает, что любой может получить к ней доступ +- Она не объявлена как `view`, поэтому может изменять состояние контракта + +### Функции просмотра {#view-functions} + +Эти функции обещают не изменять состояние данных контракта. Типичными примерами являются функции "получения" - вы можете использовать их, например, для получения баланса пользователя. + +```solidity +// Пример твердости +функция balanceOf (address _owner) в публичном представлении возвращает (uint256 _balance) { + вернуть ownerPizzaCount [_owner]; +} +``` + +```python +dappName: public(string) + +@view +@public +def readName() -> string: + return dappName +``` + +Что считается измененным состоянием: + +1. Запись переменных состояний. +2. [Генерирование событий](https://docs.soliditylang.org/en/v0.7.0/contracts.html#events). +3. [Создание других контрактов](https://docs.soliditylang.org/en/v0.7.0/control-structures.html#creating-contracts). +4. Использование `selfdestruct`. +5. Отправка эфира через вызовы. +6. Вызов любой функции, не отмеченной как `view` или `pure`. +7. Использование низкоуровневых вызовов. +8. Используя встроенную сборку, которая содержит некоторые опкоды. + +### Функции конструктора {#constructor-functions} + +Функции `constructor` выполняются только один раз при первом развертывании контракта. Подобно `constructor` во многих объектно-ориентированных языках программирования, эти функции часто инициализируют переменные состояния их заданными значениями. + +```solidity +// Пример на Solidity +// Инициализирует данные контракта, устанавливая `owner` +// в качестве адреса создателя контракта. +constructor() public { + // Все смарт-контракты полагаются на внешние транзакции для запуска своих функций. + // `msg` — это глобальная переменная, которая содержит актуальные данные о данной транзакции, + // такие как адрес отправителя и значение ETH, включенное в транзакцию. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties + owner = msg.sender; +} +``` + +```python +# Vyper example + +@external +def __init__(_beneficiary: address, _bidding_time: uint256): + self.beneficiary = _beneficiary + self.auctionStart = block.timestamp + self.auctionEnd = self.auctionStart + _bidding_time +``` + +### Встроенные функции {#built-in-functions} + +В дополнение к переменным и функциям, которые вы определяете в своем контракте, есть несколько специальных встроенных функций. Самый очевидный пример: + +- `address.send()` – Solidity +- `send(address)` – Vyper + +Это позволяет контрактам отправлять ETH на другие учетные записи. + +## Написание функций {#writing-functions} + +Ваша функция требует: + +- переменная параметра и тип (если он принимает параметры) +- декларация внутреннего / внешнего +- декларация о чистом / просмотре / к оплате +- возвращает тип (если возвращает значение) + +```solidity +pragma solidity >=0.4.0 <=0.6.0; + +contract ExampleDapp { + string dapp_name; // переменная состояния + + // Вызывается при развертывании контракта и инициализирует значение + constructor() public { + dapp_name = "My Example dapp"; + } + + // Функция получения + function read_name() public view returns(string) { + return dapp_name; + } + + // Функция установки + function update_name(string value) public { + dapp_name = value; + } +} +``` + +Полный контракт может выглядеть примерно так. Здесь функция `constructor` задает начальное значение для переменной `dapp_name`. + +## События и журналы {#events-and-logs} + +События позволяют вашему смарт-контракту взаимодействовать с вашим внешним интерфейсом или другими подписанными приложениями. После того, как транзакция проверена и добавлена в блок, смарт-контракты могут генерировать события и регистрировать информацию, которую внешний интерфейс затем может обрабатывать и использовать. + +## Примеры с комментариями {#annotated-examples} + +Это несколько примеров, написанных на Solidity. Если вы хотите поэкспериментировать с кодом, вы можете взаимодействовать с ним в [Remix](http://remix.ethereum.org). + +### Hello world {#hello-world} + +```solidity +// Указывает версию Solidity, используя семантическое версионирование. +// Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity ^0.5.10; + +// Определяет контракт с именем `HelloWorld`. +// Контракт — это набор функций и данных (его состояние). +// После развертывания контракт находится по определенному адресу в блокчейне Ethereum. +// Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + // Объявляет переменную состояния `message` типа `string`. + // Переменные состояния — это переменные, значения которых постоянно хранятся в хранилище контракта. + // Ключевое слово `public` делает переменные доступными извне контракта + // и создает функцию, которую могут вызывать другие контракты или клиенты для доступа к значению. + string public message; + + // Подобно многим объектно-ориентированным языкам, конструктор — это + // специальная функция, которая выполняется только при создании контракта. + // Конструкторы используются для инициализации данных контракта. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) public { + // Принимает строковый аргумент `initMessage` и устанавливает его значение + // в переменную хранилища контракта `message`). + message = initMessage; + } + + // Публичная функция, которая принимает строковый аргумент + // и обновляет переменную хранилища `message`. + function update(string memory newMessage) public { + message = newMessage; + } +} +``` + +### Токен {#token} + +```solidity +pragma solidity ^0.5.10; + +contract Token { + // `address` можно сравнить с адресом электронной почты — он используется для идентификации аккаунта в Ethereum. + // Адреса могут представлять смарт-контракт или внешние (пользовательские) аккаунты. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/types.html#address + address public owner; + + // `mapping` — это, по сути, структура данных хеш-таблицы. + // Этот `mapping` присваивает беззнаковое целое число (баланс токенов) адресу (владельцу токенов). + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/types.html#mapping-types + mapping (address => uint) public balances; + + // События позволяют регистрировать активность в блокчейне. + // Клиенты Ethereum могут прослушивать события, чтобы реагировать на изменения состояния контракта. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#events + event Transfer(address from, address to, uint amount); + + // Инициализирует данные контракта, устанавливая `owner` + // в качестве адреса создателя контракта. + constructor() public { + // Все смарт-контракты полагаются на внешние транзакции для запуска своих функций. + // `msg` — это глобальная переменная, которая содержит актуальные данные о данной транзакции, + // такие как адрес отправителя и значение ETH, включенное в транзакцию. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/units-and-global-variables.html#block-and-transaction-properties + owner = msg.sender; + } + + // Создает определенное количество новых токенов и отправляет их на адрес. + function mint(address receiver, uint amount) public { + // `require` — это управляющая структура, используемая для обеспечения выполнения определенных условий. + // Если выражение `require` оценивается как `false`, вызывается исключение, + // которое отменяет все изменения, внесенные в состояние во время текущего вызова. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions + + // Только владелец контракта может вызывать эту функцию + require(msg.sender == owner, "You are not the owner."); + + // Применяет максимальное количество токенов + require(amount < 1e60, "Maximum issuance exceeded"); + + // Увеличивает баланс `receiver` на `amount` + balances[receiver] += amount; + } + + // Отправляет определенное количество существующих токенов от любого вызывающего на адрес. + function transfer(address receiver, uint amount) public { + // У отправителя должно быть достаточно токенов для отправки + require(amount <= balances[msg.sender], "Insufficient balance."); + + // Корректирует балансы токенов двух адресов + balances[msg.sender] -= amount; + balances[receiver] += amount; + + // Генерирует событие, определенное ранее + emit Transfer(msg.sender, receiver, amount); + } +} +``` + +### Уникальный цифровой актив {#unique-digital-asset} + +```solidity +pragma solidity ^0.5.10; + +// Импортирует символы из других файлов в текущий контракт. +// В данном случае — серия вспомогательных контрактов из OpenZeppelin. +// Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#importing-other-source-files + +import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "../node_modules/@openzeppelin/contracts/introspection/ERC165.sol"; +import "../node_modules/@openzeppelin/contracts/math/SafeMath.sol"; + +// Ключевое слово `is` используется для наследования функций и ключевых слов из внешних контрактов. +// В этом случае `CryptoPizza` наследует от контрактов `IERC721` и `ERC165`. +// Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#inheritance +contract CryptoPizza is IERC721, ERC165 { + // Использует библиотеку SafeMath из OpenZeppelin для безопасного выполнения арифметических операций. + // Узнать больше: https://docs.openzeppelin.com/contracts/2.x/api/math#SafeMath + using SafeMath for uint256; + + // Константные переменные состояния в Solidity похожи на другие языки, + // но вы должны присваивать их из выражения, которое является константой во время компиляции. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constant-state-variables + uint256 constant dnaDigits = 10; + uint256 constant dnaModulus = 10 ** dnaDigits; + bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; + + // Типы Struct позволяют определять собственный тип + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/types.html#structs + struct Pizza { + string name; + uint256 dna; + } + + // Создает пустой массив структур Pizza + Pizza[] public pizzas; + + // Сопоставление идентификатора пиццы с адресом ее владельца + mapping(uint256 => address) public pizzaToOwner; + + // Сопоставление адреса владельца с количеством принадлежащих ему токенов + mapping(address => uint256) public ownerPizzaCount; + + // Сопоставление идентификатора токена с одобренным адресом + mapping(uint256 => address) pizzaApprovals; + + // Вы можете вкладывать сопоставления, этот пример сопоставляет владельца с одобрениями оператора + mapping(address => mapping(address => bool)) private operatorApprovals; + + // Внутренняя функция для создания случайной пиццы из строки (имени) и ДНК + function _createPizza(string memory _name, uint256 _dna) + // Ключевое слово `internal` означает, что эта функция видна только + // в этом контракте и в контрактах, которые его наследуют + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#visibility-and-getters + internal + // `isUnique` — это модификатор функции, который проверяет, существует ли пицца + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html#function-modifiers + isUnique(_name, _dna) + { + // Добавляет пиццу в массив пицц и получает идентификатор + uint256 id = SafeMath.sub(pizzas.push(Pizza(_name, _dna)), 1); + + // Проверяет, что владелец пиццы совпадает с текущим пользователем + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/control-structures.html#error-handling-assert-require-revert-and-exceptions + + // обратите внимание, что address(0) — это нулевой адрес, + // указывающий, что pizza[id] еще не назначена конкретному пользователю. + + assert(pizzaToOwner[id] == address(0)); + + // Сопоставляет пиццу с владельцем + pizzaToOwner[id] = msg.sender; + ownerPizzaCount[msg.sender] = SafeMath.add( + ownerPizzaCount[msg.sender], + 1 + ); + } + + // Создает случайную пиццу из строки (имени) + function createRandomPizza(string memory _name) public { + uint256 randDna = generateRandomDna(_name, msg.sender); + _createPizza(_name, randDna); + } + + // Генерирует случайную ДНК из строки (имени) и адреса владельца (создателя) + function generateRandomDna(string memory _str, address _owner) + public + // Функции, помеченные как `pure`, обещают не читать и не изменять состояние + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#pure-functions + pure + returns (uint256) + { + // Генерирует случайный uint из строки (имени) + адреса (владельца) + uint256 rand = uint256(keccak256(abi.encodePacked(_str))) + + uint256(_owner); + rand = rand % dnaModulus; + return rand; + } + + // Возвращает массив пицц, найденных по владельцу + function getPizzasByOwner(address _owner) + public + // Функции, помеченные как `view`, обещают не изменять состояние + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/contracts.html#view-functions + view + returns (uint256[] memory) + { + // Использует местоположение в хранилище `memory` для хранения значений только на время + // жизненного цикла этого вызова функции. + // Узнать больше: https://solidity.readthedocs.io/en/v0.5.10/introduction-to-smart-contracts.html#storage-memory-and-the-stack + uint256[] memory result = new uint256[](ownerPizzaCount[_owner]); + uint256 counter = 0; + for (uint256 i = 0; i < pizzas.length; i++) { + if (pizzaToOwner[i] == _owner) { + result[counter] = i; + counter++; + } + } + return result; + } + + // Передает пиццу и право собственности на другой адрес + function transferFrom(address _from, address _to, uint256 _pizzaId) public { + require(_from != address(0) && _to != address(0), "Invalid address."); + require(_exists(_pizzaId), "Pizza does not exist."); + require(_from != _to, "Cannot transfer to the same address."); + require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved."); + + ownerPizzaCount[_to] = SafeMath.add(ownerPizzaCount[_to], 1); + ownerPizzaCount[_from] = SafeMath.sub(ownerPizzaCount[_from], 1); + pizzaToOwner[_pizzaId] = _to; + + // Генерирует событие, определенное в импортированном контракте IERC721 + emit Transfer(_from, _to, _pizzaId); + _clearApproval(_to, _pizzaId); + } + + /** + * Безопасно передает право собственности на данный идентификатор токена другому адресу + * Если целевой адрес является контрактом, он должен реализовывать `onERC721Received`, + * который вызывается при безопасной передаче и возвращает магическое значение + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; + * в противном случае передача отменяется. + */ + function safeTransferFrom(address from, address to, uint256 pizzaId) + public + { + // solium-disable-next-line arg-overflow + this.safeTransferFrom(from, to, pizzaId, ""); + } + + /** + * Безопасно передает право собственности на данный идентификатор токена другому адресу + * Если целевой адрес является контрактом, он должен реализовывать `onERC721Received`, + * который вызывается при безопасной передаче и возвращает магическое значение + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; + * в противном случае передача отменяется. + */ + function safeTransferFrom( + address from, + address to, + uint256 pizzaId, + bytes memory _data + ) public { + this.transferFrom(from, to, pizzaId); + require(_checkOnERC721Received(from, to, pizzaId, _data), "Must implement onERC721Received."); + } + + /** + * Внутренняя функция для вызова `onERC721Received` на целевом адресе + * Вызов не выполняется, если целевой адрес не является контрактом + */ + function _checkOnERC721Received( + address from, + address to, + uint256 pizzaId, + bytes memory _data + ) internal returns (bool) { + if (!isContract(to)) { + return true; + } + + bytes4 retval = IERC721Receiver(to).onERC721Received( + msg.sender, + from, + pizzaId, + _data + ); + return (retval == _ERC721_RECEIVED); + } + + // Сжигает пиццу — полностью уничтожает токен + // Модификатор функции `external` означает, что эта функция + // является частью интерфейса контракта, и другие контракты могут ее вызывать + function burn(uint256 _pizzaId) external { + require(msg.sender != address(0), "Invalid address."); + require(_exists(_pizzaId), "Pizza does not exist."); + require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved."); + + ownerPizzaCount[msg.sender] = SafeMath.sub( + ownerPizzaCount[msg.sender], + 1 + ); + pizzaToOwner[_pizzaId] = address(0); + } + + // Возвращает количество пицц по адресу + function balanceOf(address _owner) public view returns (uint256 _balance) { + return ownerPizzaCount[_owner]; + } + + // Возвращает владельца пиццы по идентификатору + function ownerOf(uint256 _pizzaId) public view returns (address _owner) { + address owner = pizzaToOwner[_pizzaId]; + require(owner != address(0), "Invalid Pizza ID."); + return owner; + } + + // Одобряет другой адрес для передачи права собственности на пиццу + function approve(address _to, uint256 _pizzaId) public { + require(msg.sender == pizzaToOwner[_pizzaId], "Must be the Pizza owner."); + pizzaApprovals[_pizzaId] = _to; + emit Approval(msg.sender, _to, _pizzaId); + } + + // Возвращает одобренный адрес для конкретной пиццы + function getApproved(uint256 _pizzaId) + public + view + returns (address operator) + { + require(_exists(_pizzaId), "Pizza does not exist."); + return pizzaApprovals[_pizzaId]; + } + + /** + * Приватная функция для отмены текущего одобрения для данного идентификатора токена + * Отменяется, если данный адрес действительно не является владельцем токена + */ + function _clearApproval(address owner, uint256 _pizzaId) private { + require(pizzaToOwner[_pizzaId] == owner, "Must be pizza owner."); + require(_exists(_pizzaId), "Pizza does not exist."); + if (pizzaApprovals[_pizzaId] != address(0)) { + pizzaApprovals[_pizzaId] = address(0); + } + } + + /* + * Устанавливает или отменяет одобрение для данного оператора + * Оператору разрешено передавать все токены отправителя от его имени + */ + function setApprovalForAll(address to, bool approved) public { + require(to != msg.sender, "Cannot approve own address"); + operatorApprovals[msg.sender][to] = approved; + emit ApprovalForAll(msg.sender, to, approved); + } + + // Сообщает, одобрен ли оператор данным владельцем + function isApprovedForAll(address owner, address operator) + public + view + returns (bool) + { + return operatorApprovals[owner][operator]; + } + + // Принимает право собственности на пиццу — только для одобренных пользователей + function takeOwnership(uint256 _pizzaId) public { + require(_isApprovedOrOwner(msg.sender, _pizzaId), "Address is not approved."); + address owner = this.ownerOf(_pizzaId); + this.transferFrom(owner, msg.sender, _pizzaId); + } + + // Проверяет, существует ли пицца + function _exists(uint256 pizzaId) internal view returns (bool) { + address owner = pizzaToOwner[pizzaId]; + return owner != address(0); + } + + // Проверяет, является ли адрес владельцем или ему разрешена передача пиццы + function _isApprovedOrOwner(address spender, uint256 pizzaId) + internal + view + returns (bool) + { + address owner = pizzaToOwner[pizzaId]; + // Отключить проверку solium из-за + // https://github.com/duaraghav8/Solium/issues/175 + // solium-disable-next-line operator-whitespace + return (spender == owner || + this.getApproved(pizzaId) == spender || + this.isApprovedForAll(owner, spender)); + } + + // Проверить, является ли пицца уникальной и еще не существует + modifier isUnique(string memory _name, uint256 _dna) { + bool result = true; + for (uint256 i = 0; i < pizzas.length; i++) { + if ( + keccak256(abi.encodePacked(pizzas[i].name)) == + keccak256(abi.encodePacked(_name)) && + pizzas[i].dna == _dna + ) { + result = false; + } + } + require(result, "Pizza with such name already exists."); + _; + } + + // Возвращает, является ли целевой адрес контрактом + function isContract(address account) internal view returns (bool) { + uint256 size; + // В настоящее время нет лучшего способа проверить, есть ли контракт по адресу, + // чем проверить размер кода по этому адресу. + // См. https://ethereum.stackexchange.com/a/14016/36603 + // для получения более подробной информации о том, как это работает. + // TODO Проверить это снова перед выпуском Serenity, потому что тогда все адреса будут + // контрактами. + // solium-disable-next-line security/no-inline-assembly + assembly { + size := extcodesize(account) + } + return size > 0; + } +} +``` + +## Дополнительные материалы {#further-reading} + +Ознакомьтесь с документацией Solidity и Vyper для более полного обзора смарт-контрактов: + +- [Solidity](https://docs.soliditylang.org/) +- [Vyper](https://docs.vyperlang.org/en/stable/) + +## Смежные темы {#related-topics} + +- [Умные контракты](/developers/docs/smart-contracts/) +- [Виртуальная машина Ethereum](/developers/docs/evm/) + +## Связанные руководства {#related-tutorials} + +- [Сокращение контрактов для борьбы с ограничением размера контракта](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _– несколько практических советов по уменьшению размера вашего смарт-контракта._ +- [Регистрация данных из смарт-контрактов с помощью событий](/developers/tutorials/logging-events-smart-contracts/) _– введение в события смарт-контрактов и способы их использования для регистрации данных._ +- [Взаимодействие с другими контрактами из Solidity](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– как развернуть смарт-контракт из существующего контракта и взаимодействовать с ним._ diff --git a/public/content/translations/ru/developers/docs/smart-contracts/compiling/index.md b/public/content/translations/ru/developers/docs/smart-contracts/compiling/index.md new file mode 100644 index 00000000000..a79cb2e8cfb --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/compiling/index.md @@ -0,0 +1,282 @@ +--- +title: "Составление смарт-контрактов" +description: "Объяснение того, почему вам нужно компилировать смарт-контракты и что на самом деле делает компиляция." +lang: ru +incomplete: true +--- + +Вам необходимо скомпилировать свой контракт, чтобы ваше веб-приложение и виртуальная машина Ethereum (EVM) могли его понять. + +## Предварительные условия {#prerequisites} + +Возможно, вам будет полезно прочитать наше введение в [умные контракты](/developers/docs/smart-contracts/) и [виртуальную машину Ethereum](/developers/docs/evm/), прежде чем читать о компиляции. + +## EVM {#the-evm} + +Чтобы [EVM](/developers/docs/evm/) могла выполнять ваш контракт, он должен быть в виде **байт-кода**. Компиляция превращает это: + +```solidity +pragma solidity 0.4.24; + +contract Greeter { + + function greet() public view returns (string memory) { + return "Hello"; + } + +} +``` + +**в это** + +``` +PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xCFAE3217 EQ PUSH2 0x46 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x52 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x5B PUSH2 0xD6 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x9B JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x80 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xC8 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x40 DUP1 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x48656C6C6F000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 SLT 0xec 0xe 0xf5 0xf8 SLT 0xc7 0x2d STATICCALL ADDRESS SHR 0xdb COINBASE 0xb1 BALANCE 0xe8 0xf8 DUP14 0xda 0xad DUP13 LOG1 0x4c 0xb4 0x26 0xc2 DELEGATECALL PUSH7 0x8994D3E002900 +``` + +Они называются **опкодами**. Опкоды EVM — это низкоуровневые инструкции, которые может выполнять виртуальная машина Ethereum (EVM). Каждый опкод представляет собой определенную операцию, например арифметические операции, логические операции, манипулирование данными, управление потоком и т. д. + +[Подробнее об опкодах](/developers/docs/evm/opcodes/) + +## Веб-приложения {#web-applications} + +Компилятор также создаст **двоичный интерфейс приложения (ABI)**, который необходим вашему приложению для понимания контракта и вызова его функций. + +ABI - это файл JSON, который описывает развернутый контракт и его функции смарт-контракту. Это помогает преодолеть разрыв между web2 и web3 + +[Клиентская библиотека JavaScript](/developers/docs/apis/javascript/) будет считывать **ABI**, чтобы вы могли вызывать свой умный контракт в интерфейсе вашего веб-приложения. + +Ниже приведен ABI для контракта токена ERC-20. ERC-20 - это токен, которым вы можете торговать на Ethereum. + +```json +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] +``` + +## Дополнительные материалы {#further-reading} + +- [Спецификация ABI](https://solidity.readthedocs.io/en/v0.7.0/abi-spec.html) _— Solidity_ + +## Смежные темы {#related-topics} + +- [Клиентские библиотеки JavaScript](/developers/docs/apis/javascript/) +- [виртуальная машина Ethereum](/developers/docs/evm/) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/composability/index.md b/public/content/translations/ru/developers/docs/smart-contracts/composability/index.md new file mode 100644 index 00000000000..5de939f564d --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/composability/index.md @@ -0,0 +1,76 @@ +--- +title: "Возможность компоновки смарт-контрактов" +description: "Узнайте, как умные контракты можно объединять, как кубики Lego, для создания сложных децентрализованных приложений путем повторного использования существующих компонентов." +lang: ru +incomplete: true +--- + +## Краткое введение {#a-brief-introduction} + +Смарт-контракты общедоступны в Ethereum и могут рассматриваться как открытые API. Вам не нужно писать собственный смарт-контракт, чтобы стать разработчиком децентрализованных приложений, вам просто нужно знать, как с ними взаимодействовать. Например, вы можете использовать существующие умные контракты [Uniswap](https://uniswap.exchange/swap), децентрализованной биржи, для обработки всей логики обмена токенов в вашем приложении — вам не нужно начинать с нуля. Ознакомьтесь с некоторыми из их контрактов [v2](https://github.com/Uniswap/uniswap-v2-core/tree/master/contracts) и [v3](https://github.com/Uniswap/uniswap-v3-core/tree/main/contracts). + +## Что такое композиционность? {#what-is-composability} + +Композиционность - это объединение отдельных компонентов для создания новых систем или выходов. В разработке программного обеспечения композиционность означает, что разработчики могут многократно использовать существующие компоненты программного обеспечения для создания новых приложений. Хороший способ понять композиционность - это думать о составных элементах, как о блоках Lego. Каждый Lego может быть объединен с другим, позволяя Вам строить сложные структуры путем сочетаний различные Lego. + +В Ethereum каждый смарт-контракт представляет собой что-то вроде Lego - Вы можете использовать смарт-контракты из других проектов в качестве строительных блоков для Вашего проекта. Это означает, что Вам не нужно тратить время на изобретение "колеса" или строительство с нуля. + +## Как работает композиционность? {#how-does-composability-work} + +Смарт-контракты Ethereum похожи на публичные приложения, так любой может взаимодействовать с контрактом или внедрить его в децентрализованные приложения для добавления функциональности. Композиционность смарт-контрактов, как правило, работает на основе трех принципов: модульность, автономность и открытость: + +\*\*1. **Модульность**: это способность отдельных компонентов выполнять определенную задачу. В Ethereum каждый смарт-контракт имеет определенный вариант использования (как показано в примере Uniswap). + +\*\*2. **Автономность**: составные компоненты должны быть способны работать независимо. Каждый смарт-контракт в Ethereum является самоисполняемым и может функционировать, не полагаясь на другие части системы. + +\*\*3. **Обнаруживаемость**: разработчики не могут вызывать внешние контракты или интегрировать программные библиотеки в приложения, если первые не являются общедоступными. По дизайну, смарт-контракты являются открытыми источниками; любой может вызвать смарт-контракт или ответвление базового кода. + +## Преимущества композиционности {#benefits-of-composability} + +### Сокращенный цикл разработки {#shorter-development-cycle} + +Композиционность сокращает объем работы, которую разработчикам приходится выполнять при создании [децентрализованных приложений](/apps/#what-are-dapps). [Как говорит Навал Равикант:](https://twitter.com/naval/status/1444366754650656770) \ + +Если существует смарт-контракт, который решает одну проблему, другие разработчики могут повторно использовать его, чтобы им не приходилось решать одну и ту же проблему. Таким образом, разработчики могут брать существующие библиотеки программного обеспечения и добавлять дополнительную функциональность для создания новых децентрализованных приложений. + +### Больше инноваций {#greater-innovation} + +Компонуемость поощряет инновации и эксперименты, поскольку разработчики могут свободно повторно использовать, изменять, дублировать или интегрировать код с открытым исходным кодом для достижения желаемых результатов. В результате команды разработчиков тратят меньше времени на базовую функциональность и могут уделять больше времени экспериментам с новыми функциями. + +### Улучшенный пользовательский опыт {#better-user-experience} + +Функциональная совместимость компонентов экосистемы Ethereum улучшает пользовательский опыт. Пользователи могут получить доступ к большей функциональности, когда децентрализованные приложения интегрируют внешние смарт-контракты, чем во фрагментированной экосистеме, где приложения не могут взаимодействовать друг с другом. + +Мы воспользуемся примером из арбитражной торговли, чтобы проиллюстрировать преимущества функциональной совместимости: + +Если токен торгуется на `бирже А` дороже, чем на `бирже B`, вы можете воспользоваться разницей в цене, чтобы получить прибыль. Однако вы можете сделать это, только если у вас достаточно капитала для финансирования транзакции (т. е. для покупки токена на `бирже B` и его продажи на `бирже A`). + +В ситуации, когда у вас недостаточно средств для совершения сделки, идеальным вариантом может стать срочный заем. [Срочные займы](/defi/#flash-loans) — это очень технически сложная вещь, но основная идея заключается в том, что вы можете заимствовать активы (без обеспечения) и вернуть их в рамках _одной_ транзакции. + +Возвращаясь к нашему первоначальному примеру, арбитражный трейдер может взять большой срочный заем, купить токены на `бирже B`, продать их на `бирже A`, вернуть капитал + проценты и оставить себе прибыль в рамках одной транзакции. Эта сложная логика требует объединения вызовов к нескольким контрактам, что было бы невозможно, если бы у смарт-контрактов отсутствовала функциональная совместимость. + +## Примеры компонуемости в Ethereum {#composability-in-ethereum} + +### Обмен токенов {#token-swaps} + +Если вы создаете децентрализованное приложение, в котором транзакции должны оплачиваться в ETH, вы можете разрешить пользователям платить другими токенами ERC-20, интегрировав логику обмена токенов. Код автоматически конвертирует токен пользователя в ETH до того, как контракт выполнит вызванную функцию. + +### Управление {#governance} + +Создание индивидуальных систем управления для [DAO](/dao/) может быть дорогостоящим и трудоемким. Вместо этого вы можете использовать инструментарий управления с открытым исходным кодом, такой как [Aragon Client](https://client.aragon.org/), чтобы запустить свою DAO и быстро создать систему управления. + +### Управление идентификацией {#identity-management} + +Вместо создания собственной системы аутентификации или использования централизованных провайдеров, вы можете интегрировать инструменты децентрализованной идентификации (DID) для управления аутентификацией пользователей. Примером может служить [SpruceID](https://www.spruceid.com/), инструментарий с открытым исходным кодом, который предлагает функцию "Войти через Ethereum", позволяющую пользователям подтверждать свою личность с помощью кошелька Ethereum. + +## Связанные руководства {#related-tutorials} + +- [Быстрый старт разработки фронтенда для вашего децентрализованного приложения с помощью create-eth-app](/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app/) _— Обзор использования create-eth-app для создания приложений с популярными готовыми смарт-контрактами._ + +## Дополнительные материалы {#further-reading} + +_Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!_ + +- [Компонуемость — это инновация](https://a16zcrypto.com/posts/article/how-composability-unlocks-crypto-and-everything-else/) +- [Почему компонуемость важна для Web3](https://hackernoon.com/why-composability-matters-for-web3) +- [Что такое компонуемость?](https://blog.aragon.org/what-is-composability/#:~:text=Aragon,connect%20to%20every%20other%20piece.) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/deploying/index.md b/public/content/translations/ru/developers/docs/smart-contracts/deploying/index.md new file mode 100644 index 00000000000..c19c5bef2c5 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/deploying/index.md @@ -0,0 +1,81 @@ +--- +title: "Развертывание смарт-контрактов" +description: "Узнайте, как развертывать умные контракты в сетях Ethereum, включая предварительные требования, инструменты и этапы развертывания." +lang: ru +--- + +Вам необходимо развернуть свой смарт-контракт, чтобы он был доступен пользователям сети Ethereum. + +Чтобы развернуть смарт-контракт, вы просто отправляете транзакцию Ethereum, содержащую скомпилированный код смарт-контракта, не указывая получателя. + +## Предварительные условия {#prerequisites} + +Прежде чем развертывать смарт-контракты, вам следует ознакомиться с [сетями Ethereum](/developers/docs/networks/), [транзакциями](/developers/docs/transactions/) и [анатомией смарт-контрактов](/developers/docs/smart-contracts/anatomy/). + +Развертывание контракта также стоит эфира (ETH), поскольку он хранится в блокчейне, поэтому вам следует ознакомиться с [газом и комиссиями](/developers/docs/gas/) в Ethereum. + +Наконец, перед развертыванием вам нужно будет скомпилировать ваш контракт, поэтому убедитесь, что вы прочли о [компиляции смарт-контрактов](/developers/docs/smart-contracts/compiling/). + +## Как развернуть смарт-контракт {#how-to-deploy-a-smart-contract} + +### Что вам понадобится {#what-youll-need} + +- Байт-код вашего контракта — он генерируется путем [компиляции](/developers/docs/smart-contracts/compiling/) +- ETH для газа — вы устанавливаете свой лимит газа, как и для обычных транзакций, поэтому имейте в виду, что для развертывания контракта требуется гораздо больше газа, чем для простого перевода ETH +- сценарий развертывания или плагин +- доступ к [узлу Ethereum](/developers/docs/nodes-and-clients/) через запуск собственного узла, подключение к общедоступному или использование ключа API [сервиса узлов](/developers/docs/nodes-and-clients/nodes-as-a-service/) + +### Этапы развертывания смарт-контракта {#steps-to-deploy} + +Конкретные этапы будут зависеть от используемой среды разработки. Например, вы можете ознакомиться с [документацией Hardhat по развертыванию контрактов](https://hardhat.org/docs/tutorial/deploying) или [документацией Foundry по развертыванию и верификации смарт-контракта](https://book.getfoundry.sh/forge/deploying). После развертывания ваш контракт будет иметь адрес Ethereum, как и другие [аккаунты](/developers/docs/accounts/), и его можно будет верифицировать с помощью [инструментов верификации исходного кода](/developers/docs/smart-contracts/verifying/#source-code-verification-tools). + +## Связанные инструменты {#related-tools} + +**Remix — _Remix IDE позволяет разрабатывать, развертывать и администрировать смарт-контракты для блокчейнов, подобных Ethereum_** + +- [Remix](https://remix.ethereum.org) + +**Tenderly — _платформа для разработки Web3, предоставляющая средства отладки, наблюдаемости и инфраструктурные компоненты для разработки, тестирования, мониторинга и эксплуатации смарт-контрактов_** + +- [tenderly.co](https://tenderly.co/) +- [Документация](https://docs.tenderly.co/) +- [GitHub](https://github.com/Tenderly) +- [Discord](https://discord.gg/eCWjuvt) + +**Hardhat — _среда разработки для компиляции, развертывания, тестирования и отладки вашего программного обеспечения Ethereum_** + +- [hardhat.org](https://hardhat.org/getting-started/) +- [Документация по развертыванию ваших контрактов](https://hardhat.org/docs/tutorial/deploying) +- [GitHub](https://github.com/nomiclabs/hardhat) +- [Discord](https://discord.com/invite/TETZs2KK4k) + +**thirdweb — _простое развертывание любого контракта в любой EVM-совместимой сети с помощью одной команды_** + +- [Документация](https://portal.thirdweb.com/deploy/) + +**Crossmint — _платформа для разработки Web3 корпоративного уровня для развертывания смарт-контрактов, приема платежей по кредитным картам и кроссчейн-платежей, а также использования API для создания, распространения, продажи, хранения и редактирования NFT._** + +- [crossmint.com](https://www.crossmint.com) +- [Документация](https://docs.crossmint.com) +- [Discord](https://discord.com/invite/crossmint) +- [Блог](https://blog.crossmint.com) + +## Связанные руководства {#related-tutorials} + +- [Развертывание вашего первого смарт-контракта](/developers/tutorials/deploying-your-first-smart-contract/) _– введение в развертывание вашего первого смарт-контракта в тестовой сети Ethereum._ +- [Hello World | руководство по смарт-контрактам](/developers/tutorials/hello-world-smart-contract/) _– простое руководство по созданию и развертыванию базового смарт-контракта на Ethereum._ +- [Взаимодействие с другими контрактами из Solidity](/developers/tutorials/interact-with-other-contracts-from-solidity/) _– как развернуть смарт-контракт из существующего контракта и взаимодействовать с ним._ +- [Как уменьшить размер контракта](/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) _– как уменьшить размер контракта, чтобы он не превышал лимит, и сэкономить на газе_ + +## Дополнительные материалы {#further-reading} + +- [https://docs.openzeppelin.com/learn/deploying-and-interacting](https://docs.openzeppelin.com/learn/deploying-and-interacting) — _OpenZeppelin_ +- [Развертывание ваших контрактов с помощью Hardhat](https://hardhat.org/docs/tutorial/deploying) — _Nomic Labs_ + +_Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!_ + +## Смежные темы {#related-topics} + +- [Фреймворки для разработки](/developers/docs/frameworks/) +- [Запуск узла Ethereum](/developers/docs/nodes-and-clients/run-a-node/) +- [Узлы как услуга](/developers/docs/nodes-and-clients/nodes-as-a-service) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/formal-verification/index.md b/public/content/translations/ru/developers/docs/smart-contracts/formal-verification/index.md new file mode 100644 index 00000000000..3fcc8f8184a --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/formal-verification/index.md @@ -0,0 +1,284 @@ +--- +title: "Верификация смарт-контрактов" +description: "Обзор формальной верификации для смарт-контрактов Ethereum" +lang: ru +--- + +[Смарт-контракты](/developers/docs/smart-contracts/) делают возможным создание децентрализованных, не требующих доверия и надежных приложений, которые представляют новые варианты использования и открывают ценность для пользователей. Поскольку смарт-контракты управляют большими объемами ценностей, безопасность является критически важным аспектом для разработчиков. + +Формальная верификация — это один из рекомендуемых методов для улучшения [безопасности смарт-контрактов](/developers/docs/smart-contracts/security/). Формальная верификация, которая использует [формальные методы](https://www.brookings.edu/techstream/formal-methods-as-a-path-toward-better-cybersecurity/) для спецификации, проектирования и верификации программ, годами использовалась для обеспечения корректности критически важных аппаратных и программных систем. + +При реализации в смарт-контрактах формальная верификация может доказать, что бизнес-логика контракта соответствует предопределенной спецификации. По сравнению с другими методами оценки корректности кода контракта, такими как тестирование, формальная верификация дает более сильные гарантии того, что смарт-контракт является функционально корректным. + +## Что такое формальная верификация? {#what-is-formal-verification} + +Формальная верификация относится к процессу оценки корректности системы в соответствии с формальной спецификацией. Проще говоря, формальная верификация позволяет нам проверить, удовлетворяет ли поведение системы некоторым требованиям (т. е. делает ли она то, что мы хотим). + +Ожидаемое поведение системы (в данном случае смарт-контракта) описывается с помощью формального моделирования, в то время как языки спецификаций позволяют создавать формальные свойства. Затем методы формальной верификации могут проверить, что реализация контракта соответствует его спецификации, и получить математическое доказательство корректности первого. Когда контракт удовлетворяет своей спецификации, он описывается как «функционально корректный», «корректный по замыслу» или «корректный по построению». + +### Что такое формальная модель? {#what-is-a-formal-model} + +В информатике [формальная модель](https://en.wikipedia.org/wiki/Model_of_computation) — это математическое описание вычислительного процесса. Программы абстрагируются в математические функции (уравнения), при этом модель описывает, как вычисляются выходные данные функций для заданных входных данных. + +Формальные модели обеспечивают уровень абстракции, на котором можно оценивать анализ поведения программы. Существование формальных моделей позволяет создать _формальную спецификацию_, которая описывает желаемые свойства рассматриваемой модели. + +Для моделирования смарт-контрактов для формальной верификации используются различные методы. Например, некоторые модели используются для рассуждений о высокоуровневом поведении смарт-контракта. Эти методы моделирования применяют к смарт-контрактам подход «черного ящика», рассматривая их как системы, которые принимают входные данные и выполняют вычисления на основе этих входных данных. + +Высокоуровневые модели фокусируются на взаимосвязи между смарт-контрактами и внешними агентами, такими как внешние аккаунты (EOA), аккаунты контрактов и среда блокчейна. Такие модели полезны для определения свойств, которые указывают, как должен вести себя контракт в ответ на определенные взаимодействия с пользователем. + +И наоборот, другие формальные модели фокусируются на низкоуровневом поведении смарт-контракта. Хотя высокоуровневые модели могут помочь в рассуждениях о функциональности контракта, они могут не улавливать детали внутренней работы реализации. Низкоуровневые модели применяют к анализу программ подход «белого ящика» и полагаются на низкоуровневые представления приложений смарт-контрактов, такие как трассировки программ и [графы потока управления](https://en.wikipedia.org/wiki/Control-flow_graph), для рассуждений о свойствах, относящихся к выполнению контракта. + +Низкоуровневые модели считаются идеальными, поскольку они представляют фактическое выполнение смарт-контракта в среде выполнения Ethereum (т. е. [EVM](/developers/docs/evm/)). Методы низкоуровневого моделирования особенно полезны в установлении критических свойств безопасности в смарт-контрактах и обнаружении потенциальных уязвимостей. + +### Что такое формальная спецификация? {#what-is-a-formal-specification} + +Спецификация — это просто техническое требование, которому должна удовлетворять определенная система. В программировании спецификации представляют общие идеи о выполнении программы (т. е. что должна делать программа). + +В контексте смарт-контрактов формальные спецификации относятся к _свойствам_ — формальным описаниям требований, которым должен удовлетворять контракт. Такие свойства описываются как «инварианты» и представляют собой логические утверждения о выполнении контракта, которые должны оставаться верными при любых возможных обстоятельствах, без каких-либо исключений. + +Таким образом, мы можем думать о формальной спецификации как о наборе утверждений, написанных на формальном языке, которые описывают предполагаемое выполнение смарт-контракта. Спецификации охватывают свойства контракта и определяют, как он должен вести себя в различных обстоятельствах. Цель формальной верификации состоит в том, чтобы определить, обладает ли смарт-контракт этими свойствами (инвариантами) и что эти свойства не нарушаются во время выполнения. + +Формальные спецификации имеют решающее значение в разработке безопасных реализаций смарт-контрактов. Контракты, в которых не реализованы инварианты или чьи свойства нарушаются во время выполнения, подвержены уязвимостям, которые могут нанести вред функциональности или привести к злонамеренным эксплойтам. + +## Типы формальных спецификаций для смарт-контрактов {#formal-specifications-for-smart-contracts} + +Формальные спецификации позволяют проводить математические рассуждения о корректности выполнения программы. Как и в случае с формальными моделями, формальные спецификации могут фиксировать либо высокоуровневые свойства, либо низкоуровневое поведение реализации контракта. + +Формальные спецификации выводятся с использованием элементов [логики программ](https://en.wikipedia.org/wiki/Logic_programming), что позволяет проводить формальные рассуждения о свойствах программы. Логика программ имеет формальные правила, которые выражают (на математическом языке) ожидаемое поведение программы. При создании формальных спецификаций используются различные логики программ, включая [логику достижимости](https://en.wikipedia.org/wiki/Reachability_problem), [временную логику](https://en.wikipedia.org/wiki/Temporal_logic) и [логику Хоара](https://en.wikipedia.org/wiki/Hoare_logic). + +Формальные спецификации для смарт-контрактов можно в целом классифицировать как **высокоуровневые** или **низкоуровневые** спецификации. Независимо от того, к какой категории относится спецификация, она должна адекватно и недвусмысленно описывать свойство анализируемой системы. + +### Высокоуровневые спецификации {#high-level-specifications} + +Как следует из названия, высокоуровневая спецификация (также называемая «модельно-ориентированной спецификацией») описывает высокоуровневое поведение программы. Высокоуровневые спецификации моделируют смарт-контракт как [конечный автомат](https://en.wikipedia.org/wiki/Finite-state_machine) (FSM), который может переходить между состояниями, выполняя операции, при этом временная логика используется для определения формальных свойств модели FSM. + +[Временные логики](https://en.wikipedia.org/wiki/Temporal_logic) — это «правила для рассуждений о предложениях, квалифицированных с точки зрения времени (например, «Я _всегда_ голоден» или «Я _в конце концов_ проголодаюсь»)». Применительно к формальной верификации временные логики используются для формулирования утверждений о правильном поведении систем, смоделированных как конечные автоматы. В частности, временная логика описывает будущие состояния, в которых может находиться смарт-контракт, и как он переходит между состояниями. + +Высокоуровневые спецификации обычно охватывают два критических временных свойства для смарт-контрактов: **безопасность** и **живучесть**. Свойства безопасности представляют идею «никогда не случится ничего плохого» и обычно выражают инвариантность. Свойство безопасности может определять общие требования к программному обеспечению, например, отсутствие [взаимоблокировок](https://www.techtarget.com/whatis/definition/deadlock), или выражать специфичные для домена свойства для контрактов (например, инварианты контроля доступа к функциям, допустимые значения переменных состояния или условия для передачи токенов). + +Возьмем, к примеру, это требование безопасности, которое охватывает условия использования `transfer()` или `transferFrom()` в контрактах токенов ERC-20: _«Баланс отправителя никогда не бывает ниже запрошенной суммы токенов для отправки»_. Это описание инварианта контракта на естественном языке может быть переведено в формальную (математическую) спецификацию, которую затем можно строго проверить на валидность. + +Свойства живучести утверждают, что «в конце концов произойдет что-то хорошее», и касаются способности контракта переходить через различные состояния. Примером свойства живучести является «ликвидность», которая относится к способности контракта переводить свои балансы пользователям по запросу. Если это свойство нарушено, пользователи не смогут вывести активы, хранящиеся в контракте, как это случилось во время [инцидента с кошельком Parity](https://www.cnbc.com/2017/11/08/accidental-bug-may-have-frozen-280-worth-of-ether-on-parity-wallet.html). + +### Низкоуровневые спецификации {#low-level-specifications} + +Высокоуровневые спецификации берут за отправную точку конечно-автоматную модель контракта и определяют желаемые свойства этой модели. В отличие от них, низкоуровневые спецификации (также называемые «свойство-ориентированными спецификациями») часто моделируют программы (смарт-контракты) как системы, состоящие из набора математических функций, и описывают правильное поведение таких систем. + +Проще говоря, низкоуровневые спецификации анализируют _трассировки программ_ и пытаются определить свойства смарт-контракта на основе этих трассировок. Трассировки относятся к последовательностям выполнения функций, которые изменяют состояние смарт-контракта; следовательно, низкоуровневые спецификации помогают определить требования для внутреннего выполнения контракта. + +Низкоуровневые формальные спецификации могут быть представлены в виде свойств в стиле Хоара или инвариантов на путях выполнения. + +### Свойства в стиле Хоара {#hoare-style-properties} + +[Логика Хоара](https://en.wikipedia.org/wiki/Hoare_logic) предоставляет набор формальных правил для рассуждений о корректности программ, включая смарт-контракты. Свойство в стиле Хоара представляется тройкой Хоара `{P}c{Q}`, где `c` — это программа, а `P` и `Q` — предикаты состояния `c` (т. е. программы), формально описываемые как _предусловия_ и _постусловия_ соответственно. + +Предусловие — это предикат, описывающий условия, необходимые для корректного выполнения функции; пользователи, вызывающие контракт, должны удовлетворять этому требованию. Постусловие — это предикат, описывающий условие, которое устанавливает функция при корректном выполнении; пользователи могут ожидать, что это условие будет истинным после вызова функции. _Инвариант_ в логике Хоара — это предикат, который сохраняется при выполнении функции (т. е. не изменяется). + +Спецификации в стиле Хоара могут гарантировать либо _частичную корректность_, либо _полную корректность_. Реализация функции контракта является «частично корректной», если предусловие выполняется до выполнения функции, и если выполнение завершается, то постусловие также истинно. Доказательство полной корректности получается, если предусловие истинно до выполнения функции, выполнение гарантированно завершится, и когда это произойдет, постусловие будет истинным. + +Получить доказательство полной корректности сложно, так как некоторые выполнения могут задерживаться перед завершением или не завершаться вовсе. Тем не менее, вопрос о том, завершится ли выполнение, возможно, является спорным, поскольку механизм газа в Ethereum предотвращает бесконечные циклы программы (выполнение либо успешно завершается, либо заканчивается из-за ошибки «нехватки газа»). + +Спецификации смарт-контрактов, созданные с использованием логики Хоара, будут иметь предусловия, постусловия и инварианты, определенные для выполнения функций и циклов в контракте. Предусловия часто включают возможность ошибочных входных данных для функции, а постусловия описывают ожидаемую реакцию на такие входные данные (например, выбрасывание определенного исключения). Таким образом, свойства в стиле Хоара эффективны для обеспечения корректности реализаций контрактов. + +Многие платформы формальной верификации используют спецификации в стиле Хоара для доказательства семантической корректности функций. Также возможно добавлять свойства в стиле Хоара (как утверждения) непосредственно в код контракта, используя операторы `require` и `assert` в Solidity. + +Операторы `require` выражают предусловие или инвариант и часто используются для проверки входных данных пользователя, в то время как `assert` фиксирует постусловие, необходимое для безопасности. Например, надлежащий контроль доступа к функциям (пример свойства безопасности) может быть достигнут с помощью `require` в качестве проверки предусловия для идентификации вызывающего аккаунта. Аналогичным образом, инвариант для допустимых значений переменных состояния в контракте (например, общее количество токенов в обращении) можно защитить от нарушения, используя `assert` для подтверждения состояния контракта после выполнения функции. + +### Свойства на уровне трассировки {#trace-level-properties} + +Спецификации на основе трассировки описывают операции, которые переводят контракт между различными состояниями, и отношения между этими операциями. Как объяснялось ранее, трассировки — это последовательности операций, которые определенным образом изменяют состояние контракта. + +Этот подход основан на модели смарт-контрактов как систем с переходом состояний с некоторыми предопределенными состояниями (описанными переменными состояния) вместе с набором предопределенных переходов (описанных функциями контракта). Кроме того, [граф потока управления](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/) (CFG), который является графическим представлением потока выполнения программы, часто используется для описания операционной семантики контракта. Здесь каждая трассировка представляется как путь на графе потока управления. + +В первую очередь спецификации на уровне трассировки используются для рассуждений о шаблонах внутреннего выполнения в смарт-контрактах. Создавая спецификации на уровне трассировки, мы утверждаем допустимые пути выполнения (т. е. переходы состояний) для смарт-контракта. Используя такие методы, как символическое выполнение, мы можем формально проверить, что выполнение никогда не следует по пути, не определенному в формальной модели. + +Давайте используем пример контракта [DAO](/dao/), у которого есть несколько общедоступных функций, чтобы описать свойства на уровне трассировки. Здесь мы предполагаем, что контракт ДАО позволяет пользователям выполнять следующие операции: + +- Вносить средства + +- Голосовать по предложению после внесения средств + +- Требовать возврат средств, если они не голосуют по предложению + +Примеры свойств на уровне трассировки могут быть такими: _«пользователи, которые не вносят средства, не могут голосовать по предложению»_ или _«пользователи, которые не голосуют по предложению, всегда должны иметь возможность требовать возврат средств»_. Оба свойства утверждают предпочтительные последовательности выполнения (голосование не может происходить _до_ внесения средств, а требование возврата средств не может происходить _после_ голосования по предложению). + +## Методы формальной верификации смарт-контрактов {#formal-verification-techniques} + +### Проверка моделей {#model-checking} + +Проверка моделей — это метод формальной верификации, в котором алгоритм проверяет формальную модель смарт-контракта на соответствие ее спецификации. При проверке моделей смарт-контракты часто представляются как системы с переходом состояний, в то время как свойства допустимых состояний контракта определяются с использованием временной логики. + +Проверка моделей требует создания абстрактного математического представления системы (т. е. контракта) и выражения свойств этой системы с использованием формул, основанных на [пропозициональной логике](https://www.baeldung.com/cs/propositional-logic). Это упрощает задачу алгоритма проверки моделей, а именно, доказать, что математическая модель удовлетворяет заданной логической формуле. + +Проверка моделей в формальной верификации в основном используется для оценки временных свойств, которые описывают поведение контракта с течением времени. Временные свойства для смарт-контрактов включают _безопасность_ и _живучесть_, которые мы объяснили ранее. + +Например, свойство безопасности, связанное с контролем доступа (например, _Только владелец контракта может вызывать `selfdestruct`_), может быть записано в формальной логике. После этого алгоритм проверки моделей может проверить, удовлетворяет ли контракт этой формальной спецификации. + +Проверка моделей использует исследование пространства состояний, которое включает построение всех возможных состояний смарт-контракта и попытку найти достижимые состояния, приводящие к нарушениям свойств. Однако это может привести к бесконечному числу состояний (известному как «проблема взрыва состояний»), поэтому средства проверки моделей полагаются на методы абстракции, чтобы сделать возможным эффективный анализ смарт-контрактов. + +### Доказательство теорем {#theorem-proving} + +Доказательство теорем — это метод математического рассуждения о корректности программ, включая смарт-контракты. Он включает в себя преобразование модели системы контракта и ее спецификаций в математические формулы (логические утверждения). + +Целью доказательства теорем является проверка логической эквивалентности между этими утверждениями. «Логическая эквивалентность» (также называемая «логической биимпликацией») — это тип отношения между двумя утверждениями, при котором первое утверждение истинно _тогда и только тогда, когда_ истинно второе утверждение. + +Требуемое отношение (логическая эквивалентность) между утверждениями о модели контракта и ее свойстве формулируется как доказуемое утверждение (называемое теоремой). Используя формальную систему вывода, автоматический доказыватель теорем может проверить валидность теоремы. Другими словами, доказыватель теорем может окончательно доказать, что модель смарт-контракта точно соответствует его спецификациям. + +В то время как проверка моделей моделирует контракты как системы переходов с конечными состояниями, доказательство теорем может обрабатывать анализ систем с бесконечными состояниями. Однако это означает, что автоматический доказыватель теорем не всегда может знать, является ли логическая проблема «разрешимой» или нет. + +В результате часто требуется помощь человека, чтобы направить доказыватель теорем в получении доказательств корректности. Использование человеческих усилий в доказательстве теорем делает его более дорогим в использовании, чем проверка моделей, которая полностью автоматизирована. + +### Символическое выполнение {#symbolic-execution} + +Символическое выполнение — это метод анализа смарт-контракта путем выполнения функций с использованием _символических значений_ (например, `x > 5`) вместо _конкретных значений_ (например, `x == 5`). Как метод формальной верификации, символическое выполнение используется для формального рассуждения о свойствах на уровне трассировки в коде контракта. + +Символическое выполнение представляет трассировку выполнения в виде математической формулы над символическими входными значениями, иначе называемой _предикатом пути_. [Решатель SMT](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories) используется для проверки, является ли предикат пути «выполнимым» (т. е. существует ли значение, которое может удовлетворить формулу). Если уязвимый путь выполним, решатель SMT сгенерирует конкретное значение, которое направит выполнение по этому пути. + +Предположим, функция смарт-контракта принимает на вход значение `uint` (`x`) и отменяет транзакцию, если `x` больше `5`, а также меньше `10`. Поиск значения для `x`, которое вызовет ошибку, с помощью обычной процедуры тестирования потребует прогона десятков тестовых случаев (или более) без гарантии фактического обнаружения входных данных, вызывающих ошибку. + +Напротив, инструмент символического выполнения выполнит функцию с символическим значением: `X > 5 ∧ X < 10` (т. е. `x` больше 5 И `x` меньше 10). Связанный предикат пути `x = X > 5 ∧ X < 10` затем будет передан для решения решателю SMT. Если определенное значение удовлетворяет формуле `x = X > 5 ∧ X < 10`, решатель SMT вычислит его — например, решатель может выдать `7` в качестве значения для `x`. + +Поскольку символическое выполнение зависит от входных данных программы, а набор входных данных для исследования всех достижимых состояний потенциально бесконечен, это все еще форма тестирования. Однако, как показано в примере, символическое выполнение более эффективно, чем обычное тестирование, для поиска входных данных, которые вызывают нарушения свойств. + +Более того, символическое выполнение дает меньше ложных срабатываний, чем другие методы, основанные на свойствах (например, фаззинг), которые случайным образом генерируют входные данные для функции. Если во время символического выполнения срабатывает состояние ошибки, то можно сгенерировать конкретное значение, которое вызывает ошибку, и воспроизвести проблему. + +Символическое выполнение также может предоставить некоторую степень математического доказательства корректности. Рассмотрим следующий пример функции контракта с защитой от переполнения: + +``` +function safe_add(uint x, uint y) returns(uint z){ + + z = x + y; + require(z>=x); + require(z>=y); + + return z; +} +``` + +Трассировка выполнения, приводящая к целочисленному переполнению, должна удовлетворять формуле: `z = x + y AND (z >= x) AND (z >= y) AND (z < x OR z < y)`. Такая формула вряд ли будет решена, следовательно, это служит математическим доказательством того, что функция `safe_add` никогда не переполняется. + +### Зачем использовать формальную верификацию для смарт-контрактов? {#benefits-of-formal-verification} + +#### Необходимость надежности {#need-for-reliability} + +Формальная верификация используется для оценки корректности критически важных для безопасности систем, сбой которых может иметь разрушительные последствия, такие как смерть, травмы или финансовый крах. Смарт-контракты — это высокоценные приложения, контролирующие огромные суммы, и простые ошибки в проектировании могут привести к [невосполнимым потерям для пользователей](https://www.freecodecamp.org/news/a-hacker-stole-31m-of-ether-how-it-happened-and-what-it-means-for-ethereum-9e5dc29e33ce/amp/). Однако формальная верификация контракта перед развертыванием может повысить гарантии того, что он будет работать так, как ожидается, после запуска в блокчейне. + +Надежность — очень желаемое качество для любого смарт-контракта, особенно потому, что код, развернутый в виртуальной машине Ethereum (EVM), как правило, неизменяем. Поскольку обновления после запуска не всегда доступны, необходимость гарантировать надежность контрактов делает формальную верификацию необходимой. Формальная верификация способна обнаруживать сложные проблемы, такие как целочисленные недополнения и переполнения, повторный вход и плохая оптимизация газа, которые могут ускользнуть от аудиторов и тестировщиков. + +#### Доказательство функциональной корректности {#prove-functional-correctness} + +Тестирование программ — самый распространенный метод доказательства того, что смарт-контракт удовлетворяет некоторым требованиям. Это включает в себя выполнение контракта с образцом данных, которые он должен обрабатывать, и анализ его поведения. Если контракт возвращает ожидаемые результаты для образца данных, то разработчики получают объективное доказательство его корректности. + +Однако этот подход не может доказать корректное выполнение для входных значений, которые не являются частью образца. Таким образом, тестирование контракта может помочь обнаружить ошибки (т. е. если некоторые пути кода не возвращают желаемые результаты во время выполнения), но **оно не может окончательно доказать отсутствие ошибок**. + +Напротив, формальная верификация может формально доказать, что смарт-контракт удовлетворяет требованиям для бесконечного диапазона выполнений, _вообще не запуская_ контракт. Это требует создания формальной спецификации, которая точно описывает правильное поведение контракта, и разработки формальной (математической) модели системы контракта. Затем мы можем следовать формальной процедуре доказательства, чтобы проверить согласованность между моделью контракта и его спецификацией. + +При формальной верификации вопрос о том, удовлетворяет ли бизнес-логика контракта требованиям, является математическим утверждением, которое можно доказать или опровергнуть. Формально доказывая утверждение, мы можем проверить бесконечное количество тестовых случаев за конечное число шагов. Таким образом, формальная верификация имеет лучшие перспективы для доказательства того, что контракт функционально корректен по отношению к спецификации. + +#### Идеальные цели верификации {#ideal-verification-targets} + +Цель верификации описывает систему, которую необходимо формально верифицировать. Формальная верификация лучше всего используется во «встроенных системах» (небольших, простых частях программного обеспечения, которые являются частью более крупной системы). Они также идеальны для специализированных доменов с небольшим количеством правил, так как это облегчает модификацию инструментов для проверки свойств, специфичных для домена. + +Смарт-контракты — по крайней мере, в некоторой степени — удовлетворяют обоим требованиям. Например, небольшой размер контрактов Ethereum делает их подходящими для формальной верификации. Аналогичным образом, EVM следует простым правилам, что облегчает спецификацию и верификацию семантических свойств для программ, работающих в EVM. + +### Ускорение цикла разработки {#faster-development-cycle} + +Методы формальной верификации, такие как проверка моделей и символическое выполнение, как правило, более эффективны, чем обычный анализ кода смарт-контрактов (выполняемый во время тестирования или аудита). Это связано с тем, что формальная верификация использует символические значения для проверки утверждений («что, если пользователь попытается вывести _n_ эфира?»). в отличие от тестирования, которое использует конкретные значения («что, если пользователь попытается вывести 5 эфира?»). + +Символические входные переменные могут охватывать несколько классов конкретных значений, поэтому подходы формальной верификации обещают большее покрытие кода за более короткий промежуток времени. При эффективном использовании формальная верификация может ускорить цикл разработки для разработчиков. + +Формальная верификация также улучшает процесс создания децентрализованных приложений (dapps), уменьшая количество дорогостоящих ошибок проектирования. Обновление контрактов (где это возможно) для исправления уязвимостей требует значительной переработки кодовых баз и больших усилий на разработку. Формальная верификация может обнаружить многие ошибки в реализациях контрактов, которые могут ускользнуть от тестировщиков и аудиторов, и предоставляет широкие возможности для их исправления до развертывания контракта. + +## Недостатки формальной верификации {#drawbacks-of-formal-verification} + +### Стоимость ручного труда {#cost-of-manual-labor} + +Формальная верификация, особенно полуавтоматическая верификация, при которой человек направляет доказыватель для получения доказательств корректности, требует значительного ручного труда. Более того, создание формальной спецификации — это сложная деятельность, требующая высокого уровня квалификации. + +Эти факторы (усилия и квалификация) делают формальную верификацию более требовательной и дорогой по сравнению с обычными методами оценки корректности контрактов, такими как тестирование и аудит. Тем не менее, оплата стоимости полного аудита верификации является практичной, учитывая стоимость ошибок в реализациях смарт-контрактов. + +### Ложноотрицательные результаты {#false-negatives} + +Формальная верификация может только проверить, соответствует ли выполнение смарт-контракта формальной спецификации. Поэтому важно убедиться, что спецификация правильно описывает ожидаемое поведение смарт-контракта. + +Если спецификации написаны плохо, нарушения свойств, которые указывают на уязвимые выполнения, не могут быть обнаружены в ходе аудита формальной верификации. В этом случае разработчик может ошибочно предположить, что контракт не содержит ошибок. + +### Проблемы производительности {#performance-issues} + +Формальная верификация сталкивается с рядом проблем производительности. Например, проблемы взрыва состояний и путей, встречающиеся при проверке моделей и символическом выполнении соответственно, могут влиять на процедуры верификации. Кроме того, инструменты формальной верификации часто используют решатели SMT и другие решатели ограничений на своем базовом уровне, и эти решатели полагаются на вычислительно интенсивные процедуры. + +Кроме того, верификаторы программ не всегда могут определить, может ли свойство (описанное как логическая формула) быть выполнено или нет («[проблема разрешимости](https://en.wikipedia.org/wiki/Decision_problem)»), потому что программа может никогда не завершиться. Таким образом, может быть невозможно доказать некоторые свойства для контракта, даже если он хорошо специфицирован. + +## Инструменты формальной верификации для смарт-контрактов Ethereum {#formal-verification-tools} + +### Языки спецификаций для создания формальных спецификаций {#specification-languages} + +**Act**: __Act позволяет специфицировать обновления хранилища, предусловия/постусловия и инварианты контракта. Его набор инструментов также имеет бэкенды для доказательств, способные доказывать многие свойства с помощью Coq, решателей SMT или hevm.__ + +- [GitHub](https://github.com/ethereum/act) +- [Документация](https://github.com/argotorg/act) + +**Scribble** - __Scribble преобразует аннотации кода на языке спецификаций Scribble в конкретные утверждения, которые проверяют спецификацию.__ + +- [Документация](https://docs.scribble.codes/) + +**Dafny** - __Dafny — это готовый к верификации язык программирования, который использует высокоуровневые аннотации для рассуждений о корректности кода и ее доказательства.__ + +- [GitHub](https://github.com/dafny-lang/dafny) + +### Программные верификаторы для проверки корректности {#program-verifiers} + +**Certora Prover** - _Certora Prover — это автоматический инструмент формальной верификации для проверки корректности кода в смарт-контрактах. Спецификации пишутся на CVL (Certora Verification Language), а нарушения свойств обнаруживаются с помощью комбинации статического анализа и решения ограничений._ + +- [Веб-сайт](https://www.certora.com/) +- [Документация](https://docs.certora.com/en/latest/index.html) + +**Solidity SMTChecker** - __SMTChecker в Solidity — это встроенный инструмент проверки моделей, основанный на SMT (Satisfiability Modulo Theories) и решении Horn. Он подтверждает, соответствует ли исходный код контракта спецификациям во время компиляции, и статически проверяет нарушения свойств безопасности.__ + +- [GitHub](https://github.com/ethereum/solidity) + +**solc-verify** - __solc-verify — это расширенная версия компилятора Solidity, которая может выполнять автоматическую формальную верификацию кода Solidity с использованием аннотаций и модульной верификации программ.__ + +- [GitHub](https://github.com/SRI-CSL/solidity) + +**KEVM** - __KEVM — это формальная семантика виртуальной машины Ethereum (EVM), написанная на фреймворке K. KEVM является исполняемой и может доказывать определенные утверждения, связанные со свойствами, используя логику достижимости.__ + +- [GitHub](https://github.com/runtimeverification/evm-semantics) +- [Документация](https://jellopaper.org/) + +### Логические фреймворки для доказательства теорем {#theorem-provers} + +**Isabelle** - _Isabelle/HOL — это помощник для доказательств, который позволяет выражать математические формулы на формальном языке и предоставляет инструменты для доказательства этих формул. Основное применение — это формализация математических доказательств и, в частности, формальная верификация, которая включает в себя доказательство корректности компьютерного оборудования или программного обеспечения, а также доказательство свойств компьютерных языков и протоколов._ + +- [GitHub](https://github.com/isabelle-prover) +- [Документация](https://isabelle.in.tum.de/documentation.html) + +**Rocq** - _Rocq — это интерактивный доказыватель теорем, который позволяет определять программы с использованием теорем и интерактивно генерировать машино-проверяемые доказательства корректности._ + +- [GitHub](https://github.com/rocq-prover/rocq) +- [Документация](https://rocq-prover.org/docs) + +### Инструменты на основе символического выполнения для обнаружения уязвимых паттернов в смарт-контрактах {#symbolic-execution-tools} + +**Manticore** - __Инструмент для анализа байткода EVM на основе символического выполнения_._ + +- [GitHub](https://github.com/trailofbits/manticore) +- [Документация](https://github.com/trailofbits/manticore/wiki) + +**hevm** - __hevm — это движок символического выполнения и средство проверки эквивалентности для байткода EVM.__ + +- [GitHub](https://github.com/dapphub/dapptools/tree/master/src/hevm) + +**Mythril** - _Инструмент символического выполнения для обнаружения уязвимостей в смарт-контрактах Ethereum_ + +- [GitHub](https://github.com/ConsenSys/mythril-classic) +- [Документация](https://mythril-classic.readthedocs.io/en/develop/) + +## Дополнительные материалы {#further-reading} + +- [Как работает формальная верификация смарт-контрактов](https://runtimeverification.com/blog/how-formal-verification-of-smart-contracts-works/) +- [Как формальная верификация может обеспечить безупречность смарт-контрактов](https://media.consensys.net/how-formal-verification-can-ensure-flawless-smart-contracts-cbda8ad99bd1) +- [Обзор проектов формальной верификации в экосистеме Ethereum](https://github.com/leonardoalt/ethereum_formal_verification_overview) +- [Полная формальная верификация депозитного смарт-контракта Ethereum 2.0](https://runtimeverification.com/blog/end-to-end-formal-verification-of-ethereum-2-0-deposit-smart-contract/) +- [Формальная верификация самого популярного в мире смарт-контракта](https://www.zellic.io/blog/formal-verification-weth) +- [SMTChecker и формальная верификация](https://docs.soliditylang.org/en/v0.8.15/smtchecker.html) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/index.md b/public/content/translations/ru/developers/docs/smart-contracts/index.md new file mode 100644 index 00000000000..c46112d1a1e --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/index.md @@ -0,0 +1,112 @@ +--- +title: "Введение в умные контракты" +description: "Обзор смарт-контрактов с акцентом на их уникальные характеристики и ограничения." +lang: ru +--- + +## Что такое смарт-контракт? {#what-is-a-smart-contract} + +«Смарт-контракт» — это просто программа, работающая на блокчейне Ethereum. Это набор кода (его функции) и данных (его состояние), который находится по определенному адресу в цепочке блоков Ethereum. + +Смарт-контракты — это тип [аккаунта Ethereum](/developers/docs/accounts/). Это значит, что они имеют баланс и могут быть целью транзакций. Однако они не контролируются пользователем, вместо этого они развертываются в сети и работают в соответствии с программой. Учетные записи пользователей могут затем взаимодействовать со смарт-контрактом, отправляя транзакции, которые выполняют функцию, определенную в смарт-контракте. Смарт-контракты могут определять правила, как обычный контракт, и автоматически обеспечивать их соблюдение с помощью кода. Смарт-контракты нельзя просто так удалить, а взаимодействие с ними необратимо. + +## Предварительные условия {#prerequisites} + +Если вы только начинаете или ищете менее техническое введение, мы рекомендуем наше [введение в смарт-контракты](/smart-contracts/). + +Прежде чем погрузиться в мир смарт-контрактов, убедитесь, что вы ознакомились с [аккаунтами](/developers/docs/accounts/), [транзакциями](/developers/docs/transactions/) и [виртуальной машиной Ethereum](/developers/docs/evm/). + +## Цифровой торговый автомат {#a-digital-vending-machine} + +Возможно, лучшей метафорой для смарт-контракта является торговый автомат, как его описал [Ник Сабо](https://unenumerated.blogspot.com/). При правильном вводе гарантирован определенный результат. + +Чтобы купить закуску в торговом автомате: + +``` +money + snack selection = snack dispensed +``` + +Эта логика запрограммирована в торговый автомат. + +В смарт-контракт, как в торговый автомат, заложена логика. Вот простой пример того, как этот торговый автомат мог бы выглядеть, если его запустить с помощью Solidity: + +```solidity +pragma solidity 0.8.7; + +contract VendingMachine { + + // Объявление переменных состояния контракта + address public owner; + mapping (address => uint) public cupcakeBalances; + + // Когда контракт 'VendingMachine' развернут: + // 1. установить адрес развертывания как владельца контракта + // 2. установить баланс кексов развернутого смарт-контракта на 100 + constructor() { + owner = msg.sender; + cupcakeBalances[address(this)] = 100; + } + + // Разрешить владельцу увеличивать баланс кексов смарт-контракта + function refill(uint amount) public { + require(msg.sender == owner, "Только владелец может пополнять."); + cupcakeBalances[address(this)] += amount; + } + + // Разрешить любому покупать кексы + function purchase(uint amount) public payable { + require(msg.value >= amount * 1 ether, "Вы должны заплатить не менее 1 ETH за кекс"); + require(cupcakeBalances[address(this)] >= amount, "Недостаточно кексов на складе для совершения этой покупки"); + cupcakeBalances[address(this)] -= amount; + cupcakeBalances[msg.sender] += amount; + } +} +``` + +Подобно тому, как торговый автомат устраняет необходимость в продавце, смарт-контракты могут заменить посредников во многих отраслях. + +## Без разрешений {#permissionless} + +Кто угодно может написать смарт-контракт и развернуть его в сети. Вам просто нужно научиться программировать на [языке смарт-контрактов](/developers/docs/smart-contracts/languages/) и иметь достаточно ETH для развертывания вашего контракта. Развертывание смарт-контракта технически является транзакцией, поэтому вам нужно платить за [газ](/developers/docs/gas/) так же, как вы платите за газ для простого перевода ETH. Однако стоимость газа для развертывания контракта намного выше. + +В Ethereum есть удобные для разработчиков языки для написания смарт-контрактов: + +- Solidity +- Vyper + +[Подробнее о языках](/developers/docs/smart-contracts/languages/) + +Однако перед развертыванием они должны быть скомпилированы, чтобы виртуальная машина Ethereum могла интерпретировать и хранить контракт. [Подробнее о компиляции](/developers/docs/smart-contracts/compiling/) + +## Компонуемость {#composability} + +Смарт-контракты общедоступны в Ethereum и могут рассматриваться как открытые API. Это означает, что вы можете вызывать другие смарт-контракты в своем собственном смарт-контракте, чтобы значительно расширить его возможности. Контракты могут даже использовать другие контракты. + +Узнайте больше о [компонуемости смарт-контрактов](/developers/docs/smart-contracts/composability/). + +## Ограничения {#limitations} + +Смарт-контракты сами по себе не могут получать информацию о событиях из "реального мира", так как они не могут извлекать данные из оффчейн-источников. Это означает, что они не могут реагировать на события в реальном мире. Так задумано по проекту. Зависимость от внешней информации может поставить под угрозу консенсус, который важен для безопасности и децентрализации. + +Однако для блокчейн-приложений важно иметь возможность использовать оффчейн-данные. Решением являются [оракулы](/developers/docs/oracles/) — инструменты, которые принимают оффчейн-данные и делают их доступными для смарт-контрактов. + +Еще одним ограничением смарт-контрактов является максимальный размер контракта. Смарт-контракт может быть размером не более 24 Кб, иначе у него закончится газ. Эту проблему можно обойти, используя [The Diamond Pattern](https://eips.ethereum.org/EIPS/eip-2535). + +## Контракты с мультиподписью {#multisig} + +Мультиподписные контракты (контракты с несколькими подписями) - это учетные записи смарт-контрактов, которые для выполнения транзакции требуют несколько действительных подписей. Это очень полезно, чтобы избежать единичных точек отказа для контрактов, содержащих существенное количество Эфира или других токенов. Мультиподписи также разделяют ответственность за выполнение контракта и управление ключами между многими сторонами и предотвращают потерю одного закрытого ключа, ведущую к необратимой потере денежных средств. По этим причинам мультиподписные контракты могут быть использованы для простого управления DAO. Мультиподписи требуют N подписей из M возможных приемлемых подписей (где N ≤ M и M > 1) для выполнения. Часто используются `N = 3, M = 5` и `N = 4, M = 7`. Мультиподпись 4/7 требует четыре из семи возможных действительных подписей. Это значит, что денежные средства всё ещё можно восстановить, даже если три подписи потеряны. В этом случае это также означает, что большинство держателей ключей должны согласиться и подписать контракт, чтобы он выполнился. + +## Ресурсы по смарт-контрактам {#smart-contract-resources} + +**OpenZeppelin Contracts —** **_Библиотека для безопасной разработки смарт-контрактов._** + +- [openzeppelin.com/contracts/](https://openzeppelin.com/contracts/) +- [GitHub](https://github.com/OpenZeppelin/openzeppelin-contracts) +- [Форум сообщества](https://forum.openzeppelin.com/c/general/16) + +## Дополнительные материалы {#further-reading} + +- [Coinbase: Что такое смарт-контракт?](https://www.coinbase.com/learn/crypto-basics/what-is-a-smart-contract) +- [Chainlink: Что такое смарт-контракт?](https://chain.link/education/smart-contracts) +- [Видео: Смарт-контракты простыми словами](https://youtu.be/ZE2HxTmxfrI) +- [Cyfrin Updraft: Платформа для обучения и аудита в Web3](https://updraft.cyfrin.io) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/languages/index.md b/public/content/translations/ru/developers/docs/smart-contracts/languages/index.md new file mode 100644 index 00000000000..8f4aee5c134 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/languages/index.md @@ -0,0 +1,342 @@ +--- +title: "Языки программирования смарт-контрактов" +description: "Обзор и сравнение двух основных языков программирования смарт контрактов – Solidity и Vyper." +lang: ru +--- + +Отличительная черта Ethereum в том, что смарт-контракты могут быть написаны при помощи относительно удобных для разработчиков языков. Если у вас есть опыт работы с Python или любым [языком с фигурными скобками](https://wikipedia.org/wiki/List_of_programming_languages_by_type#Curly-bracket_languages), вы можете найти язык со знакомым синтаксисом. + +Два наиболее часто используемых и поддерживаемых языка это: + +- Solidity +- Vyper + +Remix IDE предоставляет комплексную среду разработки для создания и тестирования контрактов как на Solidity, так и на Vyper. [Попробуйте браузерную Remix IDE](https://remix.ethereum.org), чтобы начать программировать. + +Более опытные разработчики также могут использовать Yul, промежуточный язык для [виртуальной машины Ethereum](/developers/docs/evm/), или Yul+, расширение для Yul. + +Если вам любопытно и вы хотите помочь протестировать новые языки, которые все еще находятся в стадии активной разработки, вы можете поэкспериментировать с Fe, новым языком смарт-контрактов, который в настоящее время все еще находится в состоянии становления. + +## Предварительные условия {#prerequisites} + +Предыдущие знания языков программирования, особенно JavaScript или Python, могут помочь вам уловить разницу между языками смарт контрактов. Мы также рекомендуем вам ознакомится со смарт контрактами, как явлением, прежде чем углубляться в сравнение языков. [Введение в смарт-контракты](/developers/docs/smart-contracts/). + +## Solidity {#solidity} + +- Объектно-ориентированный высокоуровневый язык для реализации смарт-контрактов. +- Язык "фигурных скобок", на который большое влияние оказал C++. +- Статический (тип переменной известен во время компиляции). +- Поддерживает: + - Наследование (вы можете расширять другие контракты). + - Библиотеки (вы можете создавать повторно используемый код, который можно вызывать из разных контрактов как статические функции в статических классах в других языках программирования). + - Сложные типы, определяемые пользователем. + +### Важные ссылки {#important-links} + +- [Документация](https://docs.soliditylang.org/en/latest/) +- [Портал языка Solidity](https://soliditylang.org/) +- [Solidity by Example](https://docs.soliditylang.org/en/latest/solidity-by-example.html) +- [GitHub](https://github.com/ethereum/solidity/) +- [Чат Solidity в Gitter](https://gitter.im/ethereum/solidity) с мостом в [чат Solidity в Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im) +- [Шпаргалка](https://reference.auditless.com/cheatsheet) +- [Блог Solidity](https://blog.soliditylang.org/) +- [Solidity в Twitter](https://twitter.com/solidity_lang) + +### Пример контракта {#example-contract} + +```solidity +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >= 0.7.0; + +contract Coin { + // Ключевое слово "public" делает переменные + // доступными из других контрактов + address public minter; + mapping (address => uint) public balances; + + // События позволяют клиентам реагировать на определенные + // объявляемые вами изменения в контракте + event Sent(address from, address to, uint amount); + + // Код конструктора выполняется только при + // создании контракта + constructor() { + minter = msg.sender; + } + + // Отправляет определенное количество вновь созданных монет на адрес + // Может вызываться только создателем контракта + function mint(address receiver, uint amount) public { + require(msg.sender == minter); + require(amount < 1e60); + balances[receiver] += amount; + } + + // Отправляет определенное количество существующих монет + // от любого вызывающего на адрес + function send(address receiver, uint amount) public { + require(amount <= balances[msg.sender], "Недостаточный баланс."); + balances[msg.sender] -= amount; + balances[receiver] += amount; + emit Sent(msg.sender, receiver, amount); + } +} +``` + +Этот пример призван дать понимание о том, что из себя представляет синтаксис контракта на Solidity. Более подробное описание функций и переменных смотрите [в документации](https://docs.soliditylang.org/en/latest/contracts.html). + +## Vyper {#vyper} + +- Язык программирования, похожий на Python +- Сильная типизация +- Маленький и понятный код компилятора +- Эффективная генерация байткода +- Специально содержит меньше функционала, чем Solidity, с целью создания более безопасных контрактов, которые легче проверять. Vyper не поддерживает: + - Модификаторы + - Наследование + - Ассамблерное встраивание + - Перегрузку функций + - Перегрузку операторов + - Рекурсию + - Бесконечные циклы + - Бинарные фиксированные точки + +Для получения дополнительной информации [прочтите обоснование Vyper](https://vyper.readthedocs.io/en/latest/index.html). + +### Важные ссылки {#important-links-1} + +- [Документация](https://vyper.readthedocs.io) +- [Vyper by Example](https://vyper.readthedocs.io/en/latest/vyper-by-example.html) +- [More Vyper by Example](https://vyper-by-example.org/) +- [GitHub](https://github.com/vyperlang/vyper) +- [Чат сообщества Vyper в Discord](https://discord.gg/SdvKC79cJk) +- [Шпаргалка](https://reference.auditless.com/cheatsheet) +- [Платформы и инструменты для разработки смарт-контрактов для Vyper](/developers/docs/programming-languages/python/) +- [VyperPunk: научитесь защищать и взламывать смарт-контракты на Vyper](https://github.com/SupremacyTeam/VyperPunk) +- [Vyper Hub для разработки](https://github.com/zcor/vyper-dev) +- [Vyper: лучшие примеры смарт-контрактов](https://github.com/pynchmeister/vyper-greatest-hits/tree/main/contracts) +- [Awesome Vyper: избранные ресурсы](https://github.com/spadebuilders/awesome-vyper) + +### Пример {#example} + +```python +# Открытый аукцион + +# Параметры аукциона + +# Бенефициар получает деньги от участника, предложившего самую высокую цену + +beneficiary: public(address) +auctionStart: public(uint256) +auctionEnd: public(uint256) + +# Текущее состояние аукциона + +highestBidder: public(address) +highestBid: public(uint256) + +# Устанавливается в true в конце, запрещает любые изменения + +ended: public(bool) + +# Отслеживайте возвращенные ставки, чтобы мы могли следовать шаблону вывода средств + +pendingReturns: public(HashMap[address, uint256]) + +# Создайте простой аукцион с `_bidding_time` + +# секундами времени для торгов от имени + +# адреса бенефициара `_beneficiary`. + +@external +def __init__(_beneficiary: address, _bidding_time: uint256): + self.beneficiary = _beneficiary + self.auctionStart = block.timestamp + self.auctionEnd = self.auctionStart + _bidding_time + +# Сделайте ставку на аукционе на сумму, отправленную + +# вместе с этой транзакцией. + +# Сумма будет возвращена, только если + +# аукцион не выигран. + +@external +@payable +def bid(): + # Проверьте, закончился ли период торгов. + assert block.timestamp < self.auctionEnd + # Проверьте, достаточно ли высока ставка + assert msg.value > self.highestBid + # Отследите возврат средств для предыдущего участника, предложившего самую высокую цену + self.pendingReturns[self.highestBidder] += self.highestBid + # Отследите новую высокую ставку + self.highestBidder = msg.sender + self.highestBid = msg.value + +# Выведите ранее возвращенную ставку. Шаблон вывода средств + +# используется здесь, чтобы избежать проблемы с безопасностью. Если бы возмещения были напрямую + +# отправлены как часть bid(), вредоносный контракт для торгов мог бы заблокировать + +# эти возвраты и, таким образом, заблокировать поступление новых более высоких ставок. + +@external +def withdraw(): + pending_amount: uint256 = self.pendingReturns[msg.sender] + self.pendingReturns[msg.sender] = 0 + send(msg.sender, pending_amount) + +# Завершите аукцион и отправьте самую высокую ставку + +# бенефициару. + +@external +def endAuction(): + # Рекомендуется структурировать функции, которые взаимодействуют + # с другими контрактами (т. е. вызывают функции или отправляют эфир) + # в три этапа: + # 1. проверка условий + # 2. выполнение действий (потенциально изменяющих условия) + # 3. взаимодействие с другими контрактами + # Если эти этапы перепутаны, другой контракт может вызвать + # обратно текущий контракт и изменить состояние или вызвать + # многократное выполнение эффектов (выплата эфира). + # Если функции, вызываемые внутри, включают взаимодействие с внешними + # контрактами, их также следует рассматривать как взаимодействие с + # внешними контрактами. + + # 1. Условия + # Проверьте, достигнуто ли время окончания аукциона + assert block.timestamp >= self.auctionEnd + # Проверьте, не была ли эта функция уже вызвана + assert not self.ended + + # 2. Эффекты + self.ended = True + + # 3. Взаимодействие + send(self.beneficiary, self.highestBid) +``` + +Этот пример должен дать вам представление о синтаксисе контракта Vyper. Более подробное описание функций и переменных смотрите [в документации](https://vyper.readthedocs.io/en/latest/vyper-by-example.html#simple-open-auction). + +## Yul и Yul+ {#yul} + +Если вы новичок в Ethereum и еще не программировали на языках смарт-контрактов, мы рекомендуем начать с Solidity или Vyper. Обращайтесь к Yul или Yul+ только после того, как ознакомитесь с передовыми методами обеспечения безопасности смарт-контрактов и особенностями работы с EVM. + +**Yul** + +- Промежуточный язык для Ethereum. +- Поддерживает [EVM](/developers/docs/evm) и [Ewasm](https://github.com/ewasm), WebAssembly в стиле Ethereum, и разработан как пригодный общий знаменатель для обеих платформ. +- Хорошо подходит для этапов высокоуровневой оптимизации, которые могут в равной степени принести пользу как платформе EVM, так и Ewasm. + +**Yul+** + +- Низкоуровневое, высокоэффективное расширение для Yul. +- Первоначально был разработан для контракта [оптимистического ролл-апа](/developers/docs/scaling/optimistic-rollups/). +- Yul+ можно рассматривать как экспериментальное предложение по обновлению Yul, добавляющее в него новые функции. + +### Важные ссылки {#important-links-2} + +- [Документация Yul](https://docs.soliditylang.org/en/latest/yul.html) +- [Документация Yul+](https://github.com/fuellabs/yulp) +- [Вводная статья о Yul+](https://medium.com/@fuellabs/introducing-yul-a-new-low-level-language-for-ethereum-aa64ce89512f) + +### Пример контракта {#example-contract-2} + +На этом простом примере реализуем функцию power. Его можно скомпилировать с помощью `solc --strict-assembly --bin input.yul`. Пример должен быть сохранен в файле input.yul. + +``` +{ + function power(base, exponent) -> result + { + switch exponent + case 0 { result := 1 } + case 1 { result := base } + default + { + result := power(mul(base, base), div(exponent, 2)) + if mod(exponent, 2) { result := mul(base, result) } + } + } + let res := power(calldataload(0), calldataload(32)) + mstore(0, res) + return(0, 32) +} +``` + +Если у вас уже есть большой опыт работы со смарт-контрактами, полную реализацию ERC20 на Yul можно найти [здесь](https://solidity.readthedocs.io/en/latest/yul.html#complete-erc20-example). + +## Fe {#fe} + +- Статически типизированный язык для виртуальной машины Ethereum (EVM). +- Вдохновлен Python и Rust. +- Стремится быть простым в освоении — даже для разработчиков, которые плохо знакомы с экосистемой Ethereum. +- Разработка Fe все еще находится на ранней стадии, альфа-версия языка была выпущена в январе 2021 года. + +### Важные ссылки {#important-links-3} + +- [GitHub](https://github.com/ethereum/fe) +- [Анонс Fe](https://snakecharmers.ethereum.org/fe-a-new-language-for-the-ethereum-ecosystem/) +- [Дорожная карта Fe на 2021 год](https://notes.ethereum.org/LVhaTF30SJOpkbG1iVw1jg) +- [Чат Fe в Discord](https://discord.com/invite/ywpkAXFjZH) +- [Fe в Twitter](https://twitter.com/official_fe) + +### Пример контракта {#example-contract-3} + +Ниже приведен простой контракт, реализованный в Fe. + +``` +type BookMsg = bytes[100] + +contract GuestBook: + pub guest_book: map + + event Signed: + book_msg: BookMsg + + pub def sign(book_msg: BookMsg): + self.guest_book[msg.sender] = book_msg + + emit Signed(book_msg=book_msg) + + pub def get_msg(addr: address) -> BookMsg: + return self.guest_book[addr].to_mem() + +``` + +## Как выбрать {#how-to-choose} + +Как и с другими языками программирования, это в большинстве своем выбор правильного инструмента для конкретной работы, так же, как и в личных предпочтениях. + +Вот несколько фактов для раздумий, если вы ещё не пробовали ни один из языков: + +### Какие преимущества у Solidity? {#solidity-advantages} + +- Если вы новичок, есть множество материалов и инструментов обучения. Подробнее об этом можно узнать в разделе [Учитесь, создавая код](/developers/learning-tools/). +- Доступны удобные инструменты для разработчиков. +- У Solidity большое сообщество разработчиков, что означает быстрый поиск ответов на ваши вопросы. + +### Какие преимущества у Vyper? {#vyper-advatages} + +- Отличный способ начать для Python разработчиков, которые хотят писать смарт контракты. +- У Vyper меньшее количество функционала, что делает его превосходным инструментом для быстрой проверки идей. +- Цель Vyper быть легким для аудитов и максимально читабельным для людей. + +### Какие преимущества у Yul и Yul+? {#yul-advantages} + +- Простой и функциональный низкоуровневый язык. +- Позволяет максимально приблизиться к функциям EVM, что может помочь оптимизировать затраты газа в ваших контрактах. + +## Сравнение языков {#language-comparisons} + +Для сравнения базового синтаксиса, жизненного цикла контракта, интерфейсов, операторов, структур данных, функций, потока управления и многого другого ознакомьтесь с этой [шпаргалкой от Auditless](https://reference.auditless.com/cheatsheet/) + +## Дополнительные материалы {#further-reading} + +- [Библиотека контрактов Solidity от OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/) +- [Solidity by Example](https://solidity-by-example.org) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/libraries/index.md b/public/content/translations/ru/developers/docs/smart-contracts/libraries/index.md new file mode 100644 index 00000000000..e31db114833 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/libraries/index.md @@ -0,0 +1,117 @@ +--- +title: "Библиотеки смарт-контрактов" +description: "Откройте для себя многократно используемые библиотеки смарт-контрактов и строительные блоки для ускорения ваших проектов по разработке Ethereum." +lang: ru +--- + +Вам не нужно писать каждый смарт-контракт в своем проекте с нуля. Доступно множество библиотек смарт-контрактов с открытым исходным кодом, которые предоставляют многократно используемые строительные блоки для вашего проекта, которые могут избавить вас от необходимости изобретать колесо. + +## Предварительные условия {#prerequisites} + +Прежде чем переходить к библиотекам смарт-контрактов, неплохо было бы хорошо понять структуру смарт-контракта. Перейдите к [анатомии умного контракта](/developers/docs/smart-contracts/anatomy/), если вы еще этого не сделали. + +## Что находится в библиотеке {#whats-in-a-library} + +Обычно в библиотеках смарт-контрактов можно найти два типа строительных блоков: многоразовые варианты поведения, которые вы можете добавить в свои контракты, и реализации различных стандартов. + +### Поведения {#behaviors} + +При написании смарт-контрактов вы, скорее всего, будете снова и снова писать похожие шаблоны, например, назначать адрес _администратора_ для выполнения защищенных операций в контракте или добавлять кнопку экстренной _паузы_ в случае непредвиденной проблемы. + +Библиотеки смарт-контрактов обычно предоставляют повторно используемые реализации такого поведения в виде [библиотек](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#libraries) или через [наследование](https://solidity.readthedocs.io/en/v0.7.2/contracts.html#inheritance) в Solidity. + +В качестве примера ниже приведена упрощенная версия [контракта `Ownable`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.2.0/contracts/access/Ownable.sol) из [библиотеки контрактов OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts), которая назначает адрес в качестве владельца контракта и предоставляет модификатор для ограничения доступа к методу только этому владельцу. + +```solidity +contract Ownable { + address public owner; + + constructor() internal { + owner = msg.sender; + } + + modifier onlyOwner() { + require(owner == msg.sender, "Ownable: caller is not the owner"); + _; + } +} +``` + +Чтобы использовать такой строительный блок в своем контракте, вам нужно сначала импортировать его, а затем расширить его в своих собственных контрактах. Это позволит вам использовать модификатор, предоставляемый базовым контрактом `Ownable`, для защиты ваших собственных функций. + +```solidity +import ".../Ownable.sol"; // Path to the imported library + +contract MyContract is Ownable { + // The following function can only be called by the owner + function secured() onlyOwner public { + msg.sender.transfer(1 ether); + } +} +``` + +Другим популярным примером является [SafeMath](https://docs.openzeppelin.com/contracts/3.x/utilities#math) или [DsMath](https://dappsys.readthedocs.io/en/latest/ds_math.html). Это библиотеки (в отличие от базовых контрактов), которые предоставляют арифметические функции с проверками переполнения, которые не предусмотрены языком. Рекомендуется использовать любую из этих библиотек вместо собственных арифметических операций для защиты вашего контракта от переполнений, которые могут иметь катастрофические последствия! + +### Стандарты {#standards} + +Для обеспечения [компонуемости и функциональной совместимости](/developers/docs/smart-contracts/composability/) сообщество Ethereum определило несколько стандартов в виде **ERC**. Вы можете прочитать о них подробнее в разделе [стандартов](/developers/docs/standards/). + +При включении ERC в свои контракты рекомендуется искать стандартные реализации, а не пытаться развернуть свои собственные. Многие библиотеки смарт-контрактов включают реализации наиболее популярных ERC. Например, повсеместно распространенный [стандарт взаимозаменяемых токенов ERC20](/developers/tutorials/understand-the-erc-20-token-smart-contract/) можно найти в [HQ20](https://github.com/HQ20/contracts/blob/master/contracts/token/README.md), [DappSys](https://github.com/dapphub/ds-token/) и [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc20). Кроме того, некоторые ERC также предоставляют канонические реализации как часть самого ERC. + +Стоит отметить, что некоторые ERC не являются автономными, а являются дополнениями к другим ERC. Например, [ERC2612](https://eips.ethereum.org/EIPS/eip-2612) добавляет расширение к ERC20 для повышения удобства его использования. + +## Как добавить библиотеку {#how-to} + +Всегда обращайтесь к документации библиотеки, которую вы включаете, для получения конкретных инструкций о том, как включить ее в свой проект. Несколько библиотек контрактов Solidity упакованы с использованием `npm`, так что вы можете просто установить их командой `npm install`. Большинство инструментов для [компиляции](/developers/docs/smart-contracts/compiling/) контрактов будут искать в вашем каталоге `node_modules` библиотеки смарт-контрактов, поэтому вы можете сделать следующее: + +```solidity +// This will load the @openzeppelin/contracts library from your node_modules +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +contract MyNFT is ERC721 { + constructor() ERC721("MyNFT", "MNFT") public { } +} +``` + +Независимо от используемого вами метода, при подключении библиотеки всегда следите за версией [языка](/developers/docs/smart-contracts/languages/). Например, вы не можете использовать библиотеку для Solidity 0.6, если вы пишете свои контракты на Solidity 0.5. + +## Когда использовать {#when-to-use} + +Использование библиотеки смарт-контрактов для вашего проекта имеет несколько преимуществ. Прежде всего, это экономит ваше время, предоставляя вам готовые к использованию строительные блоки, которые вы можете включить в свою систему, вместо того, чтобы кодировать их самостоятельно. + +Безопасность также является большим плюсом. Библиотеки смарт-контрактов с открытым исходным кодом также часто подвергаются тщательной проверке. Поскольку от них зависят многие проекты, у сообщества есть сильный стимул держать их под постоянным контролем. Гораздо чаще ошибки обнаруживаются в коде приложения, чем в многократно используемых библиотеках контрактов. Некоторые библиотеки также проходят [внешний аудит](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/audits) для дополнительной безопасности. + +Однако использование библиотек смарт-контрактов сопряжено с риском включения кода, с которым вы не знакомы, в свой проект. Заманчиво импортировать контракт и включить его непосредственно в ваш проект, но без хорошего понимания того, что делает этот контракт, вы можете случайно создать проблему в своей системе из-за неожиданного поведения. Всегда обязательно читайте документацию по импортируемому коду, а затем просматривайте сам код, прежде чем делать его частью своего проекта! + +Наконец, при принятии решения о включении библиотеки следует учитывать ее общее использование. Широко распространенный метод имеет то преимущество, что у него более широкое сообщество и больше глаз, которые следят за его проблемами. Безопасность должна быть вашим основным приоритетом при создании смарт-контрактов! + +## Связанные инструменты {#related-tools} + +**OpenZeppelin Contracts -** **_Самая популярная библиотека для безопасной разработки смарт-контрактов._** + +- [Документация](https://docs.openzeppelin.com/contracts/) +- [GitHub](https://github.com/OpenZeppelin/openzeppelin-contracts) +- [Форум сообщества](https://forum.openzeppelin.com/c/general/16) + +**DappSys -** **_Безопасные, простые, гибкие строительные блоки для смарт-контрактов._** + +- [Документация](https://dappsys.readthedocs.io/) +- [GitHub](https://github.com/dapphub/dappsys) + +**HQ20 -** **_Проект Solidity с контрактами, библиотеками и примерами, которые помогут вам создавать полнофункциональные распределенные приложения для реального мира._** + +- [GitHub](https://github.com/HQ20/contracts) + +**thirdweb Solidity SDK -** **_Предоставляет инструменты, необходимые для эффективной разработки пользовательских смарт-контрактов_** + +- [Документация](https://portal.thirdweb.com/contracts/build/overview) +- [GitHub](https://github.com/thirdweb-dev/contracts) + +## Связанные руководства {#related-tutorials} + +- [Рекомендации по безопасности для разработчиков Ethereum](/developers/docs/smart-contracts/security/) _– руководство по вопросам безопасности при создании смарт-контрактов, включая использование библиотек._ +- [Принципы работы смарт-контракта токена ERC-20](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _– руководство по стандарту ERC20, предоставляемое несколькими библиотеками._ + +## Дополнительные материалы {#further-reading} + +_Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!_ diff --git a/public/content/translations/ru/developers/docs/smart-contracts/naming/index.md b/public/content/translations/ru/developers/docs/smart-contracts/naming/index.md new file mode 100644 index 00000000000..9fa885a5021 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/naming/index.md @@ -0,0 +1,101 @@ +--- +title: "Присвоение имен умным контрактам" +description: "Лучшие практики по присвоению имен умным контрактам Ethereum с помощью ENS" +lang: ru +--- + +Умные контракты являются краеугольным камнем децентрализованной инфраструктуры Ethereum, обеспечивая работу автономных приложений и протоколов. Но даже по мере развития возможностей контрактов пользователи и разработчики по-прежнему полагаются на необработанные шестнадцатеричные адреса для идентификации и ссылки на эти контракты. + +Присвоение имен умным контрактам с помощью [Службы имен Ethereum (ENS)](https://ens.domains/) улучшает пользовательский опыт за счет устранения шестнадцатеричных адресов контрактов и снижает риск атак, таких как отравление адресов и спуфинг-атаки. В этом руководстве объясняется, почему важно давать имена умным контрактам, как это можно реализовать, а также какие инструменты, такие как [Enscribe](https://www.enscribe.xyz), доступны для упрощения процесса и помощи разработчикам в освоении этой практики. + +## Зачем давать имена умным контрактам? {#why-name-contracts} + +### Человекочитаемые идентификаторы {#human-readable-identifiers} + +Вместо взаимодействия с непрозрачными адресами контрактов, такими как `0x8f8e...f9e3`, разработчики и пользователи могут использовать человекочитаемые имена, например `v2.myapp.eth`. Это упрощает взаимодействие с умными контрактами. + +Это стало возможным благодаря [Службе имен Ethereum](https://ens.domains/), которая предоставляет децентрализованную службу имен для адресов Ethereum. Это аналогично тому, как система доменных имен (DNS) позволяет пользователям Интернета получать доступ к сетевым адресам, используя такое имя, как ethereum.org, а не IP-адрес, например `104.18.176.152`. + +### Повышенная безопасность и доверие {#improved-security-and-trust} + +Именованные контракты помогают сократить количество случайных транзакций на неправильный адрес. Они также помогают пользователям идентифицировать контракты, привязанные к определенным приложениям или брендам. Это добавляет уровень репутационного доверия, особенно когда имена привязаны к известным родительским доменам, таким как `uniswap.eth`. + +Из-за 42-символьной длины адреса Ethereum пользователям очень трудно выявить небольшие изменения в адресах, в которых было изменено несколько символов. Например, такой адрес, как `0x58068646C148E313CB414E85d2Fe89dDc3426870`, обычно сокращается до `0x580...870` в пользовательских приложениях, таких как кошельки. Пользователь вряд ли заметит вредоносный адрес, в котором изменена пара символов. + +Этот тип техники используется в атаках с подменой и отравлением адресов, когда пользователей заставляют поверить, что они взаимодействуют с правильным адресом или отправляют средства на него, тогда как на самом деле адрес просто напоминает правильный, но не является им. + +Имена ENS для кошельков и контрактов защищают от таких атак. Подобно атакам с подменой DNS, атаки с подменой ENS также могут иметь место, однако пользователь с большей вероятностью заметит опечатку в имени ENS, чем небольшое изменение в шестнадцатеричном адресе. + +### Улучшенный UX для кошельков и обозревателей {#better-ux} + +Когда умный контракт настроен с именем ENS, такие приложения, как кошельки и обозреватели блокчейна, могут отображать имена ENS для умных контрактов вместо шестнадцатеричных адресов. Это обеспечивает значительное улучшение пользовательского опыта (UX) для пользователей. + +Например, при взаимодействии с таким приложением, как Uniswap, пользователи обычно видят, что приложение, с которым они взаимодействуют, размещено на веб-сайте `uniswap.org`, но им будет представлен шестнадцатеричный адрес контракта, если Uniswap не присвоил своим умным контрактам имена с помощью ENS. Если контракту присвоено имя, вместо этого они могут увидеть `v4.contracts.uniswap.eth`, что гораздо полезнее. + +## Присвоение имени при развертывании и после развертывания {#when-to-name} + +Есть два момента, когда умным контрактам можно присвоить имя: + +- **Во время развертывания**: присвоение имени ENS контракту по мере его развертывания. +- **После развертывания**: сопоставление существующего адреса контракта с новым именем ENS. + +Оба подхода основаны на наличии у владельца или менеджера доступа к домену ENS, чтобы они могли создавать и устанавливать записи ENS. + +## Как работает присвоение имен ENS для контрактов {#how-ens-naming-works} + +Имена ENS хранятся в сети и разрешаются в адреса Ethereum через преобразователи ENS. Чтобы присвоить имя умному контракту: + +1. Зарегистрируйте или управляйте родительским доменом ENS (например, `myapp.eth`) +2. Создайте субдомен (например, `v1.myapp.eth`) +3. Установите запись `address` субдомена на адрес контракта +4. Установите обратную запись контракта в ENS, чтобы имя можно было найти по его адресу + +Имена ENS иерархичны и поддерживают неограниченное количество суб-имен. Установка этих записей обычно включает взаимодействие с реестром ENS и публичными контрактами-преобразователями. + +## Инструменты для присвоения имен контрактам {#tools} + +Существует два подхода к присвоению имен умным контрактам. Либо с помощью [приложения ENS](https://app.ens.domains) с некоторыми ручными шагами, либо с помощью [Enscribe](https://www.enscribe.xyz). Они описаны ниже. + +### Ручная настройка ENS {#manual-ens-setup} + +С помощью [приложения ENS](https://app.ens.domains/) разработчики могут вручную создавать суб-имена и устанавливать записи прямых адресов. Однако они не могут установить основное имя для умного контракта, установив обратную запись для имени через приложение ENS. Необходимо выполнить ручные шаги, которые описаны в [документации ENS](https://docs.ens.domains/web/naming-contracts/). + +### Enscribe {#enscribe} + +[Enscribe](https://www.enscribe.xyz) упрощает присвоение имен умным контрактам с помощью ENS и повышает доверие пользователей к умным контрактам. Он предоставляет: + +- **Атомарное развертывание и присвоение имени**: присвоение имени ENS при развертывании нового контракта +- **Присвоение имен после развертывания**: прикрепление имен к уже развернутым контрактам +- **Поддержка нескольких сетей**: работает в сетях Ethereum и L2, где поддерживается ENS +- **Данные верификации контракта**: включают данные верификации контракта, полученные из нескольких источников, для повышения доверия пользователей + +Enscribe поддерживает имена ENS, предоставленные пользователями, или собственные домены, если у пользователя нет имени ENS. + +Вы можете получить доступ к [приложению Enscribe](https://app.enscribe.xyz), чтобы начать присваивать имена и просматривать умные контракты. + +## Лучшие практики {#best-practices} + +- **Используйте четкие, версионированные имена**, такие как `v1.myapp.eth`, чтобы сделать обновления контрактов прозрачными +- **Устанавливайте обратные записи**, чтобы связать контракты с именами ENS для видимости в таких приложениях, как кошельки и обозреватели блокчейна. +- **Внимательно следите за сроками действия**, если хотите предотвратить случайную смену владельца +- **Проверяйте источник контракта**, чтобы пользователи могли доверять, что именованный контракт ведет себя так, как ожидалось + +## Риски {#risks} + +Присвоение имен умным контрактам дает значительные преимущества пользователям Ethereum, однако владельцы доменов ENS должны быть бдительны в отношении их управления. Заметные риски включают: + +- **Истечение срока действия**: так же, как и имена DNS, регистрация имен ENS имеет конечный срок действия. Поэтому жизненно важно, чтобы владельцы отслеживали сроки действия своих доменов и продлевали их заблаговременно до истечения срока. Как приложение ENS, так и Enscribe предоставляют визуальные индикаторы для владельцев доменов при приближении срока истечения. +- **Смена владельца**: записи ENS представлены в виде NFT в Ethereum, где владелец определенного домена `.eth` владеет соответствующим NFT. Следовательно, если другой аккаунт завладеет этим NFT, новый владелец сможет изменять любые записи ENS по своему усмотрению. + +Для снижения таких рисков аккаунт владельца доменов второго уровня (2LD) `.eth` должен быть защищен с помощью кошелька с мультиподписью, а для управления именами контрактов должны создаваться субдомены. Таким образом, в случае любых случайных или злонамеренных изменений в праве собственности на уровне субдомена, они могут быть отменены владельцем 2LD. + +## Будущее присвоения имен контрактам {#future} + +Присвоение имен контрактам становится лучшей практикой для разработки децентрализованных приложений, подобно тому, как доменные имена заменили IP-адреса в Интернете. По мере того, как все больше инфраструктурных элементов, таких как кошельки, обозреватели и панели мониторинга, интегрируют разрешение ENS для контрактов, именованные контракты повысят безопасность и уменьшат количество ошибок во всей экосистеме. + +Делая умные контракты более легкими для распознавания и понимания, присвоение имен помогает сократить разрыв между пользователями и приложениями на Ethereum, улучшая как безопасность, так и UX для пользователей. + +## Дополнительные материалы {#further-reading} + +- [Присвоение имен умным контрактам с помощью ENS](https://docs.ens.domains/web/naming-contracts/) +- [Присвоение имен умным контрактам с помощью Enscribe](https://www.enscribe.xyz/docs). diff --git a/public/content/translations/ru/developers/docs/smart-contracts/security/index.md b/public/content/translations/ru/developers/docs/smart-contracts/security/index.md new file mode 100644 index 00000000000..0ad475b4d1d --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/security/index.md @@ -0,0 +1,576 @@ +--- +title: "Безопасность умных контрактов" +description: "Обзор руководящих принципов по созданию безопасных смарт-контрактов с помощью технологии Ethereum" +lang: ru +--- + +Умные контракты чрезвычайно гибки и способны контролировать большие объемы ценностей и данных, выполняя при этом неизменяемую логику на основе кода, развернутого в блокчейне. Это привело к созданию активной экосистемы децентрализованных приложений, не требующих доверия, которые предоставляют множество преимуществ по сравнению с устаревшими системами. Они также предоставляют возможности для атакующих, которые хотят получить прибыль, используя уязвимости в умных контрактах. + +Публичные блокчейны, такие как Ethereum, еще больше усложняют задачу обеспечения безопасности умных контрактов. Развернутый код контракта _обычно_ не может быть изменен для исправления недостатков безопасности, в то время как активы, украденные из умных контрактов, чрезвычайно трудно отследить и в основном невозможно восстановить из-за их неизменности. + +Хотя цифры разнятся, по оценкам, общая сумма украденных или потерянных ценностей из-за дефектов безопасности в умных контрактах легко превышает 1 миллиард долларов. Сюда входят громкие инциденты, такие как [взлом DAO](https://hackingdistributed.com/2016/06/18/analysis-of-the-dao-exploit/) (украдено 3,6 млн ETH, что по сегодняшним ценам составляет более 1 млрд долларов), [взлом кошелька с мультиподписью Parity](https://www.coindesk.com/markets/2017/07/19/30-million-ether-reported-stolen-due-to-parity-wallet-breach) (хакеры похитили 30 млн долларов) и [проблема с замороженным кошельком Parity](https://www.theguardian.com/technology/2017/nov/08/cryptocurrency-300m-dollars-stolen-bug-ether) (более 300 млн долларов в ETH заблокированы навсегда). + +Вышеупомянутые проблемы обязывают разработчиков прикладывать усилия для создания безопасных, надежных и отказоустойчивых умных контрактов. Безопасность умных контрактов — это серьезное дело, и каждому разработчику будет полезно его изучить. В этом руководстве будут рассмотрены аспекты безопасности для разработчиков Ethereum и изучены ресурсы для повышения безопасности умных контрактов. + +## Предварительные условия {#prerequisites} + +Прежде чем приступать к изучению вопросов безопасности, убедитесь, что вы знакомы с [основами разработки умных контрактов](/developers/docs/smart-contracts/). + +## Руководство по созданию безопасных умных контрактов Ethereum {#smart-contract-security-guidelines} + +### 1. Разработка надлежащих средств контроля доступа {#design-proper-access-controls} + +В умных контрактах функции, помеченные как `public` или `external`, могут вызываться любыми внешними аккаунтами (EOA) или аккаунтами контрактов. Указание публичной видимости для функций необходимо, если вы хотите, чтобы другие могли взаимодействовать с вашим контрактом. Однако функции, помеченные как `private`, могут вызываться только функциями внутри умного контракта, а не внешними аккаунтами. Предоставление каждому участнику сети доступа к функциям контракта может вызвать проблемы, особенно если это означает, что кто угодно может выполнять конфиденциальные операции (например, чеканку новых токенов). + +Чтобы предотвратить несанкционированное использование функций умного контракта, необходимо внедрить безопасные средства контроля доступа. Механизмы контроля доступа ограничивают возможность использования определенных функций в умном контракте только для утвержденных субъектов, таких как аккаунты, ответственные за управление контрактом. Патерн **Ownable** и **управление на основе ролей** — это два полезных патерна для реализации контроля доступа в умных контрактах: + +#### Патерн Ownable {#ownable-pattern} + +В патерне Ownable во время создания контракта один адрес назначается его «владельцем». Защищенным функциям присваивается модификатор `OnlyOwner`, который гарантирует, что контракт аутентифицирует личность вызывающего адреса перед выполнением функции. Вызовы защищенных функций с адресов, отличных от адреса владельца контракта, всегда отменяются, что предотвращает нежелательный доступ. + +#### Управление доступом на основе ролей {#role-based-access-control} + +Регистрация одного адреса в качестве `Owner` (владельца) в умном контракте создает риск централизации и представляет собой единую точку отказа. Если ключи аккаунта владельца будут скомпрометированы, атакующие смогут атаковать принадлежащий ему контракт. Вот почему использование патерна управления доступом на основе ролей с несколькими административными аккаунтами может быть лучшим вариантом. + +При управлении доступом на основе ролей доступ к конфиденциальным функциям распределяется между набором доверенных участников. Например, один аккаунт может отвечать за чеканку токенов, а другой — за выполнение обновлений или приостановку контракта. Такая децентрализация контроля доступа устраняет единые точки отказа и снижает требования к доверию для пользователей. + +##### Использование кошельков с мультиподписью + +Другой подход к реализации безопасного контроля доступа — использование [аккаунта с мультиподписью](/developers/docs/smart-contracts/#multisig) для управления контрактом. В отличие от обычного EOA, аккаунты с мультиподписью принадлежат нескольким субъектам и требуют для выполнения транзакций подписи от минимального числа аккаунтов, например, 3 из 5. + +Использование мультиподписи для контроля доступа добавляет дополнительный уровень безопасности, поскольку действия с целевым контрактом требуют согласия нескольких сторон. Это особенно полезно, если необходимо использовать патерн Ownable, поскольку это затрудняет для атакующего или недобросовестного инсайдера манипулирование конфиденциальными функциями контракта в злонамеренных целях. + +### 2. Используйте операторы require(), assert() и revert() для защиты операций контракта {#use-require-assert-revert} + +Как уже упоминалось, любой может вызывать публичные функции в вашем умном контракте после его развертывания в блокчейне. Поскольку вы не можете заранее знать, как внешние аккаунты будут взаимодействовать с контрактом, перед развертыванием идеально реализовать внутренние меры защиты от проблемных операций. Вы можете обеспечить правильное поведение в умных контрактах, используя операторы `require()`, `assert()` и `revert()` для вызова исключений и отмены изменений состояния, если выполнение не удовлетворяет определенным требованиям. + +**`require()`**: `require` определяется в начале функций и гарантирует, что предварительно определенные условия выполнены до того, как будет выполнена вызываемая функция. Оператор `require` может использоваться для проверки вводимых пользователем данных, проверки переменных состояния или аутентификации личности вызывающего аккаунта перед продолжением выполнения функции. + +**`assert()`**: `assert()` используется для обнаружения внутренних ошибок и проверки нарушений «инвариантов» в вашем коде. Инвариант — это логическое утверждение о состоянии контракта, которое должно оставаться истинным для всех выполнений функций. Инвариантным примером является максимальное общее предложение или баланс токенового контракта. Использование `assert()` гарантирует, что ваш контракт никогда не перейдет в уязвимое состояние, а если это произойдет, все изменения переменных состояния будут отменены. + +**`revert()`**: `revert()` может использоваться в операторе if-else, который вызывает исключение, если требуемое условие не выполняется. В приведенном ниже примере контракта для защиты выполнения функций используется `revert()`: + +``` +pragma solidity ^0.8.4; + +contract VendingMachine { + address owner; + error Unauthorized(); + function buy(uint amount) public payable { + if (amount > msg.value / 2 ether) + revert("Предоставлено недостаточно Ether."); + // Выполнение покупки. + } + function withdraw() public { + if (msg.sender != owner) + revert Unauthorized(); + + payable(msg.sender).transfer(address(this).balance); + } +} +``` + +### 3. Тестируйте умные контракты и проверяйте правильность кода {#test-smart-contracts-and-verify-code-correctness} + +Неизменность кода, работающего в [виртуальной машине Ethereum](/developers/docs/evm/), означает, что умные контракты требуют более высокого уровня оценки качества на этапе разработки. Тщательное тестирование вашего контракта и отслеживание любых непредвиденных результатов значительно повысит безопасность и защитит ваших пользователей в долгосрочной перспективе. + +Обычный метод — это написание небольших модульных тестов с использованием фиктивных данных, которые контракт, как ожидается, будет получать от пользователей. [Модульное тестирование](/developers/docs/smart-contracts/testing/#unit-testing) хорошо подходит для тестирования функциональности определенных функций и обеспечения того, чтобы умный контракт работал так, как ожидается. + +К сожалению, модульное тестирование минимально эффективно для повышения безопасности умных контрактов при его изолированном использовании. Модульный тест может доказать, что функция выполняется правильно для фиктивных данных, но модульные тесты эффективны лишь настолько, насколько эффективны написанные тесты. Это затрудняет обнаружение пропущенных пограничных случаев и уязвимостей, которые могут нарушить безопасность вашего умного контракта. + +Лучший подход — это сочетание модульного тестирования с тестированием на основе свойств, выполняемым с использованием [статического и динамического анализа](/developers/docs/smart-contracts/testing/#static-dynamic-analysis). Статический анализ опирается на низкоуровневые представления, такие как [графы потоков управления](https://en.wikipedia.org/wiki/Control-flow_graph) и [абстрактные синтаксические деревья](https://deepsource.io/glossary/ast/), для анализа достижимых состояний программы и путей выполнения. В то же время методы динамического анализа, такие как [фаззинг умных контрактов](https://www.cyfrin.io/blog/smart-contract-fuzzing-and-invariants-testing-foundry), выполняют код контракта со случайными входными значениями для обнаружения операций, нарушающих свойства безопасности. + +[Формальная верификация](/developers/docs/smart-contracts/formal-verification) — это еще один метод проверки свойств безопасности в умных контрактах. В отличие от обычного тестирования, формальная верификация может убедительно доказать отсутствие ошибок в умном контракте. Это достигается путем создания формальной спецификации, которая отражает желаемые свойства безопасности, и доказательства того, что формальная модель контрактов соответствует этой спецификации. + +### 4. Запросите независимую проверку вашего кода {#get-independent-code-reviews} + +После того как Вы протестировали ваш контракт, хорошей идеей будет попросить других проверить исходный код на наличие проблем с безопасностью. Тестирование не сможет выявить все возможные недостатки смарт-контракта, но независимый аудит повышает вероятность того, что уязвимости будут обнаружены. + +#### Аудиты {#audits} + +Заказ аудита умного контракта — это один из способов проведения независимой проверки кода. Аудиторы играют важную роль в обеспечении безопасности умных контрактов и отсутствия в них дефектов качества и ошибок проектирования. + +Тем не менее, не следует относиться к аудитам как к панацее. Аудиты умных контрактов не выявляют все ошибки и в основном предназначены для проведения дополнительного раунда проверок, который может помочь обнаружить проблемы, пропущенные разработчиками на начальных этапах разработки и тестирования. Вы также должны следовать лучшим практикам работы с аудиторами, таким как правильное документирование кода и добавление встроенных комментариев, чтобы извлечь максимальную пользу из аудита умного контракта. + +- [Советы и хитрости по аудиту умных контрактов](https://twitter.com/tinchoabbate/status/1400170232904400897) — _@tinchoabbate_ +- [Получите максимум от вашего аудита](https://inference.ag/blog/2023-08-14-tips/) — _Inference_ + +#### Вознаграждения за обнаружение ошибок {#bug-bounties} + +Вознаграждения за обнаружение уязвимостей — ещё один способ проведения независимого аудита. Премией за обнаружение уязвимостей награждаются люди (обычно этические хакеры, или «белые шляпы»), которые находят уязвимости в приложениях. + +При верном использовании, такие вознаграждения мотивируют членов хакерского сообщества проверить ваш код на уязвимости. Реальным примером является «ошибка бесконечных денег», которая позволила бы атакующему создать неограниченное количество эфира на [Optimism](https://www.optimism.io/), протоколе [Леер 2](/layer-2/), работающем на Ethereum. К счастью, «белый» хакер [обнаружил уязвимость](https://www.saurik.com/optimism.html) и уведомил команду, [заработав при этом крупное вознаграждение](https://cryptoslate.com/critical-bug-in-ethereum-l2-optimism-2m-bounty-paid/). + +Хорошая стратегия — установить размер выплат по программе bug bounty пропорционально сумме средств, за которую вы отвечаете. Этот подход, названный «[масштабируемая программа вознаграждения за обнаружение ошибок](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7)», предоставляет финансовые стимулы для ответственного раскрытия уязвимостей вместо их эксплуатации. + +### 5. Следуйте лучшим практикам при разработке умных контрактов {#follow-smart-contract-development-best-practices} + +Наличие аудитов и программ вознаграждения за обнаружение ошибок не освобождает вас от ответственности писать высококачественный код. Хорошая безопасность умных контрактов начинается с соблюдения надлежащих процессов проектирования и разработки: + +- Храните весь код в системе контроля версий, такой как git + +- Вносите все изменения в код через запросы на слияние + +- Убедитесь, что запросы на слияние имеют хотя бы одного независимого рецензента — если вы работаете над проектом в одиночку, рассмотрите возможность найти других разработчиков и обмениваться с ними проверками кода + +- Используйте [среду разработки](/developers/docs/frameworks/) для тестирования, компиляции и развертывания умных контрактов + +- Прогоняйте свой код через базовые инструменты анализа кода, такие как [Cyfrin Aderyn](https://github.com/Cyfrin/aderyn), Mythril и Slither. В идеале это следует делать перед слиянием каждого запроса на слияние и сравнивать различия в результатах + +- Убедитесь, что ваш код компилируется без ошибок и компилятор Solidity не выдает предупреждений + +- Правильно документируйте свой код (используя [NatSpec](https://solidity.readthedocs.io/en/develop/natspec-format.html)) и описывайте детали архитектуры контракта на понятном языке. Это облегчит аудит и проверку вашего кода другими людьми. + +### 6. Внедряйте надежные планы аварийного восстановления {#implement-disaster-recovery-plans} + +Разработка безопасных средств контроля доступа, реализация модификаторов функций и другие предложения могут улучшить безопасность умных контрактов, но они не могут исключить возможность злонамеренных эксплойтов. Создание безопасных умных контрактов требует «подготовки к сбоям» и наличия запасного плана для эффективного реагирования на атаки. Надлежащий план аварийного восстановления будет включать некоторые или все из следующих компонентов: + +#### Обновления контрактов {#contract-upgrades} + +Хотя умные контракты Ethereum по умолчанию неизменяемы, можно достичь некоторой степени изменяемости, используя патерны обновления. Обновление контрактов необходимо в тех случаях, когда критическая уязвимость делает ваш старый контракт непригодным для использования, и развертывание новой логики является наиболее целесообразным вариантом. + +Механизмы обновления контрактов работают по-разному, но «патерн прокси» является одним из наиболее популярных подходов к обновлению умных контрактов. [Патерны прокси](https://www.cyfrin.io/blog/upgradeable-proxy-smart-contract-pattern) разделяют состояние и логику приложения между _двумя_ контрактами. Первый контракт (называемый «прокси-контракт») хранит переменные состояния (например, балансы пользователей), в то время как второй контракт (называемый «логический контракт») содержит код для выполнения функций контракта. + +Аккаунты взаимодействуют с прокси-контрактом, который перенаправляет все вызовы функций логическому контракту с помощью низкоуровневого вызова [`delegatecall()`](https://docs.soliditylang.org/en/v0.8.16/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries). В отличие от обычного вызова сообщения, `delegatecall()` гарантирует, что код, работающий по адресу логического контракта, выполняется в контексте вызывающего контракта. Это означает, что логический контракт всегда будет записывать данные в хранилище прокси-контракта (а не в свое собственное хранилище), а исходные значения `msg.sender` и `msg.value` сохраняются. + +Делегирование вызовов логическому контракту требует хранения его адреса в хранилище прокси-контракта. Следовательно, обновление логики контракта — это всего лишь вопрос развертывания другого логического контракта и сохранения нового адреса в прокси-контракте. Поскольку последующие вызовы прокси-контракта автоматически направляются на новый логический контракт, вы «обновите» контракт, фактически не изменяя код. + +[Подробнее об обновлении контрактов](/developers/docs/smart-contracts/upgrading/). + +#### Аварийные остановки {#emergency-stops} + +Как уже упоминалось, обширный аудит и тестирование не могут выявить все ошибки в умном контракте. Если после развертывания в вашем коде появляется уязвимость, исправить ее невозможно, поскольку вы не можете изменить код, работающий по адресу контракта. Кроме того, внедрение механизмов обновления (например, патернов прокси) может занять время (они часто требуют одобрения от разных сторон), что только дает атакующим больше времени для нанесения большего ущерба. + +Кардинальным решением является реализация функции «аварийной остановки», которая блокирует вызовы уязвимых функций в контракте. Аварийные остановки обычно включают следующие компоненты: + +1. Глобальная логическая переменная, указывающая, находится ли умный контракт в остановленном состоянии или нет. Эта переменная устанавливается в значение `false` при настройке контракта, но изменится на `true` после остановки контракта. + +2. Функции, которые ссылаются на логическую переменную при своем выполнении. Такие функции доступны, когда умный контракт не остановлен, и становятся недоступными при срабатывании функции аварийной остановки. + +3. Сущность, имеющая доступ к функции аварийной остановки, которая устанавливает логическую переменную в значение `true`. Для предотвращения злонамеренных действий вызовы этой функции могут быть ограничены доверенным адресом (например, владельцем контракта). + +После того, как контракт активирует аварийную остановку, определенные функции станут недоступными для вызова. Это достигается путем обертывания избранных функций в модификатор, который ссылается на глобальную переменную. Ниже приведен [пример](https://github.com/fravoll/solidity-patterns/blob/master/EmergencyStop/EmergencyStop.sol), описывающий реализацию этого патерна в контрактах: + +```solidity +// Этот код не прошел профессиональный аудит и не дает никаких гарантий безопасности или корректности. Используйте на свой страх и риск. + +contract EmergencyStop { + + bool isStopped = false; + + modifier stoppedInEmergency { + require(!isStopped); + _; + } + + modifier onlyWhenStopped { + require(isStopped); + _; + } + + modifier onlyAuthorized { + // Здесь проверьте авторизацию msg.sender + _; + } + + function stopContract() public onlyAuthorized { + isStopped = true; + } + + function resumeContract() public onlyAuthorized { + isStopped = false; + } + + function deposit() public payable stoppedInEmergency { + // Здесь происходит логика депозита + } + + function emergencyWithdraw() public onlyWhenStopped { + // Здесь происходит экстренный вывод средств + } +} +``` + +Этот пример показывает основные особенности аварийных остановок: + +- `isStopped` — это логическая переменная, которая в начале имеет значение `false`, а когда контракт переходит в аварийный режим, — `true`. + +- Модификаторы функций `onlyWhenStopped` и `stoppedInEmergency` проверяют переменную `isStopped`. `stoppedInEmergency` используется для управления функциями, которые должны быть недоступны, когда контракт уязвим (например, `deposit()`). Вызовы этих функций будут просто отменены. + +`onlyWhenStopped` используется для функций, которые должны быть доступны для вызова во время чрезвычайной ситуации (например, `emergencyWithdraw()`). Такие функции могут помочь разрешить ситуацию, поэтому они исключены из списка «ограниченных функций». + +Использование функциональности аварийной остановки обеспечивает эффективное временное решение для борьбы с серьезными уязвимостями в вашем умном контракте. Однако это увеличивает потребность пользователей доверять разработчикам, чтобы те не активировали ее в корыстных целях. Для этого возможными решениями являются децентрализация контроля над аварийной остановкой либо путем подчинения ее механизму ончейн-голосования, временной блокировке, либо одобрению с помощью кошелька с мультиподписью. + +#### Мониторинг событий {#event-monitoring} + +[События](https://docs.soliditylang.org/en/v0.8.15/contracts.html#events) позволяют отслеживать вызовы функций умного контракта и контролировать изменения переменных состояния. Идеально запрограммировать ваш умный контракт так, чтобы он генерировал событие всякий раз, когда какая-либо сторона предпринимает критически важное для безопасности действие (например, вывод средств). + +Регистрация событий и их мониторинг вне сети (оффчейн) дают представление об операциях контракта и способствуют более быстрому обнаружению злонамеренных действий. Это означает, что ваша команда может быстрее реагировать на взломы и принимать меры для смягчения последствий для пользователей, такие как приостановка функций или выполнение обновления. + +Вы также можете выбрать готовый инструмент мониторинга, который автоматически пересылает оповещения всякий раз, когда кто-то взаимодействует с вашими контрактами. Эти инструменты позволят вам создавать настраиваемые оповещения на основе различных триггеров, таких как объем транзакций, частота вызовов функций или конкретные задействованные функции. Например, вы можете запрограммировать оповещение, которое приходит, когда сумма, выведенная в одной транзакции, превышает определенный порог. + +### 7. Проектирование безопасных систем управления {#design-secure-governance-systems} + +Вы можете захотеть децентрализовать свое приложение, передав контроль над основными умными контрактами членам сообщества. В этом случае система умных контрактов будет включать модуль управления — механизм, который позволяет членам сообщества одобрять административные действия через ончейн-систему управления. Например, предложение обновить прокси-контракт до новой реализации может быть вынесено на голосование держателей токенов. + +Децентрализованное управление может быть полезным, особенно потому, что оно согласовывает интересы разработчиков и конечных пользователей. Тем не менее, механизмы управления умными контрактами могут создавать новые риски при неправильной реализации. Возможный сценарий — если атакующий приобретает огромную голосующую силу (измеряемую в количестве имеющихся токенов), взяв [срочный заем](/defi/#flash-loans), и проталкивает вредоносное предложение. + +Один из способов предотвращения проблем, связанных с ончейн-управлением, — [использование временной блокировки](https://blog.openzeppelin.com/protect-your-users-with-smart-contract-timelocks/). Временная блокировка не позволяет умному контракту выполнять определенные действия до истечения определенного времени. Другие стратегии включают присвоение «веса голоса» каждому токену в зависимости от того, как долго он был заблокирован, или измерение голосующей силы адреса в исторический период (например, 2-3 блока в прошлом) вместо текущего блока. Оба метода снижают вероятность быстрого накопления голосующей силы для влияния на результаты ончейн-голосований. + +Подробнее о [проектировании безопасных систем управления](https://blog.openzeppelin.com/smart-contract-security-guidelines-4-strategies-for-safer-governance-systems/), [различных механизмах голосования в DAO](https://hackernoon.com/governance-is-the-holy-grail-for-daos) и [распространенных векторах атак на DAO с использованием DeFi](https://dacian.me/dao-governance-defi-attacks) по приведенным ссылкам. + +### 8. Сведите сложность кода к минимуму {#reduce-code-complexity} + +Традиционные разработчики программного обеспечения знакомы с принципом KISS («делай проще, дурак»), который советует избегать ненужной сложности в проектировании программного обеспечения. Это следует из давнего убеждения, что «сложные системы дают сбой сложными способами» и более подвержены дорогостоящим ошибкам. + +Простота особенно важна при написании умных контрактов, учитывая, что они потенциально контролируют большие объемы ценностей. Совет по достижению простоты при написании умных контрактов — по возможности повторно использовать существующие библиотеки, такие как [OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/5.x/). Поскольку эти библиотеки были тщательно проверены и протестированы разработчиками, их использование снижает вероятность появления ошибок при написании новой функциональности с нуля. + +Еще один распространенный совет — писать небольшие функции и сохранять модульность контрактов, разделяя бизнес-логику между несколькими контрактами. Написание более простого кода не только уменьшает поверхность атаки в умном контракте, но и облегчает рассуждения о корректности всей системы и раннее обнаружение возможных ошибок проектирования. + +### 9. Защита от распространенных уязвимостей умных контрактов {#mitigate-common-smart-contract-vulnerabilities} + +#### Повторный вход {#reentrancy} + +EVM не допускает параллелизма, то есть два контракта, участвующие в вызове сообщения, не могут выполняться одновременно. Внешний вызов приостанавливает выполнение вызывающего контракта и его память до тех пор, пока вызов не вернется, после чего выполнение продолжается в обычном режиме. Этот процесс можно формально описать как передачу [потока управления](https://www.computerhope.com/jargon/c/contflow.htm) другому контракту. + +Хотя в основном это безвредно, передача потока управления ненадежным контрактам может вызвать проблемы, такие как повторный вход. Атака повторного входа происходит, когда вредоносный контракт вызывает уязвимый контракт до того, как завершится первоначальный вызов функции. Этот тип атаки лучше всего объяснить на примере. + +Рассмотрим простой умный контракт («Victim»), который позволяет любому вносить и выводить эфир: + +```solidity +// Этот контракт уязвим. Не используйте в продакшене + +contract Victim { + mapping (address => uint256) public balances; + + function deposit() external payable { + balances[msg.sender] += msg.value; + } + + function withdraw() external { + uint256 amount = balances[msg.sender]; + (bool success, ) = msg.sender.call.value(amount)(""); + require(success); + balances[msg.sender] = 0; + } +} +``` + +Этот контракт предоставляет функцию `withdraw()`, позволяющую пользователям выводить ETH, ранее внесенные в контракт. При обработке вывода средств контракт выполняет следующие операции: + +1. Проверяет баланс ETH пользователя +2. Отправляет средства на вызывающий адрес +3. Сбрасывает их баланс до 0, предотвращая дальнейшие выводы средств пользователем + +Функция `withdraw()` в контракте `Victim` следует патерну «проверки-взаимодействия-эффекты». Она _проверяет_, выполнены ли условия, необходимые для выполнения (т. е. у пользователя положительный баланс ETH), и выполняет _взаимодействие_, отправляя ETH на адрес вызывающего, прежде чем применить _эффекты_ транзакции (т. е. уменьшить баланс пользователя). + +Если `withdraw()` вызывается из внешнего аккаунта (EOA), функция выполняется, как и ожидалось: `msg.sender.call.value()` отправляет ETH вызывающему. Однако, если `msg.sender` является аккаунтом умного контракта и вызывает `withdraw()`, отправка средств с помощью `msg.sender.call.value()` также вызовет запуск кода, хранящегося по этому адресу. + +Представьте, что по адресу контракта развернут следующий код: + +```solidity + contract Attacker { + function beginAttack() external payable { + Victim(victim_address).deposit.value(1 ether)(); + Victim(victim_address).withdraw(); + } + + function() external payable { + if (gasleft() > 40000) { + Victim(victim_address).withdraw(); + } + } +} +``` + +Этот контракт предназначен для выполнения трех действий: + +1. Принять депозит с другого аккаунта (вероятно, EOA атакующего) +2. Внести 1 ETH в контракт Victim +3. Вывести 1 ETH, хранящийся в умном контракте + +Здесь нет ничего плохого, за исключением того, что у `Attacker` есть еще одна функция, которая снова вызывает `withdraw()` в `Victim`, если оставшегося газа от входящего `msg.sender.call.value` больше 40 000. Это дает `Attacker` возможность повторно войти в `Victim` и вывести больше средств _до_ завершения первого вызова `withdraw`. Цикл выглядит следующим образом: + +```solidity +- EOA атакующего вызывает `Attacker.beginAttack()` с 1 ETH +- `Attacker.beginAttack()` вносит 1 ETH в `Victim` +- `Attacker` вызывает `withdraw()` в `Victim` +- `Victim` проверяет баланс `Attacker` (1 ETH) +- `Victim` отправляет 1 ETH в `Attacker` (что вызывает функцию по умолчанию) +- `Attacker` снова вызывает `Victim.withdraw()` (обратите внимание, что `Victim` не уменьшил баланс `Attacker` после первого вывода средств) +- `Victim` проверяет баланс `Attacker` (который все еще составляет 1 ETH, потому что он не применил эффекты первого вызова) +- `Victim` отправляет 1 ETH в `Attacker` (что вызывает функцию по умолчанию и позволяет `Attacker` повторно войти в функцию `withdraw`) +- Процесс повторяется до тех пор, пока у `Attacker` не закончится газ, после чего `msg.sender.call.value` возвращается, не вызывая дополнительных выводов средств +- `Victim` наконец применяет результаты первой транзакции (и последующих) к своему состоянию, поэтому баланс `Attacker` устанавливается в 0 +``` + +Суть в том, что, поскольку баланс вызывающего не устанавливается в 0 до завершения выполнения функции, последующие вызовы будут успешными и позволят вызывающему вывести свой баланс несколько раз. Такой тип атаки может быть использован для опустошения умного контракта, как это произошло во время [взлома DAO в 2016 году](https://www.coindesk.com/learn/understanding-the-dao-attack). Атаки повторного входа до сих пор остаются критической проблемой для умных контрактов, как показывают [публичные списки эксплойтов повторного входа](https://github.com/pcaversaccio/reentrancy-attacks). + +##### Как предотвратить атаки повторного входа + +Один из подходов к борьбе с повторным входом — следование [патерну «проверки-эффекты-взаимодействия»](https://docs.soliditylang.org/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern). Этот патерн упорядочивает выполнение функций таким образом, что код, выполняющий необходимые проверки перед продолжением выполнения, идет первым, за ним следует код, который манипулирует состоянием контракта, а код, взаимодействующий с другими контрактами или EOA, идет последним. + +Патерн «проверки-эффект-взаимодействие» используется в исправленной версии контракта `Victim`, показанной ниже: + +```solidity +contract NoLongerAVictim { + function withdraw() external { + uint256 amount = balances[msg.sender]; + balances[msg.sender] = 0; + (bool success, ) = msg.sender.call.value(amount)(""); + require(success); + } +} +``` + +Этот контракт выполняет _проверку_ баланса пользователя, применяет _эффекты_ функции `withdraw()` (сбрасывая баланс пользователя до 0) и переходит к _взаимодействию_ (отправке ETH на адрес пользователя). Это гарантирует, что контракт обновит свое хранилище до внешнего вызова, устраняя условие повторного входа, которое сделало возможной первую атаку. Контракт `Attacker` все еще мог бы вызвать `NoLongerAVictim`, но поскольку `balances[msg.sender]` был установлен в 0, дополнительные выводы средств вызовут ошибку. + +Другой вариант — использовать блокировку взаимного исключения (обычно описываемую как «мьютекс»), которая блокирует часть состояния контракта до завершения вызова функции. Это реализуется с помощью логической переменной, которая устанавливается в `true` перед выполнением функции и возвращается в `false` после завершения вызова. Как видно из примера ниже, использование мьютекса защищает функцию от рекурсивных вызовов во время обработки исходного вызова, эффективно останавливая повторный вход. + +```solidity +pragma solidity ^0.7.0; + +contract MutexPattern { + bool locked = false; + mapping(address => uint256) public balances; + + modifier noReentrancy() { + require(!locked, "Заблокировано от повторного входа."); + locked = true; + _; + locked = false; + } + // Эта функция защищена мьютексом, поэтому повторные вызовы из `msg.sender.call` не могут снова вызвать `withdraw`. + // Оператор `return` возвращает `true`, но все равно выполняет оператор `locked = false` в модификаторе + function withdraw(uint _amount) public payable noReentrancy returns(bool) { + require(balances[msg.sender] >= _amount, "Нет баланса для вывода."); + + balances[msg.sender] -= _amount; + (bool success, ) = msg.sender.call{value: _amount}(""); + require(success); + + return true; + } +} +``` + +Вы также можете использовать систему [pull payments](https://docs.openzeppelin.com/contracts/5.x/api/security#PullPayment), которая требует от пользователей вывода средств из умных контрактов, вместо системы «push payments», которая отправляет средства на аккаунты. Это исключает возможность непреднамеренного запуска кода по неизвестным адресам (а также может предотвратить некоторые атаки типа «отказ в обслуживании»). + +#### Целочисленные недополнения и переполнения {#integer-underflows-and-overflows} + +Целочисленное переполнение происходит, когда результат арифметической операции выходит за пределы допустимого диапазона значений, что приводит к его «перебросу» на наименьшее представимое значение. Например, `uint8` может хранить значения только до 2^8-1=255. Арифметические операции, которые приводят к значениям выше `255`, переполнятся и сбросят `uint` до `0`, подобно тому, как одометр на автомобиле сбрасывается до 0, как только он достигает максимального пробега (999999). + +Целочисленные недополнения происходят по схожим причинам: результат арифметической операции оказывается ниже допустимого диапазона. Допустим, вы попытались уменьшить `0` в `uint8`, результат просто перескочит на максимальное представимое значение (`255`). + +Как целочисленные переполнения, так и недополнения могут привести к неожиданным изменениям переменных состояния контракта и привести к незапланированному выполнению. Ниже приведен пример, показывающий, как атакующий может использовать арифметическое переполнение в умном контракте для выполнения недействительной операции: + +``` +pragma solidity ^0.7.6; + +// Этот контракт предназначен для использования в качестве хранилища с временной блокировкой. +// Пользователь может вносить средства в этот контракт, но не может выводить их в течение как минимум недели. +// Пользователь также может продлить время ожидания сверх 1-недельного периода. + +/* +1. Разверните TimeLock +2. Разверните Attack с адресом TimeLock +3. Вызовите Attack.attack, отправив 1 эфир. Вы сразу сможете + вывести свой эфир. + +Что произошло? +Атака вызвала переполнение TimeLock.lockTime, что позволило вывести средства +до истечения 1-недельного периода ожидания. +*/ + +contract TimeLock { + mapping(address => uint) public balances; + mapping(address => uint) public lockTime; + + function deposit() external payable { + balances[msg.sender] += msg.value; + lockTime[msg.sender] = block.timestamp + 1 weeks; + } + + function increaseLockTime(uint _secondsToIncrease) public { + lockTime[msg.sender] += _secondsToIncrease; + } + + function withdraw() public { + require(balances[msg.sender] > 0, "Недостаточно средств"); + require(block.timestamp > lockTime[msg.sender], "Время блокировки не истекло"); + + uint amount = balances[msg.sender]; + balances[msg.sender] = 0; + + (bool sent, ) = msg.sender.call{value: amount}(""); + require(sent, "Не удалось отправить Ether"); + } +} + +contract Attack { + TimeLock timeLock; + + constructor(TimeLock _timeLock) { + timeLock = TimeLock(_timeLock); + } + + fallback() external payable {} + + function attack() public payable { + timeLock.deposit{value: msg.value}(); + /* + если t = текущее время блокировки, то нам нужно найти x, такое что + x + t = 2**256 = 0 + тогда x = -t + 2**256 = type(uint).max + 1 + тогда x = type(uint).max + 1 - t + */ + timeLock.increaseLockTime( + type(uint).max + 1 - timeLock.lockTime(address(this)) + ); + timeLock.withdraw(); + } +} +``` + +##### Как предотвратить целочисленные недополнения и переполнения + +Начиная с версии 0.8.0, компилятор Solidity отклоняет код, который приводит к целочисленным недополнениям и переполнениям. Однако контракты, скомпилированные с более низкой версией компилятора, должны либо выполнять проверки в функциях, включающих арифметические операции, либо использовать библиотеку (например, [SafeMath](https://docs.openzeppelin.com/contracts/2.x/api/math)), которая проверяет на недополнение/переполнение. + +#### Манипуляция оракулом {#oracle-manipulation} + +[Оракулы](/developers/docs/oracles/) получают информацию из оффчейн-источников и отправляют ее ончейн для использования умными контрактами. С помощью оракулов вы можете создавать умные контракты, которые взаимодействуют с оффчейн-системами, такими как рынки капитала, что значительно расширяет их применение. + +Но если оракул поврежден и отправляет неверную информацию ончейн, умные контракты будут выполняться на основе ошибочных данных, что может вызвать проблемы. В этом заключается основа «проблемы оракула», которая касается задачи обеспечения того, чтобы информация от блокчейн-оракула была точной, актуальной и своевременной. + +Связанная с этим проблема безопасности — использование ончейн-оракула, такого как децентрализованная биржа, для получения спотовой цены актива. Платформы кредитования в индустрии [децентрализованных финансов (DeFi)](/defi/) часто делают это для определения стоимости залога пользователя, чтобы определить, сколько он может занять. + +Цены на DEX часто точны, в основном благодаря арбитражерам, восстанавливающим паритет на рынках. Однако они подвержены манипуляциям, особенно если ончейн-оракул рассчитывает цены активов на основе исторических торговых патернов (как это обычно бывает). + +Например, атакующий может искусственно завысить спотовую цену актива, взяв срочный заем прямо перед взаимодействием с вашим кредитным контрактом. Запрос цены актива у DEX вернет значение выше нормального (из-за того, что крупный «ордер на покупку» атакующего исказил спрос на актив), что позволит ему занять больше, чем следовало бы. Такие «атаки со срочными займами» использовались для эксплуатации зависимости от ценовых оракулов среди приложений DeFi, что стоило протоколам миллионов потерянных средств. + +##### Как предотвратить манипуляции оракулом + +Минимальное требование для [избежания манипуляций с оракулом](https://www.cyfrin.io/blog/price-oracle-manipultion-attacks-with-examples) — использование децентрализованной сети оракулов, которая запрашивает информацию из нескольких источников, чтобы избежать единых точек отказа. В большинстве случаев децентрализованные оракулы имеют встроенные криптоэкономические стимулы для поощрения узлов оракула сообщать верную информацию, что делает их более безопасными, чем централизованные оракулы. + +Если вы планируете запрашивать цену актива у ончейн-оракула, рассмотрите возможность использования того, который реализует механизм средневзвешенной по времени цены (TWAP). [Оракул TWAP](https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles) запрашивает цену актива в два разных момента времени (которые вы можете изменять) и рассчитывает спотовую цену на основе полученного среднего значения. Выбор более длительных периодов времени защищает ваш протокол от манипулирования ценами, поскольку крупные ордера, выполненные недавно, не могут повлиять на цены активов. + +## Ресурсы по безопасности умных контрактов для разработчиков {#smart-contract-security-resources-for-developers} + +### Инструменты для анализа умных контрактов и проверки правильности кода {#code-analysis-tools} + +- **[Инструменты и библиотеки для тестирования](/developers/docs/smart-contracts/testing/#testing-tools-and-libraries)** — _Коллекция стандартных отраслевых инструментов и библиотек для выполнения модульных тестов, статического и динамического анализа умных контрактов._ + +- **[Инструменты формальной верификации](/developers/docs/smart-contracts/formal-verification/#formal-verification-tools)** — _Инструменты для проверки функциональной корректности в умных контрактах и проверки инвариантов._ + +- **[Сервисы аудита умных контрактов](/developers/docs/smart-contracts/testing/#smart-contract-auditing-services)** — _Список организаций, предоставляющих услуги по аудиту умных контрактов для проектов разработки на Ethereum._ + +- **[Платформы вознаграждений за обнаружение ошибок](/developers/docs/smart-contracts/testing/#bug-bounty-platforms)** — _Платформы для координации программ вознаграждений за обнаружение ошибок и поощрения ответственного раскрытия критических уязвимостей в умных контрактах._ + +- **[Fork Checker](https://forkchecker.hashex.org/)** — _бесплатный онлайн-инструмент для проверки всей доступной информации о форкнутом контракте._ + +- **[ABI Encoder](https://abi.hashex.org/)** — _бесплатный онлайн-сервис для кодирования функций вашего контракта Solidity и аргументов конструктора._ + +- **[Aderyn](https://github.com/Cyfrin/aderyn)** — статический анализатор Solidity, обходящий абстрактные синтаксические деревья (AST) для выявления предполагаемых уязвимостей и вывода проблем в удобном для восприятия формате Markdown. + +### Инструменты для мониторинга умных контрактов {#smart-contract-monitoring-tools} + +- **[Tenderly Real-Time Alerting](https://tenderly.co/monitoring)** — _инструмент для получения уведомлений в реальном времени о необычных или неожиданных событиях в ваших умных контрактах или кошельках._ + +### Инструменты для безопасного администрирования умных контрактов {#smart-contract-administration-tools} + +- **[Safe](https://safe.global/)** — _кошелек на основе умного контракта, работающий на Ethereum, который требует одобрения транзакции минимальным количеством людей (M из N)._ + +- **[OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/5.x/)** — _библиотеки контрактов для реализации административных функций, включая владение контрактом, обновления, контроль доступа, управление, возможность приостановки и многое другое._ + +### Сервисы аудита умных контрактов {#smart-contract-auditing-services} + +- **[ConsenSys Diligence](https://diligence.consensys.io/)** — _сервис аудита умных контрактов, помогающий проектам по всей экосистеме блокчейна убедиться, что их протоколы готовы к запуску и созданы для защиты пользователей._ + +- **[CertiK](https://www.certik.com/)** — _фирма по безопасности блокчейна, пионер в использовании передовых технологий формальной верификации на умных контрактах и блокчейн-сетях._ + +- **[Trail of Bits](https://www.trailofbits.com/)** — _компания по кибербезопасности, которая сочетает исследования в области безопасности с мышлением атакующего, чтобы снизить риски и укрепить код._ + +- **[PeckShield](https://peckshield.com/)** — _компания по безопасности блокчейна, предлагающая продукты и услуги для обеспечения безопасности, конфиденциальности и удобства использования всей экосистемы блокчейна._ + +- **[QuantStamp](https://quantstamp.com/)** — _сервис аудита, способствующий массовому внедрению технологии блокчейн через услуги по оценке безопасности и рисков._ + +- **[OpenZeppelin](https://www.openzeppelin.com/security-audits)** — _компания по безопасности умных контрактов, предоставляющая аудиты безопасности для распределенных систем._ + +- **[Runtime Verification](https://runtimeverification.com/)** — _компания по безопасности, специализирующаяся на формальном моделировании и верификации умных контрактов._ + +- **[Hacken](https://hacken.io)** — _аудитор кибербезопасности Web3, применяющий 360-градусный подход к безопасности блокчейна._ + +- **[Nethermind](https://www.nethermind.io/smart-contract-audits)** — _услуги аудита Solidity и Cairo, обеспечивающие целостность умных контрактов и безопасность пользователей в Ethereum и Starknet._ + +- **[HashEx](https://hashex.org/)** — _HashEx специализируется на аудите блокчейна и умных контрактов для обеспечения безопасности криптовалют, предоставляя такие услуги, как разработка умных контрактов, тестирование на проникновение, консалтинг в области блокчейна._ + +- **[Code4rena](https://code4rena.com/)** — _конкурентная платформа для аудита, которая стимулирует экспертов по безопасности умных контрактов находить уязвимости и помогать делать web3 более безопасным._ + +- **[CodeHawks](https://codehawks.com/)** — _конкурентная аудиторская платформа, проводящая соревнования по аудиту умных контрактов для исследователей безопасности._ + +- **[Cyfrin](https://cyfrin.io)** — _мощный центр безопасности Web3, инкубирующий криптобезопасность через продукты и услуги по аудиту умных контрактов._ + +- **[ImmuneBytes](https://immunebytes.com/smart-contract-audit/)** — _фирма по безопасности Web3, предлагающая аудиты безопасности для блокчейн-систем с помощью команды опытных аудиторов и лучших в своем классе инструментов._ + +- **[Oxorio](https://oxor.io/)** — _аудиты умных контрактов и услуги по безопасности блокчейна с опытом в EVM, Solidity, ZK, кросс-чейн технологиях для криптофирм и проектов DeFi._ + +- **[Inference](https://inference.ag/)** — _аудиторская компания по безопасности, специализирующаяся на аудите умных контрактов для блокчейнов на базе EVM. Благодаря своим опытным аудиторам они выявляют потенциальные проблемы и предлагают действенные решения для их устранения до развертывания._ + +### Платформы вознаграждений за обнаружение ошибок {#bug-bounty-platforms} + +- **[Immunefi](https://immunefi.com/)** — _платформа вознаграждений за обнаружение ошибок для умных контрактов и проектов DeFi, где исследователи безопасности просматривают код, раскрывают уязвимости, получают вознаграждение и делают криптовалюту безопаснее._ + +- **[HackerOne](https://www.hackerone.com/)** — _платформа для координации уязвимостей и вознаграждений за обнаружение ошибок, которая связывает компании с пентестерами и исследователями кибербезопасности._ + +- **[HackenProof](https://hackenproof.com/)** — _экспертная платформа вознаграждений за ошибки для криптопроектов (DeFi, умные контракты, кошельки, CEX и другие), где специалисты по безопасности обеспечивают сортировочные услуги и исследователям платят за соответствующие, проверенные сообщения об ошибках._ + +- **[Sherlock](https://www.sherlock.xyz/)** — _гарант безопасности умных контрактов в Web3, с выплатами для аудиторов, управляемыми через умные контракты, чтобы обеспечить справедливую оплату за обнаружение соответствующих ошибок._ + +- **[CodeHawks](https://www.codehawks.com/)** — _конкурентная платформа вознаграждений за обнаружение ошибок, где аудиторы принимают участие в конкурсах и челленджах по безопасности, а (скоро) и в своих собственных частных аудитах._ + +### Публикации известных уязвимостей и эксплойтов умных контрактов {#common-smart-contract-vulnerabilities-and-exploits} + +- **[ConsenSys: известные атаки на умные контракты](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/)** — _понятное для новичков объяснение наиболее значительных уязвимостей контрактов с примерами кода для большинства случаев._ + +- **[SWC Registry](https://swcregistry.io/)** — _отобранный список элементов Common Weakness Enumeration (CWE), применимых к умным контрактам Ethereum._ + +- **[Rekt](https://rekt.news/)** — _регулярно обновляемое издание о громких крипто-взломах и эксплойтах, а также подробные отчеты о вскрытии._ + +### Задания для изучения безопасности умных контрактов {#challenges-for-learning-smart-contract-security} + +- **[Awesome BlockSec CTF](https://github.com/blockthreat/blocksec-ctfs)** — _отобранный список военных игр, задач и соревнований [Capture The Flag](https://www.webopedia.com/definitions/ctf-event/amp/) в области безопасности блокчейна, а также разборы решений._ + +- **[Damn Vulnerable DeFi](https://www.damnvulnerabledefi.xyz/)** — _военная игра для изучения наступательной безопасности умных контрактов DeFi и развития навыков в поиске ошибок и аудите безопасности._ + +- **[Ethernaut](https://ethernaut.openzeppelin.com/)** — _военная игра на основе Web3/Solidity, где каждый уровень — это умный контракт, который нужно «взломать»._ + +- **[HackenProof x HackTheBox](https://app.hackthebox.com/tracks/HackenProof-Track)** — _задание по взлому умных контрактов в стиле фэнтезийного приключения. Успешное выполнение задания также дает доступ к частной программе вознаграждений за обнаружение ошибок._ + +### Лучшие практики по обеспечению безопасности умных контрактов {#smart-contract-security-best-practices} + +- **[ConsenSys: лучшие практики безопасности умных контрактов Ethereum](https://consensys.github.io/smart-contract-best-practices/)** — _полный список рекомендаций по обеспечению безопасности умных контрактов Ethereum._ + +- **[Nascent: простой набор инструментов для обеспечения безопасности](https://github.com/nascentxyz/simple-security-toolkit)** — _коллекция практических руководств и контрольных списков по безопасности для разработки умных контрактов._ + +- **[Solidity Patterns](https://fravoll.github.io/solidity-patterns/)** — _полезная подборка безопасных патернов и лучших практик для языка программирования умных контрактов Solidity._ + +- **[Документация Solidity: соображения безопасности](https://docs.soliditylang.org/en/v0.8.16/security-considerations.html)** — _руководство по написанию безопасных умных контрактов на Solidity._ + +- **[Стандарт верификации безопасности умных контрактов](https://github.com/securing/SCSVS)** — _четырнадцатипунктовый контрольный список, созданный для стандартизации безопасности умных контрактов для разработчиков, архитекторов, ревьюеров безопасности и поставщиков._ + +- **[Изучение безопасности и аудита умных контрактов](https://updraft.cyfrin.io/courses/security)** — _полный курс по безопасности и аудиту умных контрактов, созданный для разработчиков умных контрактов, которые хотят повысить уровень своих знаний в области безопасности и стать исследователями безопасности._ + +### Учебные пособия по безопасности умных контрактов {#tutorials-on-smart-contract-security} + +- [Как писать безопасные умные контракты](/developers/tutorials/secure-development-workflow/) + +- [Как использовать Slither для поиска ошибок в умных контрактах](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) + +- [Как использовать Manticore для поиска ошибок в умных контрактах](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/) + +- [Руководство по безопасности умных контрактов](/developers/tutorials/smart-contract-security-guidelines/) + +- [Как безопасно интегрировать ваш контракт токенов с произвольными токенами](/developers/tutorials/token-integration-checklist/) + +- [Cyfrin Updraft — полный курс по безопасности и аудиту умных контрактов](https://updraft.cyfrin.io/courses/security) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/testing/index.md b/public/content/translations/ru/developers/docs/smart-contracts/testing/index.md new file mode 100644 index 00000000000..e43a1adb045 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/testing/index.md @@ -0,0 +1,310 @@ +--- +title: "Тестирование смарт-контрактов" +description: "Обзор техник и соображений по тестированию смарт-контрактов Ethereum." +lang: ru +--- + +Публичные блокчейны, такие как Ethereum, являются неизменными, что затрудняет изменение кода смарт-контракта после его развертывания. Существуют [шаблоны обновления контрактов](/developers/docs/smart-contracts/upgrading/) для выполнения «виртуальных обновлений», но их сложно реализовать, и они требуют социального консенсуса. Более того, обновление может исправить ошибку только _после_ ее обнаружения — если злоумышленник обнаружит уязвимость первым, ваш смарт-контракт подвергается риску эксплойта. + +По этим причинам тестирование смарт-контрактов перед [развертыванием](/developers/docs/smart-contracts/deploying/) в основной сети (Mainnet) является минимальным требованием для обеспечения [безопасности](/developers/docs/smart-contracts/security/). Существует множество методов для тестирования контрактов и оценки правильности кода; выбор зависит от ваших потребностей. Тем не менее, набор тестов, состоящий из различных инструментов и подходов, идеально подходит для выявления как незначительных, так и серьезных недостатков безопасности в коде контракта. + +## Предварительные условия {#prerequisites} + +На этой странице объясняется, как тестировать смарт-контракты перед развертыванием в сети Ethereum. Предполагается, что вы знакомы со [смарт-контрактами](/developers/docs/smart-contracts/). + +## Что такое тестирование смарт-контрактов? {#what-is-smart-contract-testing} + +Тестирование смарт-контрактов — это процесс проверки того, что код смарт-контракта работает так, как ожидалось. Тестирование полезно для проверки того, удовлетворяет ли конкретный смарт-контракт требованиям надежности, удобства использования и безопасности. + +Хотя подходы различаются, большинство методов тестирования требуют выполнения смарт-контракта с небольшим объемом данных, которые он должен обрабатывать. Если контракт дает правильные результаты для выборочных данных, считается, что он функционирует должным образом. Большинство инструментов для тестирования предоставляют ресурсы для написания и выполнения [тестовых случаев](https://en.m.wikipedia.org/wiki/Test_case) для проверки соответствия выполнения контракта ожидаемым результатам. + +### Почему важно тестировать смарт-контракты? {#importance-of-testing-smart-contracts} + +Поскольку смарт-контракты часто управляют дорогостоящими финансовыми активами, незначительные ошибки программирования могут привести и часто приводят к [огромным потерям для пользователей](https://rekt.news/leaderboard/). Однако тщательное тестирование может помочь вам выявить дефекты и проблемы в коде смарт-контракта на ранней стадии и исправить их до запуска в основной сети (Mainnet). + +Хотя возможно обновить контракт при обнаружении ошибки, обновления сложны и могут [привести к ошибкам](https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/) при неправильном обращении. Обновление контракта еще больше отрицает принцип неизменности и обременяет пользователей дополнительными предположениями о доверии. И наоборот, комплексный план тестирования вашего контракта снижает риски безопасности смарт-контрактов и уменьшает необходимость в сложных логических обновлениях после развертывания. + +## Методы тестирования смарт-контрактов {#methods-for-testing-smart-contracts} + +Методы тестирования смарт-контрактов Ethereum делятся на две большие категории: **автоматизированное тестирование** и **ручное тестирование**. Автоматизированное и ручное тестирование предлагают уникальные преимущества и компромиссы, но вы можете объединить их для создания надежного плана анализа ваших контрактов. + +### Автоматизированное тестирование {#automated-testing} + +Автоматизированное тестирование использует инструменты, которые автоматически проверяют код смарт-контракта на наличие ошибок при исполнении. Преимущество автоматизированного тестирования заключается в использовании [скриптов](https://www.techtarget.com/whatis/definition/script?amp=1) для управления оценкой функциональности контракта. Скриптовые тесты можно запланировать для многократного запуска с минимальным вмешательством человека, что делает автоматизированное тестирование более эффективным, чем ручные подходы к тестированию. + +Автоматизированное тестирование особенно полезно, когда тесты повторяются и занимают много времени, их трудно выполнять вручную, они подвержены человеческим ошибкам или включают оценку критически важных функций контракта. Но инструменты автоматизированного тестирования могут иметь и недостатки: они могут пропустить некоторые ошибки и выдать много [ложноположительных результатов](https://www.contrastsecurity.com/glossary/false-positive). Следовательно, идеальным является сочетание автоматизированного и ручного тестирования для смарт-контрактов. + +### Ручное тестирование {#manual-testing} + +Ручное тестирование выполняется с помощью человека и включает в себя последовательное выполнение каждого тестового случая в вашем наборе тестов при анализе правильности смарт-контракта. Это отличается от автоматизированного тестирования, где вы можете одновременно запускать несколько изолированных тестов на контракте и получать отчет, показывающий все неудачные и пройденные тесты. + +Ручное тестирование может проводиться одним человеком в соответствии с письменным планом тестирования, который охватывает различные сценарии тестирования. Вы также можете попросить нескольких лиц или групп взаимодействовать со смарт-контрактом в течение определенного периода в рамках ручного тестирования. Тестировщики будут сравнивать фактическое поведение контракта с ожидаемым, отмечая любое различие как ошибку. + +Эффективное ручное тестирование требует значительных ресурсов (навыков, времени, денег и усилий), и из-за человеческой ошибки возможно пропустить некоторые ошибки при выполнении тестов. Но ручное тестирование также может быть полезным — например, человек-тестировщик (например, аудитор) может использовать интуицию для обнаружения крайних случаев, которые пропустит инструмент автоматизированного тестирования. + +## Автоматизированное тестирование для смарт-контрактов {#automated-testing-for-smart-contracts} + +### Модульное тестирование {#unit-testing-for-smart-contracts} + +Модульное тестирование оценивает функции контракта по отдельности и проверяет правильность работы каждого компонента. Хорошие модульные тесты должны быть простыми, быстрыми в выполнении и давать четкое представление о том, что пошло не так, если тесты не пройдены. + +Модульные тесты полезны для проверки того, что функции возвращают ожидаемые значения и что хранилище контракта правильно обновляется после выполнения функции. Кроме того, запуск модульных тестов после внесения изменений в кодовую базу контракта гарантирует, что добавление новой логики не приведет к появлению ошибок. Ниже приведены некоторые рекомендации по проведению эффективных модульных тестов: + +#### Рекомендации по модульному тестированию смарт-контрактов {#unit-testing-guidelines} + +##### 1. Поймите бизнес-логику и рабочий процесс ваших контрактов + +Прежде чем писать модульные тесты, полезно знать, какие функции предлагает смарт-контракт и как пользователи будут получать к ним доступ и использовать их. Это особенно полезно для запуска [тестов по «счастливому пути»](https://en.m.wikipedia.org/wiki/Happy_path), которые определяют, возвращают ли функции в контракте правильный результат для допустимых пользовательских вводов. Мы объясним эту концепцию на примере (сокращенном) [контракта аукциона](https://docs.soliditylang.org/en/v0.8.17/solidity-by-example.html?highlight=Auction%20contract#simple-open-auction) + +```solidity +constructor( + uint biddingTime, + address payable beneficiaryAddress + ) { + beneficiary = beneficiaryAddress; + auctionEndTime = block.timestamp + biddingTime; + } + +function bid() external payable { + + if (block.timestamp > auctionEndTime) + revert AuctionAlreadyEnded(); + + if (msg.value <= highestBid) + revert BidNotHighEnough(highestBid); + + if (highestBid != 0) { + pendingReturns[highestBidder] += highestBid; + } + highestBidder = msg.sender; + highestBid = msg.value; + emit HighestBidIncreased(msg.sender, msg.value); + } + + function withdraw() external returns (bool) { + uint amount = pendingReturns[msg.sender]; + if (amount > 0) { + pendingReturns[msg.sender] = 0; + + if (!payable(msg.sender).send(amount)) { + pendingReturns[msg.sender] = amount; + return false; + } + } + return true; + } + +function auctionEnd() external { + if (block.timestamp < auctionEndTime) + revert AuctionNotYetEnded(); + if (ended) + revert AuctionEndAlreadyCalled(); + + ended = true; + emit AuctionEnded(highestBidder, highestBid); + + beneficiary.transfer(highestBid); + } +} +``` + +Это простой контракт аукциона, предназначенный для приема ставок в течение периода торгов. Если `highestBid` увеличивается, предыдущий участник, сделавший самую высокую ставку, получает свои деньги; как только период торгов заканчивается, `beneficiary` вызывает контракт, чтобы получить свои деньги. + +Модульные тесты для такого контракта охватывали бы различные функции, которые пользователь мог бы вызывать при взаимодействии с контрактом. Примером может служить модульный тест, который проверяет, может ли пользователь сделать ставку во время аукциона (т. е. вызовы `bid()` завершаются успешно), или тест, который проверяет, может ли пользователь сделать ставку выше текущей `highestBid`. + +Понимание рабочего процесса контракта также помогает в написании модульных тестов, которые проверяют, соответствует ли выполнение требованиям. Например, контракт аукциона указывает, что пользователи не могут делать ставки после окончания аукциона (т. е. когда `auctionEndTime` меньше `block.timestamp`). Таким образом, разработчик может запустить модульный тест, который проверяет, завершаются ли вызовы функции `bid()` успешно или неудачно после окончания аукциона (т. е. когда `auctionEndTime` > `block.timestamp`). + +##### 2. Оцените все предположения, связанные с выполнением контракта + +Важно документировать все предположения о выполнении контракта и писать модульные тесты для проверки достоверности этих предположений. Помимо защиты от непредвиденного выполнения, тестирование утверждений заставляет вас задуматься об операциях, которые могут нарушить модель безопасности смарт-контракта. Полезный совет: выходить за рамки «тестов для счастливого пользователя» и писать негативные тесты, которые проверяют, не сбоит ли функция при неверных входных данных. + +Многие фреймворки для модульного тестирования позволяют создавать утверждения — простые операторы, которые определяют, что контракт может и не может делать, — и запускать тесты, чтобы увидеть, соблюдаются ли эти утверждения при выполнении. Разработчик, работающий над описанным ранее контрактом аукциона, мог бы сделать следующие утверждения о его поведении перед запуском негативных тестов: + +- Пользователи не могут делать ставки, когда аукцион закончился или еще не начался. + +- Контракт аукциона отменяет транзакцию, если ставка ниже допустимого порога. + +- Пользователи, не выигравшие торги, получают свои средства обратно + +**Примечание**: еще один способ проверить предположения — написать тесты, которые вызывают [модификаторы функций](https://docs.soliditylang.org/en/v0.8.16/contracts.html#function-modifiers) в контракте, особенно операторы `require`, `assert` и `if…else`. + +##### 3. Измерение покрытия кода + +[Покрытие кода](https://en.m.wikipedia.org/wiki/Code_coverage) — это метрика тестирования, которая отслеживает количество ветвей, строк и операторов в вашем коде, выполненных во время тестов. Тесты должны иметь хорошее покрытие кода, чтобы минимизировать риск непроверенных уязвимостей. Без достаточного покрытия вы можете ошибочно предположить, что ваш контракт безопасен, потому что все тесты пройдены, в то время как уязвимости все еще существуют в непроверенных путях кода. Однако регистрация высокого покрытия кода дает уверенность в том, что все операторы/функции в смарт-контракте были достаточно протестированы на правильность. + +##### 4. Используйте хорошо разработанные фреймворки для тестирования + +Качество инструментов, используемых для запуска модульных тестов для ваших смарт-контрактов, имеет решающее значение. Идеальный фреймворк для тестирования — это тот, который регулярно поддерживается, предоставляет полезные функции (например, возможности ведения журнала и отчетности) и должен быть широко использован и проверен другими разработчиками. + +Фреймворки для модульного тестирования смарт-контрактов Solidity существуют на разных языках (в основном JavaScript, Python и Rust). См. некоторые из приведенных ниже руководств для получения информации о том, как начать запускать модульные тесты с различными фреймворками для тестирования: + +- **[Запуск модульных тестов с помощью Brownie](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** +- **[Запуск модульных тестов с помощью Foundry](https://book.getfoundry.sh/forge/writing-tests)** +- **[Запуск модульных тестов с помощью Waffle](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)** +- **[Запуск модульных тестов с помощью Remix](https://remix-ide.readthedocs.io/en/latest/unittesting.html#write-tests)** +- **[Запуск модульных тестов с помощью Ape](https://docs.apeworx.io/ape/stable/userguides/testing.html)** +- **[Запуск модульных тестов с помощью Hardhat](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** +- **[Запуск модульных тестов с Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** + +### Интеграционное тестирование {#integration-testing-for-smart-contracts} + +В то время как модульное тестирование отлаживает функции контракта изолированно, интеграционные тесты оценивают компоненты смарт-контракта в целом. Интеграционное тестирование может выявить проблемы, возникающие из-за межконтрактных вызовов или взаимодействия между различными функциями в одном и том же смарт-контракте. Например, интеграционные тесты могут помочь проверить, правильно ли работают такие вещи, как [наследование](https://docs.soliditylang.org/en/v0.8.12/contracts.html#inheritance) и внедрение зависимостей. + +Интеграционное тестирование полезно, если ваш контракт имеет модульную архитектуру или взаимодействует с другими ончейн-контрактами во время выполнения. Один из способов проведения интеграционных тестов — это [сделать форк блокчейна](/glossary/#fork) на определенной высоте (используя такой инструмент, как [Forge](https://book.getfoundry.sh/forge/fork-testing) или [Hardhat](https://hardhat.org/hardhat-network/docs/guides/forking-other-networks)) и смоделировать взаимодействие между вашим контрактом и развернутыми контрактами. + +Форкнутый блокчейн будет вести себя аналогично основной сети (Mainnet) и будет иметь аккаунты со связанными состояниями и балансами. Но он действует только как локальная среда разработки в песочнице, то есть вам не понадобятся реальные ETH для транзакций, и ваши изменения не повлияют на реальный протокол Ethereum. + +### Тестирование на основе свойств {#property-based-testing-for-smart-contracts} + +Тестирование на основе свойств — это процесс проверки того, что смарт-контракт удовлетворяет некоторому определенному свойству. Свойства утверждают факты о поведении контракта, которые, как ожидается, останутся верными в различных сценариях. Примером свойства смарт-контракта может быть: «Арифметические операции в контракте никогда не вызывают переполнения или антипереполнения». + +Статический и динамический анализ — два распространенных метода для проведения тестирования на основе свойств, и оба могут проверить, что код программы (в данном случае смарт-контракта) удовлетворяет некоторому предопределенному свойству. Некоторые инструменты для тестирования на основе свойств поставляются с предопределенными правилами об ожидаемых свойствах контракта и проверяют код по этим правилам, в то время как другие позволяют создавать пользовательские свойства для смарт-контракта. + +#### Статический анализ {#static-analysis} + +Статический анализатор принимает на вход исходный код смарт-контракта и выводит результаты, объявляющие, удовлетворяет ли контракт свойству или нет. В отличие от динамического анализа, статический анализ не предполагает выполнения контракта для его анализа на правильность. Вместо этого статический анализ рассуждает обо всех возможных путях, которые смарт-контракт может пройти во время выполнения (т. е. путем изучения структуры исходного кода, чтобы определить, что это будет означать для работы контракта во время выполнения). + +[Линтинг](https://www.perforce.com/blog/qac/what-is-linting) и [статическое тестирование](https://www.techtarget.com/whatis/definition/static-analysis-static-code-analysis) являются распространенными методами статического анализа контрактов. Оба метода требуют анализа низкоуровневых представлений выполнения контракта, таких как [абстрактные синтаксические деревья](https://en.m.wikipedia.org/wiki/Abstract_syntax_tree) и [графы потока управления](https://www.geeksforgeeks.org/software-engineering-control-flow-graph-cfg/amp/), выводимые компилятором. + +В большинстве случаев статический анализ полезен для обнаружения проблем безопасности, таких как использование небезопасных конструкций, синтаксических ошибок или нарушений стандартов кодирования в коде контракта. Однако известно, что статические анализаторы, как правило, ненадёжны при обнаружении более глубоких уязвимостей и могут давать чрезмерное количество ложных срабатываний. + +#### Динамический анализ {#dynamic-analysis} + +Динамический анализ генерирует символические входные данные (например, при [символическом выполнении](https://en.m.wikipedia.org/wiki/Symbolic_execution)) или конкретные входные данные (например, при [фаззинге](https://owasp.org/www-community/Fuzzing)) для функций смарт-контракта, чтобы увидеть, нарушает ли какой-либо след(ы) выполнения определенные свойства. Эта форма тестирования на основе свойств отличается от модульных тестов тем, что тестовые случаи охватывают несколько сценариев, а программа обрабатывает генерацию тестовых случаев. + +[Фаззинг](https://www.halborn.com/blog/post/what-is-fuzz-testing-fuzzing) — это пример метода динамического анализа для проверки произвольных свойств в смарт-контрактах. Фаззер вызывает функции в целевом контракте со случайными или искаженными вариациями определенного входного значения. Если смарт-контракт переходит в состояние ошибки (например, когда утверждение не выполняется), проблема отмечается, а в отчете приводятся входные данные, которые направляют выполнение к уязвимому пути. + +Фаззинг полезен для оценки механизма проверки входных данных смарт-контракта, поскольку неправильная обработка непредвиденных входных данных может привести к непреднамеренному выполнению и вызвать опасные последствия. Эта форма тестирования на основе свойств может быть идеальной по многим причинам: + +1. **Написать тестовые случаи для охвата множества сценариев сложно.** Тест на основе свойств требует только того, чтобы вы определили поведение и диапазон данных для его тестирования — программа автоматически генерирует тестовые случаи на основе определенного свойства. + +2. **Ваш набор тестов может недостаточно охватывать все возможные пути в программе.** Даже при 100% покрытии можно упустить крайние случаи. + +3. Модульные тесты доказывают, что контракт выполняется правильно для выборочных данных, но остается неизвестным, правильно ли он выполняется для входных данных за пределами выборки. Тесты на основе свойств выполняют целевой контракт с множеством вариаций заданного входного значения для поиска следов выполнения, которые вызывают сбои утверждений. Таким образом, тест на основе свойств предоставляет больше гарантий того, что контракт выполняется правильно для широкого класса входных данных. + +### Рекомендации по проведению тестирования смарт-контрактов на основе свойств {#running-property-based-tests} + +Проведение тестирования на основе свойств обычно начинается с определения свойства (например, отсутствия [целочисленных переполнений](https://github.com/ConsenSys/mythril/wiki/Integer-Overflow)) или набора свойств, которые вы хотите проверить в смарт-контракте. Вам также может потребоваться определить диапазон значений, в пределах которого программа может генерировать данные для входных данных транзакции при написании тестов на основе свойств. + +После правильной настройки инструмент для тестирования на основе свойств будет выполнять функции вашего смарт-контракта со случайно сгенерированными входными данными. Если есть какие-либо нарушения утверждений, вы должны получить отчет с конкретными входными данными, которые нарушают оцениваемое свойство. См. некоторые из приведенных ниже руководств, чтобы начать работу с тестированием на основе свойств с помощью различных инструментов: + +- **[Статический анализ смарт-контрактов с помощью Slither](https://github.com/crytic/slither)** +- **[Статический анализ смарт-контрактов с помощью Wake](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** +- **[Тестирование на основе свойств с помощью Brownie](https://eth-brownie.readthedocs.io/en/stable/tests-hypothesis-property.html)** +- **[Фаззинг контрактов с помощью Foundry](https://book.getfoundry.sh/forge/fuzz-testing)** +- **[Фаззинг контрактов с помощью Echidna](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna#echidna-tutorial)** +- **[Фаззинг контрактов с Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/fuzzing/)** +- **[Символическое выполнение смарт-контрактов с помощью Manticore](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore#manticore-tutorial)** +- **[Символическое выполнение смарт-контрактов с помощью Mythril](https://mythril-classic.readthedocs.io/en/master/tutorial.html)** + +## Ручное тестирование смарт-контрактов {#manual-testing-for-smart-contracts} + +Ручное тестирование смарт-контрактов часто проводится на более поздних этапах цикла разработки после выполнения автоматизированных тестов. Эта форма тестирования оценивает смарт-контракт как единый полностью интегрированный продукт, чтобы увидеть, работает ли он в соответствии с техническими требованиями. + +### Тестирование контрактов на локальном блокчейне {#testing-on-local-blockchain} + +Хотя автоматизированное тестирование, проводимое в локальной среде разработки, может предоставить полезную информацию для отладки, вам захочется узнать, как ваш смарт-контракт ведет себя в производственной среде. Однако развертывание в основной сети Ethereum влечет за собой плату за газ, не говоря уже о том, что вы или ваши пользователи можете потерять реальные деньги, если в вашем смарт-контракте все еще есть ошибки. + +Тестирование вашего контракта на локальном блокчейне (также известном как [сеть разработки](/developers/docs/development-networks/)) является рекомендуемой альтернативой тестированию в основной сети (Mainnet). Локальный блокчейн — это копия блокчейна Ethereum, работающая локально на вашем компьютере, которая имитирует поведение уровня исполнения Ethereum. Таким образом, вы можете программировать транзакции для взаимодействия с контрактом, не неся значительных накладных расходов. + +Запуск контрактов на локальном блокчейне может быть полезен как форма ручного интеграционного тестирования. [Смарт-контракты обладают высокой степенью компонуемости](/developers/docs/smart-contracts/composability/), что позволяет вам интегрироваться с существующими протоколами, но вам все равно нужно будет убедиться, что такие сложные ончейн-взаимодействия дают правильные результаты. + +[Подробнее о сетях для разработки.](/developers/docs/development-networks/) + +### Тестирование контрактов в тестовых сетях {#testing-contracts-on-testnets} + +Тестовая сеть работает точно так же, как основная сеть Ethereum, за исключением того, что в ней используется эфир (ETH), не имеющий реальной ценности. Развертывание вашего контракта в [тестовой сети](/developers/docs/networks/#ethereum-testnets) означает, что любой может взаимодействовать с ним (например, через интерфейс децентрализованного приложения), не рискуя средствами. + +Эта форма ручного тестирования полезна для оценки сквозного потока вашего приложения с точки зрения пользователя. Здесь бета-тестеры также могут проводить пробные запуски и сообщать о любых проблемах с бизнес-логикой контракта и общей функциональностью. + +Развертывание в тестовой сети после тестирования на локальном блокчейне является идеальным, поскольку первая ближе к поведению виртуальной машины Ethereum. Поэтому для многих нативных проектов Ethereum является обычным делом развертывать децентрализованные приложения в тестовых сетях для оценки работы смарт-контрактов в реальных условиях. + +[Подробнее о тестовых сетях Ethereum.](/developers/docs/development-networks/#public-beacon-testchains) + +## Тестирование и формальная верификация {#testing-vs-formal-verification} + +Хотя тестирование помогает подтвердить, что контракт возвращает ожидаемые результаты для некоторых входных данных, оно не может окончательно доказать то же самое для входных данных, не использовавшихся во время тестов. Таким образом, тестирование смарт-контракта не может гарантировать «функциональную правильность» (т. е. не может показать, что программа ведет себя так, как требуется для _всех_ наборов входных значений). + +Формальная верификация — это подход к оценке правильности программного обеспечения путем проверки соответствия формальной модели программы формальной спецификации. Формальная модель — это абстрактное математическое представление программы, а формальная спецификация определяет свойства программы (т. е. логические утверждения о выполнении программы). + +Поскольку свойства написаны в математических терминах, становится возможным проверить, что формальная (математическая) модель системы удовлетворяет спецификации, используя логические правила вывода. Таким образом, считается, что инструменты формальной верификации производят «математическое доказательство» правильности системы. + +В отличие от тестирования, формальная верификация может быть использована для проверки того, что выполнение смарт-контракта удовлетворяет формальной спецификации для _всех_ выполнений (т. е. не имеет ошибок), без необходимости выполнять его с выборочными данными. Это не только сокращает время, затрачиваемое на запуск десятков модульных тестов, но и более эффективно для выявления скрытых уязвимостей. Тем не менее, методы формальной верификации лежат в спектре в зависимости от сложности их реализации и полезности. + +[Подробнее о формальной верификации для смарт-контрактов.](/developers/docs/smart-contracts/formal-verification) + +## Тестирование, аудиты и программы поощрения за поиск ошибок {#testing-vs-audits-bug-bounties} + +Как уже упоминалось, тщательное тестирование редко может гарантировать отсутствие ошибок в контракте; подходы формальной верификации могут дать более надежные гарантии правильности, но в настоящее время их сложно использовать, и они сопряжены со значительными затратами. + +Тем не менее, вы можете еще больше увеличить вероятность выявления уязвимостей контракта, получив независимую проверку кода. [Аудиты смарт-контрактов](https://www.immunebytes.com/blog/what-is-a-smart-contract-audit/) и [программы поощрения за поиск ошибок](https://medium.com/immunefi/a-defi-security-standard-the-scaling-bug-bounty-9b83dfdc1ba7) — это два способа заставить других проанализировать ваши контракты. + +Аудиты проводятся аудиторами, имеющими опыт в поиске недостатков безопасности и плохих практик разработки в смарт-контрактах. Аудит обычно включает тестирование (и, возможно, формальную верификацию), а также ручную проверку всей кодовой базы. + +И наоборот, программа поощрения за поиск ошибок обычно включает в себя предложение финансового вознаграждения человеку (обычно называемому [«белым» хакером](https.en.wikipedia.org/wiki/White_hat_\(computer_security\))), который обнаруживает уязвимость в смарт-контракте и сообщает о ней разработчикам. Программы поощрения за поиск ошибок похожи на аудиты, поскольку они предполагают просьбу о помощи в поиске дефектов в смарт-контрактах. + +Основное отличие заключается в том, что программы поощрения за поиск ошибок открыты для более широкого сообщества разработчиков/хакеров и привлекают широкий круг этичных хакеров и независимых специалистов по безопасности с уникальными навыками и опытом. Это может быть преимуществом перед аудитами смарт-контрактов, которые в основном полагаются на команды, которые могут обладать ограниченным или узким опытом. + +## Инструменты и библиотеки для тестирования {#testing-tools-and-libraries} + +### Инструменты модульного тестирования {#unit-testing-tools} + +- **[solidity-coverage](https://github.com/sc-forks/solidity-coverage)** — _инструмент для определения покрытия кода для смарт-контрактов, написанных на Solidity._ + +- **[Waffle](https://ethereum-waffle.readthedocs.io/en/latest/)** — _фреймворк для продвинутой разработки и тестирования смарт-контрактов (на базе ethers.js)_. + +- **[Remix Tests](https://github.com/ethereum/remix-project/tree/master/libs/remix-tests)** — _инструмент для тестирования смарт-контрактов Solidity. Работает под плагином Remix IDE «Solidity Unit Testing», который используется для написания и запуска тестовых случаев для контракта._ + +- **[OpenZeppelin Test Helpers](https://github.com/OpenZeppelin/openzeppelin-test-helpers)** — _библиотека утверждений для тестирования смарт-контрактов Ethereum. Убедитесь, что ваши контракты работают должным образом!_ + +- **[Фреймворк модульного тестирования Brownie](https://eth-brownie.readthedocs.io/en/v1.0.0_a/tests.html)** — _Brownie использует Pytest, многофункциональный тестовый фреймворк, который позволяет писать небольшие тесты с минимальным кодом, хорошо масштабируется для больших проектов и обладает высокой расширяемостью._ + +- **[Foundry Tests](https://github.com/foundry-rs/foundry/tree/master/crates/forge)** — _Foundry предлагает Forge, быстрый и гибкий фреймворк для тестирования Ethereum, способный выполнять простые модульные тесты, проверки оптимизации газа и фаззинг контрактов._ + +- **[Hardhat Tests](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)** — _фреймворк для тестирования смарт-контрактов на основе ethers.js, Mocha и Chai._ + +- **[ApeWorx](https://docs.apeworx.io/ape/stable/userguides/testing.html)** — _фреймворк для разработки и тестирования на Python для смарт-контрактов, предназначенных для виртуальной машины Ethereum._ + +- **[Wake](https://ackeeblockchain.com/wake/docs/latest/testing-framework/overview/)** — _фреймворк на Python для модульного тестирования и фаззинга с мощными возможностями отладки и поддержкой кросс-чейн тестирования, использующий pytest и Anvil для лучшего пользовательского опыта и производительности._ + +### Инструменты тестирования на основе свойств {#property-based-testing-tools} + +#### Инструменты статического анализа {#static-analysis-tools} + +- **[Slither](https://github.com/crytic/slither)** — _фреймворк для статического анализа Solidity на Python для поиска уязвимостей, улучшения понимания кода и написания пользовательских анализов для смарт-контрактов._ + +- **[Ethlint](https://ethlint.readthedocs.io/en/latest/)** — _линтер для обеспечения соблюдения стиля и лучших практик безопасности для языка программирования смарт-контрактов Solidity._ + +- **[Cyfrin Aderyn](https://cyfrin.io/tools/aderyn)** — _статический анализатор на Rust, специально разработанный для безопасности и разработки смарт-контрактов Web3._ + +- **[Wake](https://ackeeblockchain.com/wake/docs/latest/static-analysis/using-detectors/)** — _фреймворк для статического анализа на Python с детекторами уязвимостей и качества кода, принтерами для извлечения полезной информации из кода и поддержкой написания пользовательских подмодулей._ + +- **[Slippy](https://github.com/fvictorio/slippy)** — _простой и мощный линтер для Solidity._ + +#### Инструменты динамического анализа {#dynamic-analysis-tools} + +- **[Echidna](https://github.com/crytic/echidna/)** — _быстрый фаззер контрактов для обнаружения уязвимостей в смарт-контрактах с помощью тестирования на основе свойств._ + +- **[Diligence Fuzzing](https://consensys.net/diligence/fuzzing/)** — _автоматизированный инструмент фаззинга, полезный для обнаружения нарушений свойств в коде смарт-контракта._ + +- **[Manticore](https://manticore.readthedocs.io/en/latest/index.html)** — _фреймворк динамического символического выполнения для анализа байт-кода EVM._ + +- **[Mythril](https://github.com/ConsenSys/mythril-classic)** — _инструмент оценки байт-кода EVM для обнаружения уязвимостей контрактов с использованием анализа заражения, конколического анализа и проверки потока управления._ + +- **[Diligence Scribble](https://consensys.net/diligence/scribble/)** — _Scribble — это язык спецификаций и инструмент верификации во время выполнения, который позволяет аннотировать смарт-контракты свойствами, позволяющими автоматически тестировать контракты с помощью таких инструментов, как Diligence Fuzzing или MythX._ + +## Связанные руководства {#related-tutorials} + +- [Обзор и сравнение различных продуктов для тестирования](/developers/tutorials/guide-to-smart-contract-security-tools/) \_ +- [Как использовать Echidna для тестирования смарт-контрактов](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/) +- [Как использовать Manticore для поиска ошибок в умных контрактах](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/) +- [Как использовать Slither для поиска ошибок в умных контрактах](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) +- [Как создавать заглушки для контрактов Solidity для тестирования](/developers/tutorials/how-to-mock-solidity-contracts-for-testing/) +- [Как запускать модульные тесты в Solidity с помощью Foundry](https://www.rareskills.io/post/foundry-testing-solidity) + +## Дополнительные материалы {#further-reading} + +- [Подробное руководство по тестированию смарт-контрактов Ethereum](https://iamdefinitelyahuman.medium.com/an-in-depth-guide-to-testing-ethereum-smart-contracts-2e41b2770297) +- [Как тестировать смарт-контракты Ethereum](https://betterprogramming.pub/how-to-test-ethereum-smart-contracts-35abc8fa199d) +- [Руководство MolochDAO по модульному тестированию для разработчиков](https://github.com/MolochVentures/moloch/tree/4e786db8a4aa3158287e0935dcbc7b1e43416e38/test#moloch-testing-guide) +- [Как тестировать смарт-контракты как рок-звезда](https://forum.openzeppelin.com/t/test-smart-contracts-like-a-rockstar/1001) diff --git a/public/content/translations/ru/developers/docs/smart-contracts/upgrading/index.md b/public/content/translations/ru/developers/docs/smart-contracts/upgrading/index.md new file mode 100644 index 00000000000..cb348952717 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/upgrading/index.md @@ -0,0 +1,165 @@ +--- +title: "Обновление смарт-контрактов" +description: "Обзор шаблонов обновления для смарт-контрактов Ethereum" +lang: ru +--- + +Смарт-контракты в Ethereum — это самоисполняемые программы, которые работают в виртуальной машине Ethereum (EVM). Эти программы по своей сути неизменяемы, что предотвращает любые обновления бизнес-логики после развертывания контракта. + +Хотя неизменяемость необходима для отсутствия доверия, децентрализации и безопасности смарт-контрактов, в некоторых случаях она может быть недостатком. Например, неизменяемый код может сделать невозможным для разработчиков исправление уязвимых контрактов. + +Однако расширенные исследования по улучшению смарт-контрактов привели к появлению нескольких шаблонов обновления. Эти шаблоны обновления позволяют разработчикам обновлять смарт-контракты (сохраняя при этом неизменяемость), размещая бизнес-логику в разных контрактах. + +## Предварительные условия {#prerequisites} + +Вы должны хорошо разбираться в [смарт-контрактах](/developers/docs/smart-contracts/), [анатомии смарт-контрактов](/developers/docs/smart-contracts/anatomy/) и [виртуальной машине Ethereum (EVM)](/developers/docs/evm/). Это руководство также предполагает, что читатели знакомы с программированием смарт-контрактов. + +## Что такое обновление смарт-контракта? {#what-is-a-smart-contract-upgrade} + +Обновление смарт-контракта включает в себя изменение бизнес-логики смарт-контракта при сохранении состояния контракта. Важно уточнить, что обновляемость и изменяемость — это не одно и то же, особенно в контексте смарт-контрактов. + +Вы по-прежнему не можете изменить программу, развернутую по адресу в сети Ethereum. Но вы можете изменить код, который выполняется, когда пользователи взаимодействуют со смарт-контрактом. + +Это можно сделать следующими способами: + +1. Создание нескольких версий смарт-контракта и перенос состояния (т. е. данных) из старого контракта в новый экземпляр контракта. + +2. Создание отдельных контрактов для хранения бизнес-логики и состояния. + +3. Использование прокси-шаблонов для делегирования вызовов функций от неизменяемого прокси-контракта к изменяемому контракту логики. + +4. Создание неизменяемого основного контракта, который взаимодействует с гибкими сателлитными контрактами и полагается на них для выполнения определенных функций. + +5. Использование алмазного шаблона (diamond pattern) для делегирования вызовов функций от прокси-контракта к контрактам логики. + +### Механизм обновления №1: миграция контракта {#contract-migration} + +Миграция контракта основана на управлении версиями — идее создания и управления уникальными состояниями одного и того же программного обеспечения. Миграция контракта включает в себя развертывание нового экземпляра существующего смарт-контракта и перенос хранилища и балансов в новый контракт. + +Вновь развернутый контракт будет иметь пустое хранилище, что позволит вам восстановить данные из старого контракта и записать их в новую реализацию. После этого вам нужно будет обновить все контракты, которые взаимодействовали со старым контрактом, чтобы отразить новый адрес. + +Последний шаг в миграции контракта — убедить пользователей перейти на использование нового контракта. Новая версия контракта сохранит балансы и адреса пользователей, что обеспечивает неизменность. Если это контракт на основе токенов, вам также нужно будет связаться с биржами, чтобы они отказались от старого контракта и использовали новый. + +Миграция контрактов — это относительно простая и безопасная мера для обновления смарт-контрактов без нарушения взаимодействия с пользователем. Однако ручной перенос пользовательского хранилища и балансов в новый контракт требует много времени и может повлечь за собой высокие затраты на газ. + +[Подробнее о миграции контрактов.](https://blog.trailofbits.com/2018/10/29/how-contract-migration-works/) + +### Механизм обновления №2: разделение данных {#data-separation} + +Другой метод обновления смарт-контрактов — разделение бизнес-логики и хранения данных на отдельные контракты. Это означает, что пользователи взаимодействуют с контрактом логики, а данные хранятся в контракте хранилища. + +Контракт логики содержит код, выполняемый, когда пользователи взаимодействуют с приложением. Он также содержит адрес контракта хранилища и взаимодействует с ним для получения и установки данных. + +Между тем, контракт хранилища содержит состояние, связанное со смарт-контрактом, такое как балансы и адреса пользователей. Обратите внимание, что контракт хранилища принадлежит контракту логики и настраивается с адресом последнего при развертывании. Это предотвращает вызов контракта хранилища или обновление его данных неавторизованными контрактами. + +По умолчанию контракт хранилища является неизменяемым, но вы можете заменить контракт логики, на который он указывает, новой реализацией. Это изменит код, который выполняется в EVM, при этом сохраняя хранилище и балансы нетронутыми. + +Использование этого метода обновления требует обновления адреса контракта логики в контракте хранилища. Вы также должны настроить новый контракт логики с адресом контракта хранилища по причинам, объясненным ранее. + +Шаблон разделения данных, возможно, проще реализовать по сравнению с миграцией контрактов. Однако вам придется управлять несколькими контрактами и реализовывать сложные схемы авторизации для защиты смарт-контрактов от вредоносных обновлений. + +### Механизм обновления №3: прокси-шаблоны {#proxy-patterns} + +Прокси-шаблон также использует разделение данных для хранения бизнес-логики и данных в отдельных контрактах. Однако в прокси-шаблоне контракт хранилища (называемый прокси) вызывает контракт логики во время выполнения кода. Это обратный метод разделения данных, где контракт логики вызывает контракт хранилища. + +Вот что происходит в прокси-шаблоне: + +1. Пользователи взаимодействуют с прокси-контрактом, который хранит данные, но не содержит бизнес-логику. + +2. Прокси-контракт хранит адрес контракта логики и делегирует все вызовы функций контракту логики (который содержит бизнес-логику) с помощью функции `delegatecall`. + +3. После того как вызов перенаправляется в контракт логики, возвращенные из него данные извлекаются и возвращаются пользователю. + +Использование прокси-шаблонов требует понимания функции **delegatecall**. По сути, `delegatecall` — это опкод, который позволяет одному контракту вызывать другой, при этом фактическое выполнение кода происходит в контексте вызывающего контракта. Следствием использования `delegatecall` в прокси-шаблонах является то, что прокси-контракт читает и записывает данные в свое хранилище и выполняет логику, хранящуюся в контракте логики, как если бы вызывал внутреннюю функцию. + +Из [документации Solidity](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries): + +> _Существует специальный вариант вызова сообщения, называемый **delegatecall**, который идентичен вызову сообщения, за исключением того, что код по целевому адресу выполняется в контексте (т. е. по адресу) вызывающего контракта, а `msg.sender` и `msg.value` не меняют своих значений._ _Это означает, что контракт может динамически загружать код с другого адреса во время выполнения._ _Хранилище, текущий адрес и баланс по-прежнему относятся к вызывающему контракту, только код берется с вызываемого адреса._ + +Прокси-контракт знает, что нужно вызывать `delegatecall` всякий раз, когда пользователь вызывает функцию, потому что в него встроена функция `fallback`. В программировании на Solidity [резервная функция (fallback function)](https://docs.soliditylang.org/en/latest/contracts.html#fallback-function) выполняется, когда вызов функции не соответствует ни одной из функций, указанных в контракте. + +Чтобы прокси-шаблон работал, необходимо написать собственную резервную функцию (fallback function), которая определяет, как прокси-контракт должен обрабатывать вызовы функций, которые он не поддерживает. В этом случае резервная функция (fallback function) прокси-контракта запрограммирована на запуск delegatecall и перенаправление запроса пользователя к текущей реализации контракта логики. + +Прокси-контракт по умолчанию является неизменяемым, но можно создавать новые контракты логики с обновленной бизнес-логикой. Выполнение обновления сводится к изменению адреса контракта логики, на который ссылается прокси-контракт. + +Указав прокси-контракту на новый контракт логики, вы изменяете код, который выполняется, когда пользователи вызывают функцию прокси-контракта. Это позволяет нам обновлять логику контракта, не прося пользователей взаимодействовать с новым контрактом. + +Прокси-шаблоны — популярный метод обновления смарт-контрактов, поскольку они устраняют трудности, связанные с миграцией контрактов. Однако прокси-шаблоны сложнее в использовании и могут привести к критическим ошибкам, таким как [столкновения селекторов функций](https://medium.com/nomic-foundation-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357), при неправильном использовании. + +[Подробнее о прокси-шаблонах](https://blog.openzeppelin.com/proxy-patterns/). + +### Механизм обновления №4: шаблон «Стратегия» {#strategy-pattern} + +Этот метод основан на [шаблоне «Стратегия»](https://en.wikipedia.org/wiki/Strategy_pattern), который поощряет создание программ, взаимодействующих с другими программами для реализации определенных функций. Применение шаблона «Стратегия» к разработке на Ethereum будет означать создание смарт-контракта, который вызывает функции из других контрактов. + +Основной контракт в этом случае содержит основную бизнес-логику, но взаимодействует с другими смарт-контрактами («сателлитными контрактами») для выполнения определенных функций. Этот основной контракт также хранит адрес каждого сателлитного контракта и может переключаться между различными реализациями сателлитного контракта. + +Вы можете создать новый сателлитный контракт и настроить основной контракт с новым адресом. Это позволяет вам изменять _стратегии_ (т. е. реализовывать новую логику) для смарт-контракта. + +Хотя шаблон «Стратегия» похож на ранее обсуждавшийся прокси-шаблон, он отличается тем, что основной контракт, с которым взаимодействуют пользователи, содержит бизнес-логику. Использование этого шаблона дает вам возможность вносить ограниченные изменения в смарт-контракт, не затрагивая основную инфраструктуру. + +Основным недостатком является то, что этот шаблон в основном полезен для внедрения незначительных обновлений. Кроме того, если основной контракт скомпрометирован (например, в результате взлома), вы не сможете использовать этот метод обновления. + +### Механизм обновления №5: алмазный шаблон (diamond pattern) {#diamond-pattern} + +Алмазный шаблон (diamond pattern) можно считать усовершенствованием прокси-шаблона. Алмазные шаблоны (diamond patterns) отличаются от прокси-шаблонов тем, что алмазный прокси-контракт может делегировать вызовы функций более чем одному контракту логики. + +Контракты логики в алмазном шаблоне (diamond pattern) известны как _фасеты_ (facets). Чтобы заставить работать алмазный шаблон (diamond pattern), вам нужно создать сопоставление в прокси-контракте, которое связывает [селекторы функций](https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector) с адресами различных фасетов. + +Когда пользователь совершает вызов функции, прокси-контракт проверяет сопоставление, чтобы найти фасет, ответственный за выполнение этой функции. Затем он вызывает `delegatecall` (используя резервную функцию (fallback function)) и перенаправляет вызов в соответствующий контракт логики. + +Шаблон обновления «Алмаз» (diamond) имеет некоторые преимущества перед традиционными шаблонами обновления прокси: + +1. Он позволяет обновлять небольшую часть контракта, не изменяя весь код. Использование прокси-шаблона для обновлений требует создания совершенно нового контракта логики, даже для незначительных обновлений. + +2. Все смарт-контракты (включая контракты логики, используемые в прокси-шаблонах) имеют ограничение по размеру в 24 КБ, что может быть ограничением, особенно для сложных контрактов, требующих большего количества функций. Алмазный шаблон (diamond pattern) позволяет легко решить эту проблему, разделив функции между несколькими контрактами логики. + +3. Прокси-шаблоны используют универсальный подход к контролю доступа. Субъект, имеющий доступ к функциям обновления, может изменить _весь_ контракт. Но алмазный шаблон (diamond pattern) позволяет использовать модульный подход к разрешениям, при котором вы можете ограничить права субъектов на обновление определенных функций в смарт-контракте. + +[Подробнее об алмазном шаблоне (diamond pattern)](https://eip2535diamonds.substack.com/p/introduction-to-the-diamond-standard?s=w). + +## Плюсы и минусы обновления смарт-контрактов {#pros-and-cons-of-upgrading-smart-contracts} + +| Преимущества | Недостатки | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Обновление смарт-контракта может облегчить исправление уязвимостей, обнаруженных на этапе после развертывания. | Обновление смарт-контрактов сводит на нет идею неизменяемости кода, что имеет последствия для децентрализации и безопасности. | +| Разработчики могут использовать обновления логики для добавления новых функций в децентрализованные приложения. | Пользователи должны доверять разработчикам в том, что они не будут произвольно изменять смарт-контракты. | +| Обновления смарт-контрактов могут повысить безопасность для конечных пользователей, поскольку ошибки можно быстро исправлять. | Программирование функциональности обновления в смарт-контракты добавляет еще один уровень сложности и увеличивает вероятность критических недостатков. | +| Обновления контрактов дают разработчикам больше возможностей для экспериментов с различными функциями и улучшения децентрализованных приложений с течением времени. | Возможность обновления смарт-контрактов может побудить разработчиков быстрее запускать проекты, не проводя должной проверки на этапе разработки. | +| | Небезопасный контроль доступа или централизация в смарт-контрактах могут облегчить злоумышленникам выполнение несанкционированных обновлений. | + +## Вопросы, которые следует учитывать при обновлении смарт-контрактов {#considerations-for-upgrading-smart-contracts} + +1. Используйте безопасные механизмы контроля доступа/авторизации для предотвращения несанкционированных обновлений смарт-контрактов, особенно при использовании прокси-шаблонов, шаблонов стратегий или разделения данных. Примером является ограничение доступа к функции обновления, чтобы ее мог вызывать только владелец контракта. + +2. Обновление смарт-контрактов — это сложная деятельность, требующая высокого уровня осмотрительности для предотвращения появления уязвимостей. + +3. Уменьшите необходимость в доверии за счет децентрализации процесса внедрения обновлений. Возможные стратегии включают использование [контракта кошелька с мультиподписью](/developers/docs/smart-contracts/#multisig) для контроля обновлений или требование к [членам DAO](/dao/) голосовать за утверждение обновления. + +4. Помните о затратах, связанных с обновлением контрактов. Например, копирование состояния (например, балансов пользователей) из старого контракта в новый во время миграции контракта может потребовать более одной транзакции, что означает более высокую плату за газ. + +5. Рассмотрите возможность внедрения **временных замков (timelocks)** для защиты пользователей. Временной замок (timelock) — это задержка, применяемая к изменениям в системе. Временные замки (timelocks) можно комбинировать с системой управления с мультиподписью для контроля обновлений: если предлагаемое действие достигает необходимого порога одобрения, оно не выполняется до истечения заранее определенного периода задержки. + +Временные замки (timelocks) дают пользователям время выйти из системы, если они не согласны с предлагаемым изменением (например, обновлением логики или новыми схемами комиссий). Без временных замков (timelocks) пользователям приходится доверять разработчикам в том, что они не будут вносить произвольные изменения в смарт-контракт без предварительного уведомления. Недостаток здесь в том, что временные замки (timelocks) ограничивают возможность быстрого исправления уязвимостей. + +## Ресурсы {#resources} + +**OpenZeppelin Upgrades Plugins — _набор инструментов для развертывания и защиты обновляемых смарт-контрактов._** + +- [GitHub](https://github.com/OpenZeppelin/openzeppelin-upgrades) +- [Документация](https://docs.openzeppelin.com/upgrades) + +## Руководства {#tutorials} + +- [Обновление ваших смарт-контрактов | Учебное пособие на YouTube](https://www.youtube.com/watch?v=bdXJmWajZRY) от Патрика Коллинза +- [Учебное пособие по миграции смарт-контрактов Ethereum](https://medium.com/coinmonks/ethereum-smart-contract-migration-13f6f12539bd) от Остина Гриффита +- [Использование прокси-шаблона UUPS для обновления смарт-контрактов](https://blog.logrocket.com/author/praneshas/) от Пранеша А.С. +- [Учебное пособие по Web3: написание обновляемого смарт-контракта (прокси) с использованием OpenZeppelin](https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916) от fangjun.eth + +## Дополнительные материалы {#further-reading} + +- [Состояние обновлений смарт-контрактов](https://blog.openzeppelin.com/the-state-of-smart-contract-upgrades/) от Сантьяго Палладино +- [Несколько способов обновить смарт-контракт Solidity](https://cryptomarketpool.com/multiple-ways-to-upgrade-a-solidity-smart-contract/) — блог Crypto Market Pool +- [Обучение: обновление смарт-контрактов](https://docs.openzeppelin.com/learn/upgrading-smart-contracts) — документация OpenZeppelin +- [Прокси-шаблоны для возможности обновления контрактов Solidity: Transparent и UUPS прокси](https://mirror.xyz/0xB38709B8198d147cc9Ff9C133838a044d78B064B/M7oTptQkBGXxox-tk9VJjL66E1V8BUF0GF79MMK4YG0) от Навина Саху +- [Как работают обновления Diamond](https://dev.to/mudgen/how-diamond-upgrades-work-417j) от Ника Маджа diff --git a/public/content/translations/ru/developers/docs/smart-contracts/verifying/index.md b/public/content/translations/ru/developers/docs/smart-contracts/verifying/index.md new file mode 100644 index 00000000000..dae808adfd2 --- /dev/null +++ b/public/content/translations/ru/developers/docs/smart-contracts/verifying/index.md @@ -0,0 +1,113 @@ +--- +title: "Проверка смарт-контрактов" +description: "Обзор верификации исходного кода для смарт-контрактов Ethereum" +lang: ru +--- + +[Смарт-контракты](/developers/docs/smart-contracts/) спроектированы как «бездоверительные», что означает, что пользователям не нужно доверять третьим лицам (например, разработчикам и компаниям) перед взаимодействием с контрактом. В качестве обязательного условия для бездоверительности пользователи и другие разработчики должны иметь возможность верифицировать исходный код смарт-контракта. Верификация исходного кода гарантирует пользователям и разработчикам, что опубликованный код контракта является тем же кодом, который выполняется по адресу контракта в блокчейне Ethereum. + +Важно различать «верификацию исходного кода» и «[формальную верификацию](/developers/docs/smart-contracts/formal-verification/)». Верификация исходного кода, которая будет подробно объяснена ниже, относится к проверке того, что данный исходный код смарт-контракта на языке высокого уровня (например, Solidity) компилируется в тот же байт-код, который должен выполняться по адресу контракта. Однако формальная верификация описывает проверку правильности смарт-контракта, то есть того, что контракт ведет себя так, как ожидалось. Хотя это зависит от контекста, верификация контракта обычно относится к верификации исходного кода. + +## Что такое верификация исходного кода? {#what-is-source-code-verification} + +Перед развертыванием смарт-контракта в [виртуальной машине Ethereum (EVM)](/developers/docs/evm/) разработчики [компилируют](/developers/docs/smart-contracts/compiling/) исходный код контракта — инструкции, [написанные на Solidity](/developers/docs/smart-contracts/languages/) или другом высокоуровневом языке программирования, — в байт-код. Поскольку EVM не может интерпретировать высокоуровневые инструкции, компиляция исходного кода в байт-код (т. е. низкоуровневые машинные инструкции) необходима для выполнения логики контракта в EVM. + +Верификация исходного кода — это сравнение исходного кода смарт-контракта и скомпилированного байт-кода, использованного при создании контракта, для обнаружения любых различий. Верификация смарт-контрактов важна, потому что рекламируемый код контракта может отличаться от того, что работает в блокчейне. + +Верификация смарт-контракта позволяет исследовать, что делает контракт, с помощью языка более высокого уровня, на котором он написан, без необходимости читать машинный код. Функции, значения и обычно имена переменных и комментарии остаются такими же, как в исходном коде, который компилируется и развертывается. Это значительно облегчает чтение кода. Верификация исходного кода также предусматривает документирование кода, чтобы конечные пользователи знали, для чего предназначен смарт-контракт. + +### Что такое полная верификация? {#full-verification} + +Есть некоторые части исходного кода, которые не влияют на скомпилированный байт-код, например комментарии или имена переменных. Это означает, что два исходных кода с разными именами переменных и разными комментариями могут верифицировать один и тот же контракт. Таким образом, злоумышленник может добавить вводящие в заблуждение комментарии или дать неверные имена переменных в исходном коде, и контракт будет верифицирован с исходным кодом, отличным от оригинального. + +Этого можно избежать, добавив к байт-коду дополнительные данные, которые будут служить _криптографической гарантией_ точности исходного кода и _отпечатком_ информации о компиляции. Необходимая информация находится в [метаданных контракта Solidity](https://docs.soliditylang.org/en/v0.8.15/metadata.html), и хэш этого файла добавляется к байт-коду контракта. Вы можете увидеть это в действии на [площадке для работы с метаданными](https://playground.sourcify.dev) + +Файл метаданных содержит информацию о компиляции контракта, включая исходные файлы и их хэши. Это означает, что если изменятся какие-либо параметры компиляции или даже один байт в одном из исходных файлов, файл метаданных изменится. Следовательно, хэш файла метаданных, который добавляется к байт-коду, также изменяется. Это означает, что если байт-код контракта + добавленный хэш метаданных совпадают с заданным исходным кодом и настройками компиляции, мы можем быть уверены, что это точно тот же исходный код, который использовался при первоначальной компиляции, и в нем не отличается ни один байт. + +Этот тип верификации, использующий хэш метаданных, называется **«[полной верификацией](https://docs.sourcify.dev/docs/full-vs-partial-match/)»** (также «идеальной верификацией»). Если хэши метаданных не совпадают или не учитываются при верификации, это будет «частичное совпадение», что в настоящее время является более распространенным способом верификации контрактов. Без полной верификации возможно [внедрение вредоносного кода](https://samczsun.com/hiding-in-plain-sight/), который не будет отражен в верифицированном исходном коде. Большинство разработчиков не знают о полной верификации и не сохраняют файл метаданных своей компиляции, поэтому частичная верификация до сих пор является методом верификации контрактов де-факто. + +## Почему важна верификация исходного кода? {#importance-of-source-code-verification} + +### Бездоверительность {#trustlessness} + +Бездоверительность — это, пожалуй, самая главная предпосылка для смарт-контрактов и [децентрализованных приложений (dapps)](/developers/docs/dapps/). Смарт-контракты являются «неизменяемыми» и не могут быть изменены; контракт будет выполнять только ту бизнес-логику, которая определена в коде на момент развертывания. Это означает, что разработчики и предприятия не могут вмешиваться в код контракта после его развертывания в Ethereum. + +Чтобы смарт-контракт был бездоверительным, его код должен быть доступен для независимой верификации. Хотя скомпилированный байт-код для каждого смарт-контракта общедоступен в блокчейне, низкоуровневый язык трудно понять как разработчикам, так и пользователям. + +Проекты снижают необходимость в доверии, публикуя исходный код своих контрактов. Но это приводит к другой проблеме: трудно проверить, что опубликованный исходный код соответствует байт-коду контракта. В этом случае ценность бездоверительности теряется, потому что пользователям приходится доверять разработчикам в том, что они не изменят бизнес-логику контракта (т. е. изменив байт-код) перед его развертыванием в блокчейне. + +Инструменты верификации исходного кода предоставляют гарантии того, что файлы исходного кода смарт-контракта соответствуют ассемблерному коду. Результатом является бездоверительная экосистема, в которой пользователи не доверяют слепо третьим сторонам, а верифицируют код перед внесением средств в контракт. + +### Безопасность пользователя {#user-safety} + +В смарт-контрактах на кону обычно стоят большие деньги. Это требует более высоких гарантий безопасности и верификации логики смарт-контракта перед его использованием. Проблема в том, что недобросовестные разработчики могут обмануть пользователей, вставив в смарт-контракт вредоносный код. Без верификации вредоносные смарт-контракты могут иметь [бэкдоры](https://www.trustnodes.com/2018/11/10/concerns-rise-over-backdoored-smart-contracts), спорные механизмы контроля доступа, эксплуатируемые уязвимости и другие вещи, которые ставят под угрозу безопасность пользователей и остаются незамеченными. + +Публикация файлов исходного кода смарт-контракта облегчает заинтересованным сторонам, таким как аудиторы, оценку контракта на предмет потенциальных векторов атаки. Когда несколько сторон независимо друг от друга верифицируют смарт-контракт, пользователи получают более надежные гарантии его безопасности. + +## Как верифицировать исходный код для смарт-контрактов Ethereum {#source-code-verification-for-ethereum-smart-contracts} + +[Развертывание смарт-контракта в Ethereum](/developers/docs/smart-contracts/deploying/) требует отправки транзакции с полезной нагрузкой данных (скомпилированным байт-кодом) на специальный адрес. Полезная нагрузка данных генерируется путем компиляции исходного кода, а также [аргументы конструктора](https://docs.soliditylang.org/en/v0.8.14/contracts.html#constructor) экземпляра контракта, добавляемые к полезной нагрузке данных в транзакции. Компиляция детерминирована, то есть она всегда дает один и тот же результат (т. е. байт-код контракта), если используются одни и те же исходные файлы и параметры компиляции (например, версия компилятора, оптимизатор). + +![Диаграмма, показывающая верификацию исходного кода смарт-контракта](./source-code-verification.png) + +Верификация смарт-контракта в основном включает в себя следующие шаги: + +1. Передача исходных файлов и параметров компиляции в компилятор. + +2. Компилятор выводит байт-код контракта + +3. Получение байт-кода развернутого контракта по заданному адресу + +4. Сравнение развернутого байт-кода с перекомпилированным байт-кодом. Если коды совпадают, контракт верифицируется с заданным исходным кодом и настройками компиляции. + +5. Кроме того, если хэши метаданных в конце байт-кода совпадают, это будет полное совпадение. + +Обратите внимание, что это упрощенное описание верификации, и существует множество исключений, которые с ним не сработают, например, наличие [неизменяемых переменных](https://docs.sourcify.dev/docs/immutables/). + +## Инструменты верификации исходного кода {#source-code-verification-tools} + +Традиционный процесс верификации контрактов может быть сложным. Вот почему у нас есть инструменты для верификации исходного кода смарт-контрактов, развернутых в Ethereum. Эти инструменты автоматизируют большую часть верификации исходного кода, а также курируют верифицированные контракты для удобства пользователей. + +### Etherscan {#etherscan} + +Хотя Etherscan в основном известен как [обозреватель блокчейна Ethereum](/developers/docs/data-and-analytics/block-explorers/), он также предлагает [сервис верификации исходного кода](https://etherscan.io/verifyContract) для разработчиков и пользователей смарт-контрактов. + +Etherscan позволяет перекомпилировать байт-код контракта из исходной полезной нагрузки данных (исходный код, адрес библиотеки, настройки компилятора, адрес контракта и т. д.) Если перекомпилированный байт-код связан с байт-кодом (и параметрами конструктора) ончейн-контракта, то [контракт считается верифицированным](https://info.etherscan.com/types-of-contract-verification/). + +После верификации исходный код вашего контракта получает метку «Verified» и публикуется на Etherscan, чтобы другие могли его проверить. Он также добавляется в раздел [Verified Contracts](https://etherscan.io/contractsVerified/) — репозиторий смарт-контрактов с верифицированным исходным кодом. + +Etherscan — самый используемый инструмент для верификации контрактов. Однако верификация контрактов на Etherscan имеет недостаток: она не сравнивает **хэш метаданных** ончейн-байт-кода и перекомпилированного байт-кода. Поэтому совпадения в Etherscan являются частичными. + +[Подробнее о верификации контрактов на Etherscan](https://medium.com/etherscan-blog/verifying-contracts-on-etherscan-f995ab772327). + +### Blockscout {#blockscout} + +[Blockscout](https://blockscout.com/) — это обозреватель блокчейна с открытым исходным кодом, который также предоставляет [сервис верификации контрактов](https://eth.blockscout.com/contract-verification) для разработчиков и пользователей смарт-контрактов. Как альтернатива с открытым исходным кодом, Blockscout предлагает прозрачность в том, как выполняется верификация, и позволяет сообществу вносить свой вклад в улучшение процесса верификации. + +Подобно другим сервисам верификации, Blockscout позволяет вам верифицировать исходный код вашего контракта, перекомпилировав байт-код и сравнив его с развернутым контрактом. После верификации ваш контракт получает статус верификации, а исходный код становится общедоступным для аудита и взаимодействия. Верифицированные контракты также перечислены в [репозитории верифицированных контрактов](https://eth.blockscout.com/verified-contracts) Blockscout для удобного просмотра и поиска. + +### Sourcify {#sourcify} + +[Sourcify](https://sourcify.dev/#/verifier) — еще один инструмент для верификации контрактов с открытым исходным кодом, который является децентрализованным. Это не обозреватель блоков, он верифицирует контракты только в [различных сетях на базе EVM](https://docs.sourcify.dev/docs/chains). Он действует как публичная инфраструктура, на основе которой другие инструменты могут создавать свои решения, и нацелен на обеспечение более удобного для человека взаимодействия с контрактами с использованием комментариев [ABI](/developers/docs/smart-contracts/compiling/#web-applications) и [NatSpec](https://docs.soliditylang.org/en/v0.8.15/natspec-format.html), содержащихся в файле метаданных. + +В отличие от Etherscan, Sourcify поддерживает полные совпадения с хэшем метаданных. Верифицированные контракты обслуживаются в его [публичном репозитории](https://docs.sourcify.dev/docs/repository/) по HTTP и [IPFS](https://docs.ipfs.io/concepts/what-is-ipfs/#what-is-ipfs), которое является децентрализованным [хранилищем с адресацией по содержимому](https://docs.storacha.network/concepts/content-addressing/). Это позволяет получать файл метаданных контракта через IPFS, поскольку добавленный хэш метаданных является хэшем IPFS. + +Кроме того, можно также получить файлы исходного кода через IPFS, так как хэши IPFS этих файлов также находятся в метаданных. Контракт можно верифицировать, предоставив файл метаданных и исходные файлы через его API или [пользовательский интерфейс](https://sourcify.dev/#/verifier), или с помощью плагинов. Инструмент мониторинга Sourcify также отслеживает создание контрактов в новых блоках и пытается верифицировать контракты, если их метаданные и исходные файлы опубликованы на IPFS. + +[Подробнее о верификации контрактов на Sourcify](https://soliditylang.org/blog/2020/06/25/sourcify-faq/). + +### Tenderly {#tenderly} + +[Платформа Tenderly](https://tenderly.co/) позволяет разработчикам Web3 создавать, тестировать, отслеживать и эксплуатировать смарт-контракты. Сочетая инструменты отладки с наблюдаемостью и стандартными элементами для создания инфраструктуры, Tenderly помогает разработчикам ускорить разработку смарт-контрактов. Чтобы полностью использовать функции Tenderly, разработчикам необходимо [выполнить верификацию исходного кода](https://docs.tenderly.co/monitoring/contract-verification) с помощью нескольких методов. + +Верифицировать контракт можно в частном или публичном порядке. Если верификация частная, смарт-контракт виден только вам (и другим членам вашего проекта). Публичная верификация контракта делает его видимым для всех, кто использует платформу Tenderly. + +Вы можете верифицировать свои контракты с помощью [панели управления](https://docs.tenderly.co/contract-verification), [плагина Tenderly для Hardhat](https://docs.tenderly.co/contract-verification/hardhat) или [интерфейса командной строки](https://docs.tenderly.co/monitoring/smart-contract-verification/verifying-contracts-using-cli). + +При верификации контрактов через панель управления вам необходимо импортировать исходный файл или файл метаданных, сгенерированный компилятором Solidity, адрес/сеть и настройки компилятора. + +Использование плагина Tenderly для Hardhat позволяет лучше контролировать процесс верификации с меньшими усилиями, давая вам возможность выбирать между автоматической (без кода) и ручной (на основе кода) верификацией. + +## Дополнительные материалы {#further-reading} + +- [Верификация исходного кода контракта](https://programtheblockchain.com/posts/2018/01/16/verifying-contract-source-code/) diff --git a/public/content/translations/ru/developers/docs/standards/index.md b/public/content/translations/ru/developers/docs/standards/index.md new file mode 100644 index 00000000000..4d8beecbc61 --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/index.md @@ -0,0 +1,59 @@ +--- +title: "Стандарты разработки Ethereum" +description: "Узнайте о стандартах Ethereum, включая EIP, стандартах токенов, таких как ERC-20 и ERC-721, и соглашениях по разработке." +lang: ru +incomplete: true +--- + +## Обзор стандартов {#standards-overview} + +Сообщество Ethereum приняло множество стандартов, которые помогают поддерживать совместимость проектов (таких как [клиенты Ethereum](/developers/docs/nodes-and-clients/) и кошельки) в разных реализациях, а также обеспечивать, чтобы смарт-контракты и децентрализованные приложения оставались компонуемыми. + +Обычно стандарты представляются в виде [Предложений по улучшению Ethereum](/eips/) (EIP), которые обсуждаются членами сообщества в рамках [стандартного процесса](https://eips.ethereum.org/EIPS/eip-1). + +- [Введение в EIP](/eips/) +- [Список EIP](https://eips.ethereum.org/) +- [Репозиторий EIP на GitHub](https://github.com/ethereum/EIPs) +- [Доска обсуждений EIP](https://ethereum-magicians.org/c/eips) +- [Введение в управление Ethereum](/governance/) +- [Обзор управления Ethereum](https://web.archive.org/web/20201107234050/https://blog.bmannconsulting.com/ethereum-governance/) _31 марта 2019 г. - Борис Манн_ +- [Управление разработкой протокола Ethereum и координация обновления сети](https://hudsonjameson.com/posts/2020-03-23-ethereum-protocol-development-governance-and-network-upgrade-coordination/) _23 марта 2020 г. - Хадсон Джеймсон_ +- [Плейлист со всеми встречами основных разработчиков Ethereum](https://www.youtube.com/@EthereumProtocol) _(плейлист на YouTube)_ + +## Типы стандартов {#types-of-standards} + +Существует 3 типа EIP: + +- Трек стандартов: описывает любое изменение, которое влияет на большинство или все реализации Ethereum +- [Мета-трек](https://eips.ethereum.org/meta): описывает процесс, связанный с Ethereum, или предлагает внести изменения в процесс +- [Информационный трек](https://eips.ethereum.org/informational): описывает проблему проектирования Ethereum или предоставляет общие рекомендации или информацию сообществу Ethereum + +Кроме того, стандартный путь подразделяется на 4 категории: + +- [Ядро](https://eips.ethereum.org/core): улучшения, требующие форка для достижения консенсуса +- [Сеть](https://eips.ethereum.org/networking): улучшения, связанные с devp2p и «облегченным» подпротоколом Ethereum, а также предлагаемые улучшения спецификаций сетевых протоколов Whisper и Swarm. +- [Интерфейс](https://eips.ethereum.org/interface): улучшения в сфере спецификаций и стандартов API/RPC клиента, а также определенных стандартов на уровне языка, таких как имена методов и ABI контрактов. +- [ERC](https://eips.ethereum.org/erc): стандарты и соглашения на уровне приложений + +Более подробную информацию об этих различных типах и категориях можно найти в [EIP-1](https://eips.ethereum.org/EIPS/eip-1#eip-types) + +### Стандарты токенов {#token-standards} + +- [ERC-20](/developers/docs/standards/tokens/erc-20/) — стандартный интерфейс для взаимозаменяемых токенов, таких как токены для голосования, токены для стейкинга или виртуальные валюты. + - [ERC-223](/developers/docs/standards/tokens/erc-223/) — стандарт взаимозаменяемых токенов, который делает поведение токенов идентичным поведению эфира (ether) и поддерживает обработку передачи токенов на стороне получателей. + - [ERC-1363](/developers/docs/standards/tokens/erc-1363/) — расширение интерфейса для токенов ERC-20, которое поддерживает выполнение обратного вызова в контрактах получателя в одной транзакции. +- [ERC-721](/developers/docs/standards/tokens/erc-721/) — стандартный интерфейс для невзаимозаменяемых токенов, например, свидетельство о праве собственности на произведение искусства или песню. + - [ERC-2309](https://eips.ethereum.org/EIPS/eip-2309) — стандартизированное событие, которое генерируется при создании/передаче одного или нескольких невзаимозаменяемых токенов с использованием последовательных идентификаторов токенов. + - [ERC-4400](https://eips.ethereum.org/EIPS/eip-4400) — расширение интерфейса для роли потребителя EIP-721. + - [ERC-4907](https://eips.ethereum.org/EIPS/eip-4907) — добавляет к токенам ERC-721 ограниченную по времени роль с ограниченными разрешениями. +- [ERC-777](/developers/docs/standards/tokens/erc-777/) — **(НЕ РЕКОМЕНДУЕТСЯ)** стандарт токенов, улучшающий ERC-20. +- [ERC-1155](/developers/docs/standards/tokens/erc-1155/) — стандарт токенов, который может содержать как взаимозаменяемые, так и невзаимозаменяемые активы. +- [ERC-4626](/developers/docs/standards/tokens/erc-4626/) — стандарт токенизированного хранилища, предназначенный для оптимизации и унификации технических параметров доходных хранилищ. + +Узнайте больше о [стандартах токенов](/developers/docs/standards/tokens/). + +## Дополнительные материалы {#further-reading} + +- [Предложения по улучшению Ethereum (EIP)](/eips/) + +_Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!_ diff --git a/public/content/translations/ru/developers/docs/standards/tokens/erc-1155/index.md b/public/content/translations/ru/developers/docs/standards/tokens/erc-1155/index.md new file mode 100644 index 00000000000..d219eaf397c --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/erc-1155/index.md @@ -0,0 +1,146 @@ +--- +title: "Стандарт мульти-токенов ERC-1155" +description: "Узнайте о ERC-1155 — стандарте нескольких токенов, который объединяет взаимозаменяемые и невзаимозаменяемые токены в одном контракте." +lang: ru +--- + +## Введение {#introduction} + +Стандартный интерфейс для контрактов, которые управляют несколькими типами токенов. Один развернутый контракт может включать любую комбинацию взаимозаменяемых токенов, невзаимозаменяемых токенов или других конфигураций (например, полувзаимозаменяемых токенов). + +**Что значит стандарт мульти-токена?** + +Идея проста и предназначена для создания интерфейса смарт-контракта, который может представлять и контролировать любое количество токенов взаимозаменяемых и невзаимозаменяемых типов. Таким образом, токен ERC-1155 может выполнять те же функции, что и токены [ERC-20](/developers/docs/standards/tokens/erc-20/) и [ERC-721](/developers/docs/standards/tokens/erc-721/), и даже обе одновременно. Это повышает функциональность стандартов ERC-20 и ERC-721, что делает их более эффективными и исправляет очевидные ошибки реализации. + +Токен ERC-1155 полностью описан в [EIP-1155](https://eips.ethereum.org/EIPS/eip-1155). + +## Предварительные условия {#prerequisites} + +Чтобы лучше понять эту страницу, мы рекомендуем сначала прочитать о [стандартах токенов](/developers/docs/standards/tokens/), [ERC-20](/developers/docs/standards/tokens/erc-20/) и [ERC-721](/developers/docs/standards/tokens/erc-721/). + +## Функции и возможности ERC-1155: {#body} + +- [Пакетная передача](#batch_transfers): Передача нескольких активов в одном вызове. +- [Пакетный баланс](#batch_balance): Получение балансов нескольких активов за один вызов. +- [Пакетное одобрение](#batch_approval): Одобрение всех токенов для одного адреса. +- [Хуки](#receive_hook): Хук получения токенов. +- [Поддержка NFT](#nft_support): Если объем эмиссии равен 1, токен считается NFT. +- [Правила безопасной передачи](#safe_transfer_rule): Набор правил для безопасной передачи. + +### Пакетные передачи {#batch-transfers} + +Перевод партией работает почти так же, как и обычные ERC-20 переводы. Давайте рассмотрим обычную функцию `transferFrom` стандарта ERC-20: + +```solidity +// ERC-20 +function transferFrom(address from, address to, uint256 value) external returns (bool); + +// ERC-1155 +function safeBatchTransferFrom( + address _from, + address _to, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data +) external; +``` + +Единственное различие в ERC-1155 заключается в том, что мы передаем значения в виде массива и также передаем массив идентификаторов. Например, если `ids=[3, 6, 13]` и `values=[100, 200, 5]`, то в результате будут выполнены следующие передачи: + +1. Передача 100 токенов с ID 3 от `_from` к `_to`. +2. Передача 200 токенов с ID 6 от `_from` к `_to`. +3. Передача 5 токенов с ID 13 от `_from` к `_to`. + +В ERC-1155 есть только `transferFrom`, но нет `transfer`. Чтобы использовать ее как обычную функцию `transfer`, просто укажите в качестве адреса отправителя адрес, вызывающий функцию. + +### Пакетный баланс {#batch-balance} + +Соответствующий вызов `balanceOf` в ERC-20 также имеет парную функцию с поддержкой пакетной обработки. В качестве напоминания версия ERC-20: + +```solidity +// ERC-20 +function balanceOf(address owner) external view returns (uint256); + +// ERC-1155 +function balanceOfBatch( + address[] calldata _owners, + uint256[] calldata _ids +) external view returns (uint256[] memory); +``` + +Даже проще, чем запрос баланса, мы можем получить несколько балансов за один запрос. Мы передаем массив владельцев, а затем массив идентификаторов токенов. + +Например, если `_ids=[3, 6, 13]` и `_owners=[0xbeef..., 0x1337..., 0x1111...]`, возвращаемое значение будет: + +```solidity +[ + balanceOf(0xbeef...), + balanceOf(0x1337...), + balanceOf(0x1111...) +] +``` + +### Пакетное одобрение {#batch-approval} + +```solidity +// ERC-1155 +function setApprovalForAll( + address _operator, + bool _approved +) external; + +function isApprovedForAll( + address _owner, + address _operator +) external view returns (bool); +``` + +Утверждения немного отличаются от ERC-20. Вместо одобрения определенных сумм вы устанавливаете оператора как одобренного или неодобренного с помощью `setApprovalForAll`. + +Проверить текущий статус можно с помощью `isApprovedForAll`. Как вы видите, это операция "все или ничего". Вы не можете выбрать количество токенов для утверждения или даже класс токенов. + +Это сделано намеренно для простоты. Вы можете одобрить все только для одного адреса. + +### Хук получения {#receive-hook} + +```solidity +function onERC1155BatchReceived( + address _operator, + address _from, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data +) external returns(bytes4); +``` + +Благодаря поддержке [EIP-165](https://eips.ethereum.org/EIPS/eip-165), ERC-1155 поддерживает хуки получения только для умных контрактов. Функция-хук должна возвращать предопределенное «магическое» значение типа bytes4, которое задается как: + +```solidity +bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)")) +``` + +Когда принимающий контракт возвращает это значение, считается, что контракт принимает передачу и знает, как обрабатывать токены ERC-1155. Отлично, токены больше не будут застревать в контракте! + +### Поддержка NFT {#nft-support} + +Если объем предложения равен единице, то токен по сути является невзаимозаменяемым (NFT). Как и в стандарте ERC-721, вы можете задать URL метаданных. URL-адрес может считываться и изменяться клиентами, см. [здесь](https://eips.ethereum.org/EIPS/eip-1155#metadata). + +### Правило безопасной передачи {#safe-transfer-rule} + +Мы уже коснулись нескольких правил безопасного перевода в предыдущих объяснениях. Но давайте взглянем на самые важные из правил: + +1. Вызывающий должен иметь разрешение на расходование токенов с адреса `_from` или вызывающий должен быть равен `_from`. +2. Вызов передачи должен быть отменен, если: + 1. адрес `_to` равен 0. + 2. длина `_ids` не совпадает с длиной `_values`. + 3. любой из балансов держателя(-ей) токена(-ов) из `_ids` меньше соответствующего количества из `_values`, отправляемого получателю. + 4. происходит любая другая ошибка. + +_Примечание_: все пакетные функции, включая хук, также существуют в версиях без пакетной обработки. Это сделано для эффективности расходования газа, поскольку передача одного актива, скорее всего, останется наиболее распространенным способом. Мы опустили их для простоты объяснения, включая правила безопасной передачи. Названия идентичны, просто уберите слово «Batch». + +## Дополнительные материалы {#further-reading} + +- [EIP-1155: стандарт нескольких токенов](https://eips.ethereum.org/EIPS/eip-1155) +- [ERC-1155: документация OpenZeppelin](https://docs.openzeppelin.com/contracts/5.x/erc1155) +- [ERC-1155: репозиторий на GitHub](https://github.com/enjin/erc-1155) +- [Alchemy NFT API](https://www.alchemy.com/docs/reference/nft-api-quickstart) diff --git a/public/content/translations/ru/developers/docs/standards/tokens/erc-1363/index.md b/public/content/translations/ru/developers/docs/standards/tokens/erc-1363/index.md new file mode 100644 index 00000000000..f42853a0926 --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/erc-1363/index.md @@ -0,0 +1,213 @@ +--- +title: "Стандарт оплачиваемых токенов ERC-1363" +description: "ERC-1363 — это интерфейс расширения для токенов ERC-20, который поддерживает выполнение пользовательской логики в контракте получателя после переводов или в контракте расходования после одобрений в рамках одной транзакции." +lang: ru +--- + +## Введение {#introduction} + +### Что такое ERC-1363? {#what-is-erc1363} + +ERC-1363 — это интерфейс расширения для токенов ERC-20, который поддерживает выполнение пользовательской логики в контракте получателя после переводов или в контракте расходования после одобрений в рамках одной транзакции. + +### Отличия от ERC-20 {#erc20-differences} + +Стандартные операции ERC-20, такие как `transfer`, `transferFrom` и `approve`, не позволяют выполнять код в контракте получателя или расходования без отдельной транзакции. +Это усложняет разработку пользовательского интерфейса и препятствует внедрению, поскольку пользователи должны дождаться выполнения первой транзакции, а затем отправить вторую. +Им также приходится дважды платить за ГАЗ. + +ERC-1363 позволяет взаимозаменяемым токенам проще выполнять действия и работать без использования каких-либо внесетевых слушателей. +Он позволяет выполнить обратный вызов в контракте получателя или расходования после перевода или одобрения в рамках одной транзакции. + +## Предварительные условия {#prerequisites} + +Чтобы лучше понять эту страницу, мы рекомендуем вам сначала прочитать о: + +- [Стандарты токенов](/developers/docs/standards/tokens/) +- [ERC-20](/developers/docs/standards/tokens/erc-20/) + +## Тело {#body} + +ERC-1363 представляет стандартный API для взаимодействия токенов ERC-20 с умными контрактами после выполнения `transfer`, `transferFrom` или `approve`. + +Этот стандарт предоставляет базовую функциональность для перевода токенов, а также позволяет одобрять токены, чтобы их могла потратить другая внутрисетевая третья сторона, а затем выполнить обратный вызов в контракте получателя или расходования. + +Существует множество предлагаемых вариантов использования умных контрактов, которые могут принимать обратные вызовы ERC-20. + +Примеры: + +- **Краудсейлы**: отправленные токены вызывают мгновенное распределение вознаграждения. +- **Сервисы**: оплата активирует доступ к услуге за один шаг. +- **Счета**: токены автоматически оплачивают счета. +- **Подписки**: одобрение годовой ставки активирует подписку в рамках платежа за первый месяц. + +По этим причинам он изначально назывался **"оплачиваемым токеном"**. + +Поведение обратного вызова еще больше расширяет его полезность, обеспечивая беспрепятственные взаимодействия, такие как: + +- **Стейкинг**: переведенные токены вызывают автоматическую блокировку в контракте стейкинга. +- **Голосование**: полученные токены регистрируют голоса в системе управления. +- **Обмен**: одобрение токенов активирует логику обмена за один шаг. + +Токены ERC-1363 могут использоваться для определенных утилит во всех случаях, когда требуется выполнить обратный вызов после получения перевода или одобрения. +ERC-1363 также полезен для предотвращения потери или блокировки токенов в умных контрактах путем проверки способности получателя обрабатывать токены. + +В отличие от других предложений по расширению ERC-20, ERC-1363 не переопределяет методы ERC-20 `transfer` и `transferFrom` и определяет идентификаторы интерфейсов, которые должны быть реализованы, сохраняя обратную совместимость с ERC-20. + +Из [EIP-1363](https://eips.ethereum.org/EIPS/eip-1363): + +### Методы {#methods} + +Умные контракты, реализующие стандарт ERC-1363, **ДОЛЖНЫ** реализовывать все функции интерфейса `ERC1363`, а также интерфейсов `ERC20` и `ERC165`. + +```solidity +pragma solidity ^0.8.0; + +/** + * @title ERC1363 + * @dev Интерфейс расширения для токенов ERC-20, который поддерживает выполнение кода в контракте получателя + * после `transfer` или `transferFrom` или кода в контракте расходования после `approve` в рамках одной транзакции. + */ +interface ERC1363 is ERC20, ERC165 { + /* + * ПРИМЕЧАНИЕ: идентификатор ERC-165 для этого интерфейса — 0xb0202a11. + * 0xb0202a11 === + * bytes4(keccak256('transferAndCall(address,uint256)')) ^ + * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ + * bytes4(keccak256('approveAndCall(address,uint256)')) ^ + * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) + */ + + /** + * @dev Перемещает токены в количестве `value` со счета вызывающего на `to` + * и затем вызывает `ERC1363Receiver::onTransferReceived` на `to`. + * @param to Адрес, на который переводятся токены. + * @param value Количество токенов для перевода. + * @return Логическое значение, указывающее, что операция прошла успешно, если не возникло исключение. + */ + function transferAndCall(address to, uint256 value) external returns (bool); + + /** + * @dev Перемещает токены в количестве `value` со счета вызывающего на `to` + * и затем вызывает `ERC1363Receiver::onTransferReceived` на `to`. + * @param to Адрес, на который переводятся токены. + * @param value Количество токенов для перевода. + * @param data Дополнительные данные без указанного формата, отправляемые при вызове `to`. + * @return Логическое значение, указывающее, что операция прошла успешно, если не возникло исключение. + */ + function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); + + /** + * @dev Перемещает токены в количестве `value` из `from` в `to`, используя механизм разрешений, + * и затем вызывает `ERC1363Receiver::onTransferReceived` в `to`. + * @param from Адрес, с которого отправляются токены. + * @param to Адрес, на который переводятся токены. + * @param value Количество токенов для перевода. + * @return Логическое значение, указывающее, что операция прошла успешно, если не возникло исключение. + */ + function transferFromAndCall(address from, address to, uint256 value) external returns (bool); + + /** + * @dev Перемещает токены в количестве `value` из `from` в `to`, используя механизм разрешений, + * и затем вызывает `ERC1363Receiver::onTransferReceived` в `to`. + * @param from Адрес, с которого отправляются токены. + * @param to Адрес, на который переводятся токены. + * @param value Количество токенов для перевода. + * @param data Дополнительные данные без указанного формата, отправляемые при вызове `to`. + * @return Логическое значение, указывающее, что операция прошла успешно, если не возникло исключение. + */ + function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); + + /** + * @dev Устанавливает количество токенов `value` в качестве разрешения для `spender` на токены вызывающего, + * а затем вызывает `ERC1363Spender::onApprovalReceived` на `spender`. + * @param spender Адрес, который будет тратить средства. + * @param value Количество токенов, которое будет потрачено. + * @return Логическое значение, указывающее, что операция прошла успешно, если не возникло исключение. + */ + function approveAndCall(address spender, uint256 value) external returns (bool); + + /** + * @dev Устанавливает количество токенов `value` в качестве разрешения для `spender` на токены вызывающего, + * а затем вызывает `ERC1363Spender::onApprovalReceived` на `spender`. + * @param spender Адрес, который будет тратить средства. + * @param value Количество токенов, которое будет потрачено. + * @param data Дополнительные данные без указанного формата, отправляемые при вызове `spender`. + * @return Логическое значение, указывающее, что операция прошла успешно, если не возникло исключение. + */ + function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); +} + +interface ERC20 { + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + function transfer(address to, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); + function approve(address spender, uint256 value) external returns (bool); + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function allowance(address owner, address spender) external view returns (uint256); +} + +interface ERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +Умный контракт, который хочет принимать токены ERC-1363 через `transferAndCall` или `transferFromAndCall`, **ДОЛЖЕН** реализовывать интерфейс `ERC1363Receiver`: + +```solidity +/** + * @title ERC1363Receiver + * @dev Интерфейс для любого контракта, который хочет поддерживать `transferAndCall` или `transferFromAndCall` от контрактов токенов ERC-1363. + */ +interface ERC1363Receiver { + /** + * @dev Эта функция вызывается всякий раз, когда токены ERC-1363 переводятся в этот контракт с помощью `ERC1363::transferAndCall` или `ERC1363::transferFromAndCall` + * оператором `operator` от `from`. + * + * ПРИМЕЧАНИЕ: чтобы принять перевод, эта функция должна вернуть + * `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` + * (т. е. 0x88a7ca5c или свой собственный селектор функции). + * + * @param operator Адрес, который вызвал функцию `transferAndCall` или `transferFromAndCall`. + * @param from Адрес, с которого были переведены токены. + * @param value Количество переведенных токенов. + * @param data Дополнительные данные без указанного формата. + * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))`, если перевод разрешен, если не возникло исключение. + */ + function onTransferReceived(address operator, address from, uint256 value, bytes calldata data) external returns (bytes4); +} +``` + +Умный контракт, который хочет принимать токены ERC-1363 через `approveAndCall`, **ДОЛЖЕН** реализовывать интерфейс `ERC1363Spender`: + +```solidity +/** + * @title ERC1363Spender + * @dev Интерфейс для любого контракта, который хочет поддерживать `approveAndCall` от контрактов токенов ERC-1363. + */ +interface ERC1363Spender { + /** + * @dev Эта функция вызывается всякий раз, когда `owner` токенов ERC-1363 одобряет этот контракт через `ERC1363::approveAndCall` + * для траты своих токенов. + * + * ПРИМЕЧАНИЕ: чтобы принять одобрение, эта функция должна вернуть + * `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` + * (т. е. 0x7b04a2d0 или свой собственный селектор функции). + * + * @param owner Адрес, который вызвал функцию `approveAndCall` и ранее владел токенами. + * @param value Количество токенов, которое будет потрачено. + * @param data Дополнительные данные без указанного формата. + * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))`, если одобрение разрешено, если не возникло исключение. + */ + function onApprovalReceived(address owner, uint256 value, bytes calldata data) external returns (bytes4); +} +``` + +## Дополнительные материалы {#further-reading} + +- [ERC-1363: Стандарт оплачиваемых токенов](https://eips.ethereum.org/EIPS/eip-1363) +- [ERC-1363: репозиторий GitHub](https://github.com/vittominacori/erc1363-payable-token) diff --git a/public/content/translations/ru/developers/docs/standards/tokens/erc-20/index.md b/public/content/translations/ru/developers/docs/standards/tokens/erc-20/index.md new file mode 100644 index 00000000000..e4244f5eb63 --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/erc-20/index.md @@ -0,0 +1,186 @@ +--- +title: "Стандарт токенов ERC- 20" +description: "Узнайте об ERC-20, стандарте для взаимозаменяемых токенов на Ethereum, который обеспечивает совместимость приложений для токенов." +lang: ru +--- + +## Введение {#introduction} + +**Что такое токен?** + +Токены в Ethereum могут представлять практически все, что угодно: + +- баллы репутации на онлайн-платформе +- навыки персонажа в игре +- финансовые активы, такие как доля в компании +- фиатная валюта, как доллар США +- унция золота +- и многое другое... + +Такая важная функция Ethereum должна обрабатываться надежным стандартом, верно? Именно эту роль выполняет ERC-20. Этот стандарт позволяет разработчикам создавать приложения для токенов, которые совместимы с другими продуктами и услугами. Стандарт ERC-20 также используется для предоставления дополнительной функциональности [эфиру](/glossary/#ether). + +**Что такое ERC-20?** + +ERC-20 вводит стандарт для взаимозаменяемых токенов, другими словами, они обладают свойством, которое делает каждый токен точно таким же (по типу и ценности), как и другой токен. Например, токен ERC-20 действует точно так же, как ETH, означая, что 1 токен всегда равен и всегда будет равен всем остальным токенам. + +## Предварительные условия {#prerequisites} + +- [Аккаунты](/developers/docs/accounts) +- [Смарт-контракты](/developers/docs/smart-contracts/) +- [Стандарты токенов](/developers/docs/standards/tokens/) + +## Тело {#body} + +ERC-20 (Ethereum Request for Comments 20), предложенный Фабианом Фогельстеллером в ноябре 2015 года, является стандартом токенов, который реализует API для токенов в смарт-контрактах. + +Примеры функциональности, которую предоставляет ERC-20: + +- перевод токенов с одного аккаунта на другой +- узнать текущий баланс токенов на счету +- узнать количество доступных токенов в сети +- подтвердить, может ли сумма токена со счета быть потрачена аккаунтом третьей стороны + +Если Смарт-контракт реализует следующие методы и события, его можно назвать контрактом ERC-20 токенов, и после развертывания он будет отвечать за отслеживание созданных токенов в Ethereum. + +Из [EIP-20](https://eips.ethereum.org/EIPS/eip-20): + +### Методы {#methods} + +```solidity +function name() public view returns (string) +function symbol() public view returns (string) +function decimals() public view returns (uint8) +function totalSupply() public view returns (uint256) +function balanceOf(address _owner) public view returns (uint256 balance) +function transfer(address _to, uint256 _value) public returns (bool success) +function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) +function approve(address _spender, uint256 _value) public returns (bool success) +function allowance(address _owner, address _spender) public view returns (uint256 remaining) +``` + +### События {#events} + +```solidity +event Transfer(address indexed _from, address indexed _to, uint256 _value) +event Approval(address indexed _owner, address indexed _spender, uint256 _value) +``` + +### Примеры {#web3py-example} + +Давайте разберемся почему Стандарт настолько важен, чтобы упростить для нас проверку любого контракта токена ERC-20 в Ethereum. +Нам просто нужен двоичный интерфейс приложения контракта (ABI) для создания интерфейса для любого токена ERC-20. Как вы можете увидеть ниже, мы будем использовать упрощенный ABI, чтобы сделать пример простым. + +#### Пример Web3.py {#web3py-example} + +Во-первых, убедитесь, что вы установили библиотеку Python [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation): + +``` +pip install web3 +``` + +```python +from web3 import Web3 + + +w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) + +dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI +weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Обернутый эфир (WETH) + +acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 2 + +# Это упрощенный двоичный интерфейс приложения (ABI) контракта токена ERC-20. +# Он будет предоставлять только методы: balanceOf(address), decimals(), symbol() и totalSupply() +simplified_abi = [ + { + 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}], + 'name': 'balanceOf', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'decimals', + 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'symbol', + 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'totalSupply', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + } +] + +dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi) +symbol = dai_contract.functions.symbol().call() +decimals = dai_contract.functions.decimals().call() +totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals +addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals + +# DAI +print("===== %s =====" % symbol) +print("Общее предложение:", totalSupply) +print("Баланс адреса:", addr_balance) + +weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi) +symbol = weth_contract.functions.symbol().call() +decimals = weth_contract.functions.decimals().call() +totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals +addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals + +# WETH +print("===== %s =====" % symbol) +print("Общее предложение:", totalSupply) +print("Баланс адреса:", addr_balance) +``` + +## Известные проблемы {#erc20-issues} + +### Проблема с получением токенов ERC-20 {#reception-issue} + +**По состоянию на 20.06.2024 из-за этой проблемы было потеряно токенов ERC-20 на сумму не менее 83 656 418 долларов США. Обратите внимание, что чистая реализация ERC-20 подвержена этой проблеме, если вы не примените набор дополнительных ограничений поверх стандарта, перечисленных ниже.** + +Когда токены ERC-20 отправляются на умный контракт, который не предназначен для обработки токенов ERC-20, эти токены могут быть безвозвратно утеряны. Это происходит потому, что у принимающего контракта нет функциональности для распознавания входящих токенов или реагирования на них, и в стандарте ERC-20 нет механизма для уведомления принимающего контракта о входящих токенах. Эта проблема проявляется в основном следующими способами: + +1. Механизм перевода токенов + +- Токены ERC-20 переводятся с помощью функций transfer или transferFrom + - Когда пользователь отправляет токены на адрес контракта с помощью этих функций, токены переводятся независимо от того, предназначен ли принимающий контракт для их обработки + +2. Отсутствие уведомления + - Принимающий контракт не получает уведомления или обратного вызова о том, что на него были отправлены токены + - Если в принимающем контракте отсутствует механизм для обработки токенов (например, резервная функция или специальная функция для управления приемом токенов), токены фактически застревают на адресе контракта +3. Отсутствие встроенной обработки + - Стандарт ERC-20 не включает обязательную функцию для реализации принимающими контрактами, что приводит к ситуации, когда многие контракты не могут должным образом управлять входящими токенами + +**Возможные решения** + +Хотя полностью предотвратить эту проблему с ERC-20 невозможно, существуют методы, которые позволяют значительно снизить вероятность потери токенов для конечного пользователя: + +- Наиболее распространенная проблема возникает, когда пользователь отправляет токены на адрес самого контракта токена (например, USDT, депонированный на адрес контракта токена USDT). Рекомендуется ограничить функцию `transfer(..)` , чтобы отменять такие попытки перевода. Рассмотрите возможность добавления проверки `require(_to != address(this));` в реализацию функции `transfer(..)`. +- Функция `transfer(..)` в целом не предназначена для внесения токенов на контракты. `approve(..) и шаблон `transferFrom(..)`используется для внесения токенов ERC-20 на контракты. Можно ограничить функцию перевода, чтобы запретить с ее помощью вносить токены на любые контракты, однако это может нарушить совместимость с контрактами, которые предполагают, что токены могут быть депонированы на контракты с помощью функции`trasnfer(..)` (например, пулы ликвидности Uniswap). +- Всегда предполагайте, что токены ERC-20 могут оказаться в вашем контракте, даже если ваш контракт не должен их получать. Не существует способа предотвратить или отклонить случайные пополнения на стороне получателя. Рекомендуется реализовать функцию, которая позволит извлекать случайно депонированные токены ERC-20. +- Рассмотрите возможность использования альтернативных стандартов токенов. + +В результате этой проблемы появились некоторые альтернативные стандарты, такие как [ERC-223](/developers/docs/standards/tokens/erc-223) или [ERC-1363](/developers/docs/standards/tokens/erc-1363). + +## Дополнительные материалы {#further-reading} + +- [EIP-20: Стандарт токенов ERC-20](https://eips.ethereum.org/EIPS/eip-20) +- [OpenZeppelin - Токены](https://docs.openzeppelin.com/contracts/3.x/tokens#ERC20) +- [OpenZeppelin - Реализация ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) +- [Alchemy - Руководство по токенам ERC20 на Solidity](https://www.alchemy.com/overviews/erc20-solidity) + +## Другие стандарты взаимозаменяемых токенов {#fungible-token-standards} + +- [ERC-223](/developers/docs/standards/tokens/erc-223) +- [ERC-1363](/developers/docs/standards/tokens/erc-1363) +- [ERC-777](/developers/docs/standards/tokens/erc-777) +- [ERC-4626 - Токенизированные хранилища](/developers/docs/standards/tokens/erc-4626) diff --git a/public/content/translations/ru/developers/docs/standards/tokens/erc-223/index.md b/public/content/translations/ru/developers/docs/standards/tokens/erc-223/index.md new file mode 100644 index 00000000000..387801e85ed --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/erc-223/index.md @@ -0,0 +1,198 @@ +--- +title: "Стандарт токенов ERC- 223" +description: "Обзор стандарта взаимозаменяемых токенов ERC-223, принципы его работы и сравнение с ERC-20." +lang: ru +--- + +## Введение {#introduction} + +### Что такое ERC-223? {#what-is-erc223} + +ERC-223 — это стандарт для взаимозаменяемых токенов, похожий на стандарт ERC-20. Ключевое отличие заключается в том, что ERC-223 определяет не только API токена, но и логику перевода токенов от отправителя к получателю. Он вводит модель коммуникации, которая позволяет обрабатывать переводы токенов на стороне получателя. + +### Отличия от ERC-20 {#erc20-differences} + +ERC-223 устраняет некоторые ограничения ERC-20 и вводит новый метод взаимодействия между контрактом токена и контрактом, который получает токены. Есть несколько вещей, которые возможны с ERC-223, но не с ERC-20: + +- Обработка перевода токенов на стороне получателя: получатели могут обнаружить, что токен ERC-223 зачисляется. +- Отклонение неправильно отправленных токенов: если пользователь отправляет токены ERC-223 на контракт, который не предназначен для их получения, контракт может отклонить транзакцию, предотвращая потерю токенов. +- Метаданные в переводах: токены ERC-223 могут включать метаданные, что позволяет прикреплять произвольную информацию к транзакциям с токенами. + +## Предварительные условия {#prerequisites} + +- [Аккаунты](/developers/docs/accounts) +- [Смарт-контракты](/developers/docs/smart-contracts/) +- [Стандарты токенов](/developers/docs/standards/tokens/) +- [ERC-20](/developers/docs/standards/tokens/erc-20/) + +## Тело {#body} + +ERC-223 — это стандарт токенов, который реализует API для токенов в смарт-контрактах. Он также объявляет API для контрактов, которые должны получать токены ERC-223. Контракты, которые не поддерживают API получателя ERC-223, не могут получать токены ERC-223, что предотвращает ошибку пользователя. + +Если смарт-контракт реализует следующие методы и события, его можно назвать контрактом токена, совместимым с ERC-223. После развертывания он +будет отвечать за отслеживание созданных токенов в Ethereum. + +Контракт не обязан иметь только эти функции, и разработчик может добавить в него любую другую функцию из разных стандартов токенов. Например, функции `approve` и `transferFrom` не являются частью стандарта ERC-223, но они могут быть реализованы при необходимости. + +Из [EIP-223](https://eips.ethereum.org/EIPS/eip-223): + +### Методы {#methods} + +Токен ERC-223 должен включать следующие методы: + +```solidity +function name() public view returns (string) +function symbol() public view returns (string) +function decimals() public view returns (uint8) +function totalSupply() public view returns (uint256) +function balanceOf(address _owner) public view returns (uint256 balance) +function transfer(address _to, uint256 _value) public returns (bool success) +function transfer(address _to, uint256 _value, bytes calldata _data) public returns (bool success) +``` + +Контракт, который должен получать токены ERC-223, должен иметь в себе следующий метод: + +```solidity +function tokenReceived(address _from, uint _value, bytes calldata _data) +``` + +Если токены ERC-223 отправляются на контракт, который не реализует функцию `tokenReceived(..)`, то перевод должен завершиться неудачей, а токены не должны быть списаны с баланса отправителя. + +### События {#events} + +```solidity +event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes calldata _data) +``` + +### Примеры: {#examples} + +API токена ERC-223 похож на API токена ERC-20, поэтому с точки зрения разработки пользовательского интерфейса разницы нет. Единственное исключение здесь заключается в том, что токены ERC-223 могут не иметь функций `approve` + `transferFrom`, поскольку они являются необязательными для этого стандарта. + +#### Примеры на Solidity {#solidity-example} + +Следующий пример иллюстрирует, как работает базовый контракт токена ERC-223: + +```solidity +pragma solidity ^0.8.19; +abstract contract IERC223Recipient { + function tokenReceived(address _from, uint _value, bytes memory _data) public virtual; +} +contract VeryBasicERC223Token { + event Transfer(address indexed from, address indexed to, uint value, bytes data); + string private _name; + string private _symbol; + uint8 private _decimals; + uint256 private _totalSupply; + mapping(address => uint256) private balances; + function name() public view returns (string memory) { return _name; } + function symbol() public view returns (string memory) {return _symbol; } + function decimals() public view returns (uint8) { return _decimals; } + function totalSupply() public view returns (uint256) { return _totalSupply; } + function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { size := extcodesize(account) } + return size > 0; + } + function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success){ + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data); + } + emit Transfer(msg.sender, _to, _value, _data); + return true; + } + function transfer(address _to, uint _value) public returns (bool success){ + bytes memory _empty = hex"00000000"; + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + if(isContract(_to)) { + IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty); + } + emit Transfer(msg.sender, _to, _value, _empty); + return true; + } +} +``` + +Теперь мы хотим, чтобы другой контракт принимал депозиты `tokenA`, предполагая, что tokenA — это токен ERC-223. Контракт должен принимать только tokenA и отклонять любые другие токены. Когда контракт получает tokenA, он должен вызвать событие `Deposit()` и увеличить значение внутренней переменной `deposits`. + +Вот код: + +```solidity +contract RecipientContract is IERC223Recipient { + event Deposit(address whoSentTheTokens); + uint256 deposits = 0; + address tokenA; // Единственный токен, который мы хотим принимать. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + // Важно понимать, что в этой функции + // msg.sender — это адрес получаемого токена, + // msg.value всегда равен 0, так как в большинстве случаев контракт токена не владеет и не отправляет эфир, + // _from — это отправитель перевода токена, + // _value — это количество зачисленных токенов. + require(msg.sender == tokenA); + deposits += _value; + emit Deposit(_from); + } +} +``` + +## Часто задаваемые вопросы {#faq} + +### Что произойдет, если мы отправим на контракт какой-нибудь tokenB? {#sending-tokens} + +Транзакция не пройдёт, а передача токенов — не произойдет. Токены вернутся на адрес отправителя. + +### Как мы можем сделать депозит на этот контракт? {#contract-deposits} + +Вызовите функцию `transfer(address,uint256)` или `transfer(address,uint256,bytes)` токена ERC-223, указав адрес `RecipientContract`. + +### Что будет, если отправить токен ERC-20 на этот контракт? {#erc-20-transfers} + +Если токен ERC-20 будет отправлен на `RecipientContract`, токены будут переведены, но перевод не будет распознан (событие `Deposit()` не будет вызвано, а значение депозитов не изменится). Нежелательные депозиты ERC-20 не могут быть отфильтрованы или предотвращены. + +### Что, если мы хотим выполнить какую-то функцию после депозита токена? {#function-execution} + +Есть несколько способов. В этом примере мы будем следовать методу, который делает переводы ERC-223 идентичными переводам эфира: + +```solidity +contract RecipientContract is IERC223Recipient { + event Foo(); + event Bar(uint256 someNumber); + address tokenA; // Единственный токен, который мы хотим принимать. + function tokenReceived(address _from, uint _value, bytes memory _data) public override + { + require(msg.sender == tokenA); + address(this).call(_data); // Обработка входящей транзакции и выполнение последующего вызова функции. + } + function foo() public + { + emit Foo(); + } + function bar(uint256 _someNumber) public + { + emit Bar(_someNumber); + } +} +``` + +Когда `RecipientContract` получит токен ERC-223, контракт выполнит функцию, закодированную как параметр `_data` транзакции токена, идентично тому, как транзакции эфира кодируют вызовы функций как транзакцию `data`. Для получения дополнительной информации прочтите [о поле данных](/developers/docs/transactions/#the-data-field). + +В приведенном выше примере токен ERC-223 должен быть переведен на адрес `RecipientContract` с помощью функции `transfer(address,uin256,bytes calldata _data)`. Если параметр данных будет `0xc2985578` (сигнатура функции `foo()`), то функция foo() будет вызвана после получения депозита токена, и будет запущено событие Foo(). + +Параметры также могут быть закодированы в `data` перевода токена, например, мы можем вызвать функцию bar() со значением 12345 для `_someNumber`. В этом случае `data` должен быть `0x0423a13200000000000000000000000000000000000000000000000000000000000004d2`, где `0x0423a132` — это сигнатура функции `bar(uint256)`, а `00000000000000000000000000000000000000000000000000000000000004d2` — это 12345 в виде uint256. + +## Ограничения {#limitations} + +Несмотря на то, что стандарт ERC-223 решает ряд проблем стандарта ERC-20, он не без ограничений: + +- Внедрение и совместимость: ERC-223 еще не получил широкого распространения, что может ограничивать его совместимость с существующими инструментами и платформами. +- Обратная совместимость: ERC-223 не имеет обратной совместимости с ERC-20, что означает, что существующие контракты и инструменты ERC-20 — без модификаций — не будут работать с токенами ERC-223. +- Стоимость газа: дополнительные проверки и функции при переводе ERC-223 могут привести к более высоким затратам на газ по сравнению с транзакциями ERC-20. + +## Дополнительные материалы {#further-reading} + +- [EIP-223: Стандарт токенов ERC-223](https://eips.ethereum.org/EIPS/eip-223) +- [Первоначальное предложение по ERC-223](https://github.com/ethereum/eips/issues/223) diff --git a/public/content/translations/ru/developers/docs/standards/tokens/erc-4626/index.md b/public/content/translations/ru/developers/docs/standards/tokens/erc-4626/index.md new file mode 100644 index 00000000000..096996fae9f --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/erc-4626/index.md @@ -0,0 +1,227 @@ +--- +title: "Стандарт токенизированных хранилищ ERC-4626" +description: "Стандарт для доходных хранилищ." +lang: ru +--- + +## Введение {#introduction} + +ERC-4626 - стандарт, разработанный для оптимизации и объединения технических параметров доходных хранилищ. Он предоставляет стандартный API для токенизированных доходных хранилищ, которые представляют собой доли одного базового токена ERC-20. ERC-4626 также описывает необязательное расширение для токенизированных хранилищ, использующих ERC-20, предлагая базовую функциональность для внесения депозита, вывода токенов и считывания балансов. + +**Роль ERC-4626 в доходных хранилищах** + +Рынки кредитования, агрегаторы и внутренне процентные токены помогают пользователям находить лучшую доходность на свои криптотокены путем выполнения различных стратегий. Эти стратегии выполняются с небольшими вариациями, что может приводить к ошибкам или тратить впустую ресурсы на разработку. + +ERC-4626 в доходных хранилищах снизит трудозатраты на интеграцию и откроет доступ к доходности в различных приложениях с небольшими специальными усилиями со стороны разработчиков путем создания более последовательных и надежных шаблонов реализации. + +Токен ERC-4626 полностью описан в [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626). + +**Асинхронное расширение хранилища (ERC-7540)** + +ERC-4626 оптимизирован для атомарных депозитов и погашений до определенного лимита. Если лимит достигнут, новые депозиты или погашения не могут быть отправлены. Это ограничение плохо работает для любой системы умных контрактов с асинхронными действиями или задержками в качестве необходимого условия для взаимодействия с Хранилищем (например, протоколы реальных активов, протоколы кредитования с недостаточным обеспечением, межсетевые протоколы кредитования, токены ликвидного стейкинга или модули страховой безопасности). + +ERC-7540 расширяет полезность Хранилищ ERC-4626 для асинхронных сценариев использования. Существующий интерфейс Хранилища (`deposit`/`withdraw`/`mint`/`redeem`) полностью используется для получения асинхронных Запросов. + +Расширение ERC-7540 полностью описано в [ERC-7540](https://eips.ethereum.org/EIPS/eip-7540). + +**Расширение хранилища с несколькими активами (ERC-7575)** + +Один из недостающих вариантов использования, который не поддерживается ERC-4626, — это Хранилища, которые имеют несколько активов или точек входа, такие как токены поставщика ликвидности (LP). Они, как правило, громоздки или несовместимы из-за требования к самому ERC-4626 быть токеном ERC-20. + +ERC-7575 добавляет поддержку Хранилищ с несколькими активами путем вынесения реализации токена ERC-20 за пределы реализации ERC-4626. + +Расширение ERC-7575 полностью описано в [ERC-7575](https://eips.ethereum.org/EIPS/eip-7575). + +## Предварительные условия {#prerequisites} + +Чтобы лучше понять эту страницу, мы рекомендуем вам сначала прочитать о [стандартах токенов](/developers/docs/standards/tokens/) и [ERC-20](/developers/docs/standards/tokens/erc-20/). + +## Функции и возможности ERC-4626: {#body} + +### Методы {#methods} + +#### актив {#asset} + +```solidity +function asset() public view returns (address assetTokenAddress) +``` + +Эта функция возвращает адрес базового токена, используемого хранилищем для учета, внесения депозитов и вывода средств. + +#### всегоАктивов {#totalassets} + +```solidity +function totalAssets() public view returns (uint256) +``` + +Эта функция возвращает общее количество базовых активов, хранящихся в хранилище. + +#### конвертироватьВДОли {#convertoshares} + +```solidity +function convertToShares(uint256 assets) public view returns (uint256 shares) +``` + +Эта функция возвращает количество долей (`shares`), которое будет обменено хранилищем на предоставленное количество активов (`assets`). + +#### конвертироватьВАктивы {#convertoassets} + +```solidity +function convertToAssets(uint256 shares) public view returns (uint256 assets) +``` + +Эта функция возвращает количество активов (`assets`), которое будет обменено хранилищем на предоставленное количество долей (`shares`). + +#### максДепозит {#maxdeposit} + +```solidity +function maxDeposit(address receiver) public view returns (uint256 maxAssets) +``` + +Эта функция возвращает максимальное количество базовых активов, которое можно внести одним вызовом [`deposit`](#deposit), при этом доли выпускаются для получателя (`receiver`). + +#### предпросмотрДепозита {#previewdeposit} + +```solidity +function previewDeposit(uint256 assets) public view returns (uint256 shares) +``` + +Эта функция позволяет пользователям симулировать результат своего депозита на текущем блоке. + +#### депозит {#deposit} + +```solidity +function deposit(uint256 assets, address receiver) public returns (uint256 shares) +``` + +Эта функция вносит активы (`assets`) базовых токенов в хранилище и передает право собственности на доли (`shares`) получателю (`receiver`). + +#### максМинт {#maxmint} + +```solidity +function maxMint(address receiver) public view returns (uint256 maxShares) +``` + +Эта функция возвращает максимальное количество долей, которое можно выпустить одним вызовом [`mint`](#mint), при этом доли выпускаются для получателя (`receiver`). + +#### предпросмотрМинта {#previewmint} + +```solidity +function previewMint(uint256 shares) public view returns (uint256 assets) +``` + +Эта функция позволяет пользователям симулировать результат своего выпуска (минта) на текущем блоке. + +#### минт {#mint} + +```solidity +function mint(uint256 shares, address receiver) public returns (uint256 assets) +``` + +Эта функция выпускает (минтит) ровно `shares` (долей) хранилища для получателя (`receiver`) путем внесения `assets` (активов) базовых токенов. + +#### максВывод {#maxwithdraw} + +```solidity +function maxWithdraw(address owner) public view returns (uint256 maxAssets) +``` + +Эта функция возвращает максимальное количество базовых активов, которое можно вывести с баланса владельца (`owner`) одним вызовом [`withdraw`](#withdraw). + +#### предпросмотрВывода {#previewwithdraw} + +```solidity +function previewWithdraw(uint256 assets) public view returns (uint256 shares) +``` + +Эта функция позволяет пользователям симулировать результат своего вывода на текущем блоке. + +#### вывод {#withdraw} + +```solidity +function withdraw(uint256 assets, address receiver, address owner) public returns (uint256 shares) +``` + +Эта функция сжигает доли (`shares`) владельца (`owner`) и отправляет ровно `assets` (активов) токена из хранилища получателю (`receiver`). + +#### максПогашение {#maxredeem} + +```solidity +function maxRedeem(address owner) public view returns (uint256 maxShares) +``` + +Эта функция возвращает максимальное количество долей, которое можно погасить с баланса владельца (`owner`) через вызов [`redeem`](#redeem). + +#### предпросмотрПогашения {#previewredeem} + +```solidity +function previewRedeem(uint256 shares) public view returns (uint256 assets) +``` + +Эта функция позволяет пользователям симулировать результат своего погашения на текущем блоке. + +#### погашение {#redeem} + +```solidity +function redeem(uint256 shares, address receiver, address owner) public returns (uint256 assets) +``` + +Эта функция погашает определенное количество долей (`shares`) владельца (`owner`) и отправляет активы (`assets`) базового токена из хранилища получателю (`receiver`). + +#### общееПредложение {#totalsupply} + +```solidity +function totalSupply() public view returns (uint256) +``` + +Возвращает общее количество непогашенных долей хранилища в обращении. + +#### баланс {#balanceof} + +```solidity +function balanceOf(address owner) public view returns (uint256) +``` + +Возвращает общее количество долей хранилища, которыми в настоящее время владеет `owner`. + +### Карта интерфейса {#mapOfTheInterface} + +![Карта интерфейса ERC-4626](./map-of-erc-4626.png) + +### События {#events} + +#### Событие Deposit + +**ДОЛЖНО** генерироваться, когда токены вносятся в хранилище с помощью методов [`mint`](#mint) и [`deposit`](#deposit). + +```solidity +event Deposit( + address indexed sender, + address indexed owner, + uint256 assets, + uint256 shares +) +``` + +Где `sender` — это пользователь, который обменял `assets` на `shares` и перевел эти `shares` владельцу (`owner`). + +#### Событие Withdraw + +**ДОЛЖНО** генерироваться, когда доли выводятся из хранилища вкладчиком с помощью методов [`redeem`](#redeem) или [`withdraw`](#withdraw). + +```solidity +event Withdraw( + address indexed sender, + address indexed receiver, + address indexed owner, + uint256 assets, + uint256 shares +) +``` + +Где `sender` — это пользователь, который инициировал вывод и обменял `shares` (доли), принадлежащие `owner` (владельцу), на `assets` (активы). `receiver` — это пользователь, который получил выведенные `assets` (активы). + +## Дополнительные материалы {#further-reading} + +- [EIP-4626: Стандарт токенизированного хранилища](https://eips.ethereum.org/EIPS/eip-4626) +- [ERC-4626: репозиторий на GitHub](https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC4626.sol) diff --git a/public/content/translations/ru/developers/docs/standards/tokens/erc-721/index.md b/public/content/translations/ru/developers/docs/standards/tokens/erc-721/index.md new file mode 100644 index 00000000000..bcb9110fb85 --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/erc-721/index.md @@ -0,0 +1,255 @@ +--- +title: "Стандарт невзаимозаменяемых токенов ERC-721" +description: "Узнайте о ERC-721, стандарте для невзаимозаменяемых токенов (NFT), которые представляют собой уникальные цифровые активы в сети Ethereum." +lang: ru +--- + +## Введение {#introduction} + +**Что такое невзаимозаменяемый токен?** + +Невзаимозаменяемые токены (NFT) используются для уникальной идентификации чего-то или кого-то. Этот тип токена идеально подходит для использования на платформах, предлагающих коллекционные предметы, ключи доступа, лотерейные билеты, пронумерованные места на концерты, спортивные матчи и т.д. Этот особый тип токена имеет удивительные возможности, поэтому он заслуживает надлежащего стандарта, ERC-721 призван решить эту проблему! + +**Что такое ERC-721?** + +ERC-721 вводит стандарт для NFT, другими словами, этот тип токена уникален и может иметь значение, отличное от другого токена из того же смарт-контракта, возможно, из-за его возраста, редкости или даже из-за чего-то другого, например его внешнего вида. +Подожди, визуально? + +Да! У всех NFT есть переменная `uint256` под названием `tokenId`, поэтому для любого контракта ERC-721 пара +`contract address, uint256 tokenId` должна быть глобально уникальной. При этом у децентрализованного приложения может быть "конвертер", который +использует `tokenId` в качестве входных данных и выводит изображение чего-то классного, например: зомби, оружия, навыков или удивительных котят! + +## Предварительные условия {#prerequisites} + +- [Аккаунты](/developers/docs/accounts/) +- [Смарт-контракты](/developers/docs/smart-contracts/) +- [Стандарты токенов](/developers/docs/standards/tokens/) + +## Тело {#body} + +ERC-721 (Ethereum Request for Comments 721), предложенный Уильямом Энтрикеном, Дитером Ширли, Якобом Эвансом и Настасьей Сакс в январе 2018 года, является стандартом невзаимозаменяемых токенов, который реализует API для токенов в смарт-контрактах. + +Он предоставляет такие функции, как: перенос токенов из одной учетной записи в другую, получение текущего баланса токенов учетной записи, узнать кто владелец определенного токена, а также узнать общее количество токенов, доступных в сети. +Помимо этого, он также имеет некоторые другие функции, такие как подтверждение того, что количество токенов из учетной записи может быть перемещено сторонней учетной записью. + +Если в смарт-контракте реализованы следующие методы и события, его можно назвать контрактом невзаимозаменяемых токенов ERC-721, и после развертывания он будет нести ответственность за отслеживание созданных токенов в Ethereum. + +Из [EIP-721](https://eips.ethereum.org/EIPS/eip-721): + +### Методы {#methods} + +```solidity + function balanceOf(address _owner) external view returns (uint256); + function ownerOf(uint256 _tokenId) external view returns (address); + function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable; + function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; + function transferFrom(address _from, address _to, uint256 _tokenId) external payable; + function approve(address _approved, uint256 _tokenId) external payable; + function setApprovalForAll(address _operator, bool _approved) external; + function getApproved(uint256 _tokenId) external view returns (address); + function isApprovedForAll(address _owner, address _operator) external view returns (bool); +``` + +### События {#events} + +```solidity + event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); + event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); + event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); +``` + +### Примеры {#web3py-example} + +Давайте посмотрим, насколько важен стандарт, чтобы упростить нам проверку любого контракта токена ERC-721 на Ethereum. +Нам просто нужен двоичный интерфейс приложения контракта (ABI) для создания интерфейса к любому токену ERC-721. Как вы можете увидеть ниже, мы будем использовать упрощенный ABI, чтобы сделать пример простым. + +#### Пример Web3.py {#web3py-example} + +Во-первых, убедитесь, что вы установили библиотеку Python [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html#installation): + +``` +pip install web3 +``` + +```python +from web3 import Web3 +from web3._utils.events import get_event_data + + +w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com")) + +ck_token_addr = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d" # Контракт CryptoKitties + +acc_address = "0xb1690C08E213a35Ed9bAb7B318DE14420FB57d8C" # Аукцион по продаже CryptoKitties + +# Это упрощенный двоичный интерфейс приложения (ABI) для контракта ERC-721 NFT. +# Он будет раскрывать только методы: balanceOf(address), name(), ownerOf(tokenId), symbol(), totalSupply() +simplified_abi = [ + { + 'inputs': [{'internalType': 'address', 'name': 'owner', 'type': 'address'}], + 'name': 'balanceOf', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'name', + 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [{'internalType': 'uint256', 'name': 'tokenId', 'type': 'uint256'}], + 'name': 'ownerOf', + 'outputs': [{'internalType': 'address', 'name': '', 'type': 'address'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'symbol', + 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [], + 'name': 'totalSupply', + 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], + 'stateMutability': 'view', 'type': 'function', 'constant': True + }, +] + +ck_extra_abi = [ + { + 'inputs': [], + 'name': 'pregnantKitties', + 'outputs': [{'name': '', 'type': 'uint256'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + }, + { + 'inputs': [{'name': '_kittyId', 'type': 'uint256'}], + 'name': 'isPregnant', + 'outputs': [{'name': '', 'type': 'bool'}], + 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True + } +] + +ck_contract = w3.eth.contract(address=w3.to_checksum_address(ck_token_addr), abi=simplified_abi+ck_extra_abi) +name = ck_contract.functions.name().call() +symbol = ck_contract.functions.symbol().call() +kitties_auctions = ck_contract.functions.balanceOf(acc_address).call() +print(f"{name} [{symbol}] NFT на аукционах: {kitties_auctions}") + +pregnant_kitties = ck_contract.functions.pregnantKitties().call() +print(f"{name} [{symbol}] беременных NFT: {pregnant_kitties}") + +# Используем ABI события Transfer для получения информации о переданных Kitties. +tx_event_abi = { + 'anonymous': False, + 'inputs': [ + {'indexed': False, 'name': 'from', 'type': 'address'}, + {'indexed': False, 'name': 'to', 'type': 'address'}, + {'indexed': False, 'name': 'tokenId', 'type': 'uint256'}], + 'name': 'Transfer', + 'type': 'event' +} + +# Нам нужна подпись события для фильтрации журналов +event_signature = w3.keccak(text="Transfer(address,address,uint256)").hex() + +logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), + "topics": [event_signature] +}) + +# Примечания: +# - Увеличьте количество блоков с 120, если событие Transfer не будет возвращено. +# - Если вы не нашли событие Transfer, вы можете попытаться получить tokenId по адресу: +# https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#events +# Нажмите, чтобы развернуть журналы события и скопировать его аргумент "tokenId" +recent_tx = [get_event_data(w3.codec, tx_event_abi, log)["args"] for log in logs] + +if recent_tx: + kitty_id = recent_tx[0]['tokenId'] # Вставьте сюда tokenId по ссылке выше + is_pregnant = ck_contract.functions.isPregnant(kitty_id).call() + print(f"{name} [{symbol}] NFT {kitty_id} беременен: {is_pregnant}") +``` + +В контракте CryptoKitties есть несколько интересных событий, помимо стандартных. + +Давайте проверим два из них: `Pregnant` и `Birth`. + +```python +# Используем ABI событий Pregnant и Birth для получения информации о новых Kitties. +ck_extra_events_abi = [ + { + 'anonymous': False, + 'inputs': [ + {'indexed': False, 'name': 'owner', 'type': 'address'}, + {'indexed': False, 'name': 'matronId', 'type': 'uint256'}, + {'indexed': False, 'name': 'sireId', 'type': 'uint256'}, + {'indexed': False, 'name': 'cooldownEndBlock', 'type': 'uint256'}], + 'name': 'Pregnant', + 'type': 'event' + }, + { + 'anonymous': False, + 'inputs': [ + {'indexed': False, 'name': 'owner', 'type': 'address'}, + {'indexed': False, 'name': 'kittyId', 'type': 'uint256'}, + {'indexed': False, 'name': 'matronId', 'type': 'uint256'}, + {'indexed': False, 'name': 'sireId', 'type': 'uint256'}, + {'indexed': False, 'name': 'genes', 'type': 'uint256'}], + 'name': 'Birth', + 'type': 'event' + }] + +# Нам нужна подпись события для фильтрации журналов +ck_event_signatures = [ + w3.keccak(text="Pregnant(address,uint256,uint256,uint256)").hex(), + w3.keccak(text="Birth(address,uint256,uint256,uint256,uint256)").hex(), +] + +# Вот событие Pregnant: +# - https://etherscan.io/tx/0xc97eb514a41004acc447ac9d0d6a27ea6da305ac8b877dff37e49db42e1f8cef#eventlog +pregnant_logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), + "topics": [ck_event_signatures[0]] +}) + +recent_pregnants = [get_event_data(w3.codec, ck_extra_events_abi[0], log)["args"] for log in pregnant_logs] + +# Вот событие Birth: +# - https://etherscan.io/tx/0x3978028e08a25bb4c44f7877eb3573b9644309c044bf087e335397f16356340a +birth_logs = w3.eth.get_logs({ + "fromBlock": w3.eth.block_number - 120, + "address": w3.to_checksum_address(ck_token_addr), + "topics": [ck_event_signatures[1]] +}) + +recent_births = [get_event_data(w3.codec, ck_extra_events_abi[1], log)["args"] for log in birth_logs] +``` + +## Популярные NFT {#popular-nfts} + +- [Etherscan NFT Tracker](https://etherscan.io/nft-top-contracts) перечисляет лучшие NFT на Ethereum по объему переводов. +- [CryptoKitties](https://www.cryptokitties.co/) — это игра, основанная на разведении и коллекционировании очаровательных + существ, которых мы называем CryptoKitties. +- [Sorare](https://sorare.com/) — это глобальный фэнтези-футбол, в котором вы можете коллекционировать предметы ограниченного выпуска, + управлять своими командами и соревноваться за призы. +- [Служба имён Ethereum (ENS)](https://ens.domains/) предлагает безопасный и децентрализованный способ адресации ресурсов как + в блокчейне, так и за его пределами, используя простые, удобочитаемые имена. +- [POAP](https://poap.xyz) предоставляет бесплатные NFT людям, которые посещают мероприятия или выполняют определенные действия. POAP-ы бесплатные для создания и распространения. +- [Unstoppable Domains](https://unstoppabledomains.com/) — это компания из Сан-Франциско, которая создает домены на + блокчейнах. Домены на блокчейне заменяют адреса криптовалют на удобочитаемые имена и могут использоваться для создания + устойчивых к цензуре веб-сайтов. +- [Gods Unchained Cards](https://godsunchained.com/) — это ККИ (коллекционная карточная игра) в блокчейне Ethereum, которая использует NFT для обеспечения реального права собственности + на внутриигровые активы. +- [Bored Ape Yacht Club](https://boredapeyachtclub.com) — это коллекция из 10 000 уникальных NFT, которые, помимо того, что являются доказуемо редкими произведениями искусства, действуют как членский токен клуба, предоставляя участникам льготы и преимущества, которые со временем увеличиваются в результате усилий сообщества. + +## Дополнительные материалы {#further-reading} + +- [EIP-721: стандарт невзаимозаменяемых токенов ERC-721](https://eips.ethereum.org/EIPS/eip-721) +- [OpenZeppelin — документация по ERC-721](https://docs.openzeppelin.com/contracts/3.x/erc721) +- [OpenZeppelin — реализация ERC-721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol) +- [Alchemy NFT API](https://www.alchemy.com/docs/reference/nft-api-quickstart) diff --git a/public/content/translations/ru/developers/docs/standards/tokens/erc-777/index.md b/public/content/translations/ru/developers/docs/standards/tokens/erc-777/index.md new file mode 100644 index 00000000000..735b45f7606 --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/erc-777/index.md @@ -0,0 +1,45 @@ +--- +title: "Стандарт токенов ERC- 777" +description: "Узнайте об ERC-777, улучшенном стандарте взаимозаменяемых токенов с перехватчиками, хотя по соображениям безопасности рекомендуется ERC-20." +lang: ru +--- + +## Предупреждение {#warning} + +**ERC-777 трудно реализовать должным образом из-за его [подверженности различным формам атак](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2620). Вместо этого рекомендуется использовать [ERC-20](/developers/docs/standards/tokens/erc-20/).** Эта страница оставлена в качестве исторического архива. + +## Введение? Введение {#introduction} + +ERC-777 — это стандарт взаимозаменяемых токенов, улучшающий существующий стандарт [ERC-20](/developers/docs/standards/tokens/erc-20/). + +## Предварительные условия {#prerequisites} + +Чтобы лучше понять эту страницу, мы рекомендуем вам сначала прочитать об [ERC-20](/developers/docs/standards/tokens/erc-20/). + +## Какие именно улучшения над ERC-20 предлагает ERC-777? {#-erc-777-vs-erc-20} + +ERC-777 обеспечивает следующие усовершенствования по сравнению с ERC-20. + +### Перехватчики {#hooks} + +Перехватчики — это функция, описанная в коде умного контракта. Перехватчики вызываются при отправке или получении токенов через контракт. Это позволяет умному контракту реагировать на входящие или исходящие токены. + +Перехватчики регистрируются и обнаруживаются с помощью стандарта [ERC-1820](https://eips.ethereum.org/EIPS/eip-1820). + +#### Чем хороши перехватчики? {#why-are-hooks-great} + +1. Перехватчики позволяют отправлять токены в контракт и уведомлять контракт в рамках одной транзакции, в отличие от [ERC-20](https://eips.ethereum.org/EIPS/eip-20), который для этого требует двойного вызова (`approve`/`transferFrom`). +2. Контракты, в которых не зарегистрированы перехватчики, несовместимы с ERC-777. Отправляющий контракт прервет транзакцию, если в принимающем контракте не зарегистрирован перехватчик. Это предотвращает случайные переводы на умные контракты, несовместимые с ERC-777. +3. Перехватчики могут отклонять транзакции. + +### Десятичные знаки {#decimals} + +Этот стандарт также решает проблему путаницы вокруг `decimals`, вызванную в ERC-20. Эта ясность улучшает опыт разработчика. + +### Обратная совместимость с ERC-20 {#backwards-compatibility-with-erc-20} + +С контрактами ERC-777 можно взаимодействовать так, будто бы они — контракты ERC-20. + +## Дополнительные материалы {#further-reading} + +[EIP-777: Стандарт токенов](https://eips.ethereum.org/EIPS/eip-777) diff --git a/public/content/translations/ru/developers/docs/standards/tokens/index.md b/public/content/translations/ru/developers/docs/standards/tokens/index.md new file mode 100644 index 00000000000..0871ce8b81b --- /dev/null +++ b/public/content/translations/ru/developers/docs/standards/tokens/index.md @@ -0,0 +1,41 @@ +--- +title: "Стандарты токенов" +description: "Изучите стандарты токенов Ethereum, включая ERC-20, ERC-721 и ERC-1155, для взаимозаменяемых и невзаимозаменяемых токенов." +lang: ru +incomplete: true +--- + +## Введение {#introduction} + +Многие стандарты разработки Ethereum сосредоточены на интерфейсах токенов. Эти стандарты помогают обеспечить компонуемость смарт-контрактов, поэтому, когда новый проект выпускает токен, он остается совместимым с существующими децентрализованными биржами и приложениями. + +Стандарты токенов определяют, как токены ведут себя и взаимодействуют в экосистеме Ethereum. Они облегчают разработчикам создание продуктов, избавляя от необходимости изобретать велосипед, и обеспечивают беспрепятственную работу токенов с кошельками, биржами и платформами DeFi. Будь то в играх, управлении или других вариантах использования, эти стандарты обеспечивают согласованность и делают Ethereum более взаимосвязанным. + +## Предварительные условия {#prerequisites} + +- [Стандарты разработки Ethereum](/developers/docs/standards/) +- [Умные контракты](/developers/docs/smart-contracts/) + +## Стандарты токенов {#token-standards} + +Вот некоторые из самых популярных стандартов токенов в Ethereum: + +- [ERC-20](/developers/docs/standards/tokens/erc-20/) — стандартный интерфейс для взаимозаменяемых токенов, таких как токены для голосования, токены для стейкинга или виртуальные валюты. + +### Стандарты NFT {#nft-standards} + +- [ERC-721](/developers/docs/standards/tokens/erc-721/) — стандартный интерфейс для невзаимозаменяемых токенов, например, свидетельство о праве собственности на произведение искусства или песню. +- [ERC-1155](/developers/docs/standards/tokens/erc-1155/) — стандарт ERC-1155 позволяет совершать более эффективные сделки и объединять транзакции, тем самым экономя средства. Этот стандарт токенов позволяет создавать как утилитарные токены (такие, как $BNB или $BAT), так и NFT, например - CryptoPunks. + +Полный список предложений [ERC](https://eips.ethereum.org/erc). + +## Дополнительные материалы {#further-reading} + +_Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!_ + +## Связанные руководства {#related-tutorials} + +- [Контрольный список интеграции токенов](/developers/tutorials/token-integration-checklist/) _— контрольный список вопросов, которые следует учитывать при взаимодействии с токенами._ +- [Как устроен смарт-контракт токена ERC-20](/developers/tutorials/understand-the-erc-20-token-smart-contract/) _— введение в развертывание вашего первого смарт-контракта в тестовой сети Ethereum._ +- [Переводы и одобрение токенов ERC-20 из смарт-контракта Solidity](/developers/tutorials/transfers-and-approval-of-erc-20-tokens-from-a-solidity-smart-contract/) _— как использовать смарт-контракт для взаимодействия с токеном на языке Solidity._ +- [Реализация рынка ERC-721 [практическое руководство]](/developers/tutorials/how-to-implement-an-erc721-market/) _— как выставлять токенизированные предметы на продажу на децентрализованной доске объявлений._ diff --git a/public/content/translations/ru/developers/docs/storage/index.md b/public/content/translations/ru/developers/docs/storage/index.md new file mode 100644 index 00000000000..43708a344c4 --- /dev/null +++ b/public/content/translations/ru/developers/docs/storage/index.md @@ -0,0 +1,216 @@ +--- +title: "Децентрализованное хранилище" +description: "Обзор того, что такое децентрализованное хранилище, и доступные инструменты для его интеграции в децентрализованное приложение." +lang: ru +--- + +В отличие от централизованного сервера, управляемого одной компанией или организацией, децентрализованные системы хранения состоят из одноранговой сети пользователей-операторов, которые владеют частью общих данных, создавая отказоустойчивую систему совместного использования файловых хранилищ. Это может быть приложение на основе блокчейна или любая одноранговая сеть. + +Сам Ethereum можно использовать как децентрализованную систему хранения, это касается хранения кода во всех смарт-контрактах. Однако, когда дело доходит до больших объемов данных - Ethereum для этого не предназначен. Блокчейн постоянно растет, но на момент написания этой статьи размер блокчейна Ethereum составляет около 500 ГБ – 1 ТБ ([в зависимости от клиента](https://etherscan.io/chartsync/chaindefault)), и каждый узел в сети должен иметь возможность хранить все эти данные. Если бы цепочка расширилась до больших объемов данных (скажем, 5 ТБ), было бы невозможно, чтобы все узлы продолжали работать. Кроме того, стоимость развертывания такого большого объема данных в основную сеть будет непомерно высокой из-за комиссий за [газ](/developers/docs/gas). + +Из-за этих ограничений нам нужна другая цепочка или методология для децентрализованного хранения больших объемов данных. + +При рассмотрении вариантов децентрализованного хранилища (dStorage) пользователь должен помнить о нескольких вещах. + +- Механизм устойчивости/структура стимулов +- Обеспечение сохранности данных +- Децентрализация +- Консенсус + +## Механизм сохранения / структура стимулов {#persistence-mechanism} + +### На основе блокчейна {#blockchain-based} + +Чтобы часть данных сохранялась навсегда, нам нужно использовать механизм устойчивости. Например, в Ethereum механизм устойчивости заключается в том, что при запуске узла необходимо учитывать всю цепочку. Новые данные прикрепляются к концу цепочки, и она продолжает расти, требуя, чтобы каждый узел копировал все новые включенные данные. + +Это называется сохранением **на основе блокчейна**. + +Проблема с сохранением на основе блокчейна в том, что блокчейн может стать слишком большим, чтобы его можно было поддерживать и хранить все данные (например, по оценкам [многих источников](https://healthit.com.au/how-big-is-the-internet-and-how-do-we-measure-it/), для Интернета требуется более 40 зеттабайт дискового пространства). + +Кроме того, блокчейн должен иметь механизм поощрения. Для постоянства на основе блокчейна существует платеж валидатору. Когда данные добавляются в цепочку, валидаторам платят за добавление данных. + +Платформы с устойчивостью на основе блокчейна: + +- Ethereum +- [Arweave](https://www.arweave.org/) + +### На основе контракта {#contract-based} + +**Сохранение на основе контракта** исходит из того, что данные не могут быть скопированы каждым узлом и храниться вечно, а вместо этого их сохранность должна поддерживаться контрактными соглашениями. Эти соглашения установлены между множеством узлов, пообещавших хранить фрагмент данных некоторое время. Они должны быть оплачены или обновлены каждый раз, когда они исполняются для того, чтобы записать новое состояние. + +В большинстве случаев вместо хранения всех данных ончейн сохраняется хэш местоположения данных в блокчейне. Таким образом нет надобности держать все данные в блокчейне. + +Платформы с устойчивостью на основе контракта: + +- [Filecoin](https://docs.filecoin.io/basics/what-is-filecoin) +- [Skynet](https://sia.tech/) +- [Storj](https://storj.io/) +- [Züs](https://zus.network/) +- [Crust Network](https://crust.network) +- [Swarm](https://www.ethswarm.org/) +- [4EVERLAND](https://www.4everland.org/) + +### Дополнительные соображения {#additional-consideration} + +IPFS — это распределенная система для хранения и доступа к файлам, веб-сайтам, приложениям и данным. Она не имеет встроенной системы поощрения, но вместо этого может использоваться с любым из вышеперечисленных объектов на контрактной основе для долгосрочного хранения. Другой способ сохранения данных на IPFS это работа со службой привязки, которая привязывает ваши данные для вас. Вы можете запустить свой собственный узел IPFS и внести свой вклад в сеть, чтобы сохранить свои и/или чужие данные бесплатно! + +- [IPFS](https://docs.ipfs.io/concepts/what-is-ipfs/) +- [Pinata](https://www.pinata.cloud/) _(сервис закрепления IPFS)_ +- [web3.storage](https://web3.storage/) _(сервис закрепления IPFS/Filecoin)_ +- [Infura](https://infura.io/product/ipfs) _(сервис закрепления IPFS)_ +- [IPFS Scan](https://ipfs-scan.io) _(обозреватель закреплений IPFS)_ +- [4EVERLAND](https://www.4everland.org/) _(сервис закрепления IPFS)_ +- [Filebase](https://filebase.com) _(сервис закрепления IPFS)_ +- [Spheron Network](https://spheron.network/) _(сервис закрепления IPFS/Filecoin)_ + +SWARM — это децентрализованная технология хранения и распространения данных с системой поощрения за хранение и оракулом цен на аренду хранилища. + +## Хранение данных {#data-retention} + +Чтобы сохранить данные, системы должны иметь какой-то механизм, обеспечивающий это сохранение. + +### Механизм оспаривания {#challenge-mechanism} + +Один из самых популярных способов убедиться что данные сохранены - задать узлам криптографическую задачу, призванную подтвердить что узлы все еще хранят данные. Один из простых вариантов - посмотреть на proof-of-access в Arweave. Они проверяют узлы, чтобы убедиться имеют ли последние доступ одновременно к самому свежему блоку - и случайному блоку из прошлого. Если узел не может ответить корректно - он штрафуется. + +Виды децентрализованных хранилищ с механизмом обеспечения: + +- Züs +- Skynet +- Arweave +- Filecoin +- Crust Network +- 4EVERLAND + +### Децентрализованность {#decentrality} + +Не существует хороших инструментов для измерения уровня децентрализации платформ, предоставляющих доказательства того, что они не централизованы, но в целом вам следует использовать инструменты, которые не имеют какой-либо формы KYC. + +Децентрализованные инструменты без KYC: + +- Skynet +- Arweave +- Filecoin +- IPFS +- Ethereum +- Crust Network +- 4EVERLAND + +### Консенсус {#consensus} + +Большинство из этих инструментов имеют собственную версию [механизма консенсуса](/developers/docs/consensus-mechanisms/), но, как правило, они основаны либо на [**доказательстве работы (PoW)**](/developers/docs/consensus-mechanisms/pow/), либо на [**доказательстве владения (PoS)**](/developers/docs/consensus-mechanisms/pos/). + +На основе доказательства работы: + +- Skynet +- Arweave + +На основе доказательства владения: + +- Ethereum +- Filecoin +- Züs +- Crust Network + +## Связанные инструменты {#related-tools} + +**IPFS — _InterPlanetary File System — это децентрализованное хранилище и система ссылок на файлы для Ethereum._** + +- [Ipfs.io](https://ipfs.io/) +- [Документация](https://docs.ipfs.io/) +- [GitHub](https://github.com/ipfs/ipfs) + +**Storj DCS — _безопасное, приватное и совместимое с S3 децентрализованное облачное хранилище объектов для разработчиков._** + +- [Storj.io](https://storj.io/) +- [Документация](https://docs.storj.io/) +- [GitHub](https://github.com/storj/storj) + +**Sia — _использует криптографию для создания бездоверительного рынка облачных хранилищ, позволяя покупателям и продавцам совершать транзакции напрямую._** + +- [Skynet.net](https://sia.tech/) +- [Документация](https://docs.sia.tech/) +- [GitHub](https://github.com/SiaFoundation/) + +**Filecoin — _Filecoin был создан той же командой, что стоит за IPFS. Это система поощрения, построенная поверх идеалов IPFS._** + +- [Filecoin.io](https://filecoin.io/) +- [Документация](https://docs.filecoin.io/) +- [GitHub](https://github.com/filecoin-project/) + +**Arweave — _Arweave — это платформа децентрализованного хранилища (dStorage) для хранения данных._** + +- [Arweave.org](https://www.arweave.org/) +- [Документация](https://docs.arweave.org/info/) +- [Arweave](https://github.com/ArweaveTeam/arweave/) + +**Züs — _Züs — это платформа децентрализованного хранилища (dStorage) на основе доказательства владения (proof-of-stake) с шардингом и блобберами._** + +- [zus.network](https://zus.network/) +- [Документация](https://docs.zus.network/zus-docs/) +- [GitHub](https://github.com/0chain/) + +**Crust Network — _Crust — это платформа децентрализованного хранилища (dStorage), работающая поверх IPFS._** + +- [Crust.network](https://crust.network) +- [Документация](https://wiki.crust.network) +- [GitHub](https://github.com/crustio) + +**Swarm — _платформа распределенного хранения и служба распространения контента для стека Ethereum Web3._** + +- [EthSwarm.org](https://www.ethswarm.org/) +- [Документация](https://docs.ethswarm.org/) +- [GitHub](https://github.com/ethersphere/) + +**OrbitDB — _децентрализованная одноранговая база данных поверх IPFS._** + +- [OrbitDB.org](https://orbitdb.org/) +- [Документация](https://github.com/orbitdb/field-manual/) +- [GitHub](https://github.com/orbitdb/orbit-db/) + +**Aleph.im — _децентрализованный облачный проект (база данных, файловое хранилище, вычисления и DID). Уникальное сочетание оффчейн и ончейн одноранговых технологий. Уникальное сочетание оффчейн и ончейн одноранговых технологий._** + +- [Aleph.im](https://aleph.cloud/) +- [Документация](https://docs.aleph.cloud/) +- [GitHub](https://github.com/aleph-im/) + +**Ceramic — _управляемое пользователем хранилище баз данных IPFS для приложений с большим объемом данных и высокой вовлеченностью._** + +- [Ceramic.network](https://ceramic.network/) +- [Документация](https://developers.ceramic.network/) +- [GitHub](https://github.com/ceramicnetwork/js-ceramic/) + +**Filebase — _совместимое с S3 децентрализованное хранилище и геоизбыточный сервис закрепления IPFS. Все файлы, загруженные в IPFS через Filebase, автоматически закрепляются в инфраструктуре Filebase с 3-кратной репликацией по всему миру._** + +- [Filebase.com](https://filebase.com/) +- [Документация](https://docs.filebase.com/) +- [GitHub](https://github.com/filebase) + +**4EVERLAND — _платформа облачных вычислений Web 3.0, которая объединяет основные возможности хранения, вычислений и сетевого взаимодействия, совместима с S3 и обеспечивает синхронное хранение данных в децентрализованных сетях хранения, таких как IPFS и Arweave._** + +- [4everland.org](https://www.4everland.org/) +- [Документация](https://docs.4everland.org/) +- [GitHub](https://github.com/4everland) + +**Kaleido — _платформа «блокчейн как услуга» с узлами IPFS, создаваемыми одним нажатием кнопки_** + +- [Kaleido](https://kaleido.io/) +- [Документация](https://docs.kaleido.io/kaleido-services/ipfs/) +- [GitHub](https://github.com/kaleido-io) + +**Spheron Network — _Spheron — это платформа как услуга (PaaS), предназначенная для децентрализованных приложений, которые хотят запустить свои приложения в децентрализованной инфраструктуре с наилучшей производительностью. Она предоставляет готовые к использованию вычислительные мощности, децентрализованное хранилище, CDN и веб-хостинг._** + +- [spheron.network](https://spheron.network/) +- [Документация](https://docs.spheron.network/) +- [GitHub](https://github.com/spheronFdn) + +## Дополнительные материалы {#further-reading} + +- [Что такое децентрализованное хранилище?](https://coinmarketcap.com/academy/article/what-is-decentralized-storage-a-deep-dive-by-filecoin) — _CoinMarketCap_ +- [Развенчиваем пять распространенных мифов о децентрализованном хранилище](https://www.storj.io/blog/busting-five-common-myths-about-decentralized-storage) — _Storj_ + +_Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!_ + +## Смежные темы {#related-topics} + +- [Фреймворки для разработки](/developers/docs/frameworks/)