Перейти к основному контенту
Change page

Верификация смарт-контрактов

Смарт-контракты спроектированы так, чтобы быть «не требующими доверия» (trustless). Это означает, что пользователям не нужно доверять третьим сторонам (например, разработчикам и компаниям) перед взаимодействием с контрактом. В качестве обязательного условия для отсутствия необходимости в доверии пользователи и другие разработчики должны иметь возможность верифицировать исходный код смарт-контракта. Верификация исходного кода гарантирует пользователям и разработчикам, что опубликованный код контракта — это тот же самый код, который выполняется по адресу контракта в блокчейне Эфириума.

Важно делать различие между «верификацией исходного кода» и «формальной верификацией». Верификация исходного кода, которая будет подробно объяснена ниже, относится к проверке того, что данный исходный код смарт-контракта на языке высокого уровня (например, Solidity) компилируется в тот же байт-код, который будет выполняться по адресу контракта. Однако формальная верификация описывает проверку правильности смарт-контракта, то есть того, что контракт ведет себя так, как ожидается. Хотя это зависит от контекста, верификация контракта обычно подразумевает верификацию исходного кода.

Что такое верификация исходного кода?

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

Верификация исходного кода — это сравнение исходного кода смарт-контракта и скомпилированного байт-кода, используемого при создании контракта, для обнаружения любых различий. Верификация смарт-контрактов имеет значение, поскольку заявленный код контракта может отличаться от того, что выполняется в блокчейне.

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

Что такое полная верификация?

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

Этого можно избежать, добавив к байт-коду дополнительные данные, которые будут служить криптографической гарантией точности исходного кода и отпечатком информации о компиляции. Необходимая информация находится в метаданных контракта Solidity (opens in a new tab), и хеш этого файла добавляется к байт-коду контракта. Вы можете увидеть это в действии в песочнице метаданных (opens in a new tab).

Файл метаданных содержит информацию о компиляции контракта, включая исходные файлы и их хеши. Это означает, что если изменятся какие-либо настройки компиляции или даже один байт в одном из исходных файлов, файл метаданных изменится. Следовательно, хеш файла метаданных, который добавляется к байт-коду, также изменится. Это означает, что если байт-код контракта + добавленный хеш метаданных совпадают с данным исходным кодом и настройками компиляции, мы можем быть уверены, что это именно тот исходный код, который использовался при оригинальной компиляции, и ни один байт не отличается.

Этот тип верификации, использующий хеш метаданных, называется «полной верификацией (opens in a new tab)» (также «идеальной верификацией»). Если хеши метаданных не совпадают или не учитываются при верификации, это будет «частичным совпадением», что в настоящее время является более распространенным способом верификации контрактов. Без полной верификации можно внедрить вредоносный код (opens in a new tab), который не будет отражен в верифицированном исходном коде. Большинство разработчиков не знают о полной верификации и не сохраняют файл метаданных своей компиляции, поэтому частичная верификация до сих пор была методом де-факто для верификации контрактов.

Почему верификация исходного кода важна?

Отсутствие необходимости в доверии

Отсутствие необходимости в доверии, пожалуй, является главной предпосылкой для смарт-контрактов и децентрализованных приложений (dapp). Смарт-контракты «неизменяемы» и не могут быть модифицированы; контракт будет выполнять только ту бизнес-логику, которая определена в коде на момент развертывания. Это означает, что разработчики и предприятия не могут подделать код контракта после его развертывания в Эфириуме.

Чтобы смарт-контракт был не требующим доверия, код контракта должен быть доступен для независимой верификации. Хотя скомпилированный байт-код каждого смарт-контракта публично доступен в блокчейне, низкоуровневый язык труден для понимания — как для разработчиков, так и для пользователей.

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

Инструменты верификации исходного кода предоставляют гарантии того, что файлы исходного кода смарт-контракта совпадают с кодом ассемблера. Результатом является экосистема, не требующая доверия, где пользователи не доверяют слепо третьим сторонам, а вместо этого верифицируют код перед внесением средств в контракт.

Безопасность пользователей

В смарт-контрактах на кону обычно стоят большие деньги. Это требует более высоких гарантий безопасности и верификации логики смарт-контракта перед его использованием. Проблема в том, что недобросовестные разработчики могут обмануть пользователей, внедрив вредоносный код в смарт-контракт. Без верификации вредоносные смарт-контракты могут иметь бэкдоры (opens in a new tab), спорные механизмы контроля доступа, уязвимости, пригодные для эксплуатации, и другие вещи, ставящие под угрозу безопасность пользователей, которые остались бы незамеченными.

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

Как верифицировать исходный код смарт-контрактов Эфириума

Развертывание смарт-контракта в Эфириуме требует отправки транзакции с полезной нагрузкой данных (скомпилированным байт-кодом) на специальный адрес. Полезная нагрузка данных генерируется путем компиляции исходного кода, плюс аргументы конструктора (opens in a new tab) экземпляра контракта, добавленные к полезной нагрузке данных в транзакции. Компиляция детерминирована, что означает, что она всегда производит один и тот же результат (т. е. байт-код контракта), если используются одни и те же исходные файлы и настройки компиляции (например, версия компилятора, оптимизатор).

A diagram showing showing smart contract source code verification

Верификация смарт-контракта в основном включает следующие шаги:

  1. Передача исходных файлов и настроек компиляции в компилятор.

  2. Компилятор выводит байт-код контракта.

  3. Получение байт-кода развернутого контракта по заданному адресу.

  4. Сравнение развернутого байт-кода с перекомпилированным байт-кодом. Если коды совпадают, контракт верифицируется с данным исходным кодом и настройками компиляции.

  5. Кроме того, если хеши метаданных в конце байт-кода совпадают, это будет полным совпадением.

Обратите внимание, что это упрощенное описание верификации, и существует множество исключений, которые не будут работать с этим, например, наличие неизменяемых переменных (opens in a new tab).

Инструменты верификации исходного кода

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

Etherscan

Хотя Etherscan в основном известен как обозреватель блоков Эфириума, он также предлагает сервис верификации исходного кода (opens in a new tab) для разработчиков и пользователей смарт-контрактов.

Etherscan позволяет перекомпилировать байт-код контракта из оригинальной полезной нагрузки данных (исходный код, адрес библиотеки, настройки компилятора, адрес контракта и т. д.). Если перекомпилированный байт-код связан с байт-кодом (и параметрами конструктора) ончейн-контракта, то контракт верифицирован (opens in a new tab).

После верификации исходный код вашего контракта получает метку «Verified» (Верифицирован) и публикуется на Etherscan для аудита другими пользователями. Он также добавляется в раздел Verified Contracts (opens in a new tab) — репозиторий смарт-контрактов с верифицированными исходными кодами.

Etherscan — самый используемый инструмент для верификации контрактов. Однако верификация контрактов в Etherscan имеет недостаток: она не сравнивает хеш метаданных ончейн-байт-кода и перекомпилированного байт-кода. Поэтому совпадения в Etherscan являются частичными.

Подробнее о верификации контрактов на Etherscan (opens in a new tab).

Blockscout

Blockscout (opens in a new tab) — это обозреватель блоков с открытым исходным кодом, который также предоставляет сервис верификации контрактов (opens in a new tab) для разработчиков и пользователей смарт-контрактов. В качестве альтернативы с открытым исходным кодом Blockscout предлагает прозрачность в том, как выполняется верификация, и позволяет сообществу вносить свой вклад в улучшение процесса верификации.

Подобно другим сервисам верификации, Blockscout позволяет верифицировать исходный код вашего контракта путем перекомпиляции байт-кода и его сравнения с развернутым контрактом. После верификации ваш контракт получает статус верификации, а исходный код становится публично доступным для аудита и взаимодействия. Верифицированные контракты также перечислены в репозитории верифицированных контрактов (opens in a new tab) Blockscout для удобного просмотра и обнаружения.

Sourcify

Sourcify (opens in a new tab) — это еще один инструмент для верификации контрактов, который имеет открытый исходный код и является децентрализованным. Это не обозреватель блоков, и он верифицирует контракты только в различных сетях на базе EVM (opens in a new tab). Он действует как публичная инфраструктура для создания других инструментов поверх него и стремится обеспечить более удобное для человека взаимодействие с контрактами с использованием ABI и комментариев NatSpec (opens in a new tab), найденных в файле метаданных.

В отличие от Etherscan, Sourcify поддерживает полные совпадения с хешем метаданных. Верифицированные контракты обслуживаются в его публичном репозитории (opens in a new tab) по HTTP и IPFS (opens in a new tab), который является децентрализованным хранилищем с контентной адресацией (opens in a new tab). Это позволяет извлекать файл метаданных контракта через IPFS, поскольку добавленный хеш метаданных является хешем IPFS.

Кроме того, можно также получить файлы исходного кода через IPFS, так как хеши IPFS этих файлов также находятся в метаданных. Контракт можно верифицировать, предоставив файл метаданных и исходные файлы через его API или пользовательский интерфейс (opens in a new tab), либо используя плагины. Инструмент мониторинга Sourcify также отслеживает создание контрактов в новых блоках и пытается верифицировать контракты, если их метаданные и исходные файлы опубликованы в IPFS.

Подробнее о верификации контрактов на Sourcify (opens in a new tab).

Tenderly

Платформа Tenderly (opens in a new tab) позволяет разработчикам Web3 создавать, тестировать, отслеживать и управлять смарт-контрактами. Объединяя инструменты отладки с возможностями наблюдения и строительными блоками инфраструктуры, Tenderly помогает разработчикам ускорить разработку смарт-контрактов. Чтобы в полной мере использовать функции Tenderly, разработчикам необходимо выполнить верификацию исходного кода (opens in a new tab) с использованием нескольких методов.

Контракт можно верифицировать приватно или публично. Если смарт-контракт верифицирован приватно, он виден только вам (и другим участникам вашего проекта). Публичная верификация контракта делает его видимым для всех, кто использует платформу Tenderly.

Вы можете верифицировать свои контракты с помощью панели управления (opens in a new tab), плагина Tenderly для Hardhat (opens in a new tab) или CLI (opens in a new tab).

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

Использование плагина Tenderly для Hardhat позволяет получить больше контроля над процессом верификации с меньшими усилиями, давая возможность выбирать между автоматической (без кода) и ручной (на основе кода) верификацией.

Дополнительная литература