Перейти к основному содержанию
Работает на: публичных сетях (mainnet и testnet). Чтобы верифицировать контракты в Virtual Environment, см. Деплой и верификация контрактов и Верификация прокси-контрактов с помощью Foundry.
Tenderly верифицирует смарт-контракты, развёрнутые через команды Foundry forge create, forge script и forge verify-contract, посредством своего API верификации, совместимого с Etherscan. Верификация бывает либо приватной (исходный код виден только внутри вашего проекта в Tenderly), либо публичной (виден всем, у кого есть ссылка).

Прежде чем начать

Вам понадобятся slug вашего аккаунта и проекта Tenderly, ключ доступа Tenderly (Dashboard → Account Settings → Authorization) и профинансированный аккаунт в целевой сети. Верификатор Tenderly сопоставляет хеш метаданных, который компилятор Solidity добавляет к развёрнутому байткоду, с исходным кодом, который вы отправляете. Сохраняйте метаданные в результатах компиляции и фиксируйте настройки компилятора, чтобы они не изменились между моментом деплоя и моментом верификации:
foundry.toml
cbor_metadata = true и bytecode_hash = "ipfs" — это значения по умолчанию в Foundry, но некоторые шаблоны их убирают; bytecode_hash = "none" ломает верификацию. Расхождение в настройках компилятора между деплоем и верификацией приводит к ошибке Bytecode does not match deployed contract. В примерах ниже используется Base Sepolia (chain ID 84532). Настройка окружения:
.env

URL верификатора

Каждая команда верификации Foundry принимает --verifier-url, указывающий на API верификации Tenderly, и --etherscan-api-key $TENDERLY_ACCESS_KEY для аутентификации:
Каждый сегмент URL соответствует значению, которое можно посмотреть в Dashboard:

Приватная верификация

Приватно верифицированные контракты видны только участникам вашего проекта в разделе Contracts в Dashboard.
showLineNumbers
forge verify-contract ожидает, что аргументы конструктора уже закодированы в ABI; используйте cast abi-encode, чтобы получить их. --watch опрашивает верификатор, пока верификация не завершится, и печатает результат.
При успехе Foundry печатает строку URL: https://etherscan.io/address/.... Это особенность отображения потока, совместимого с Etherscan; контракт был верифицирован в Tenderly, а не в Etherscan. Подтвердите это в Dashboard в разделе Contracts.

Публичная верификация

Замените URL верификатора на вариант с суффиксом /public; больше ничего менять не нужно. Страница с верифицированным исходным кодом станет доступна всем, у кого есть ссылка, без входа в Tenderly.
showLineNumbers
Публичная верификация необратима. Публично верифицированный контракт остаётся публичным. Приватная и публичная верификация — независимые записи: чтобы сделать приватно верифицированный контракт публичным, повторно верифицируйте его через URL /public.

Деплой и верификация одной командой

forge create и forge script принимают те же флаги встроенно, поэтому деплой и верификацию можно запустить одной командой. В отличие от forge verify-contract, обе они принимают аргументы конструктора как сырые значения и сами кодируют их в ABI:
showLineNumbers
Ставьте --constructor-args в конце. Он жадно поглощает остаток командной строки, поэтому любой флаг, поставленный после него, будет воспринят как ещё один аргумент конструктора.
Для деплоев нескольких контрактов используйте forge script с флагом --slow; каждый контракт, который развёртывает скрипт, верифицируется автоматически, а аргументы конструктора берутся из broadcast-лога. Без --slow пакетирование broadcast может отправить транзакцию до подтверждения предыдущей, из-за чего может произойти гонка с шагом верификации:
showLineNumbers

Верификация контракта, который вы не разворачивали

Когда контракт верифицирован в публичном обозревателе (Etherscan, Basescan), но не в вашем проекте Tenderly, клонируйте верифицированный исходный код локально с помощью forge clone и повторно верифицируйте его через API Tenderly:
showLineNumbers
forge clone скачивает верифицированный исходный код из Etherscan-совместимого API исходной сети (используйте ключ соответствующего обозревателя для каждой сети), восстанавливает структуру проекта и фиксирует настройки компилятора, которые использовал исходный деплойер. Запустите forge build в клонированной директории, чтобы убедиться, что она собирается; ошибки разрешения импортов обычно связаны с remappings.txt. Затем верифицируйте в Tenderly:
showLineNumbers
Если верификация падает с ошибкой Bytecode does not match deployed contract, передайте исходные настройки компилятора явно. Все они перечислены на странице обозревателя, где контракт уже верифицирован, в разделе исходного кода контракта:
showLineNumbers

Контракты, живущие в директории lib

forge build компилирует только то, что достижимо из src/. Контракт, который существует только внутри зависимости в lib/ (прокси, стандартная реализация ERC), никогда не попадает в кеш сборки, и forge verify-contract падает с ошибкой:
Создайте однострочный файл src/Imports.sol, который импортирует контракт, а затем пересоберите:
src/Imports.sol
Imports.sol никогда не отправляется в верификатор; он лишь заставляет компилятор кешировать контракт и его зависимости. После этого верифицируйте, используя полный путь контракта в lib/, поскольку исходный код физически находится именно там. Для TransparentUpgradeableProxy, который вы не разворачивали, конструктор имеет вид (address _logic, address initialOwner, bytes _data), и большую его часть можно восстановить из состояния сети:
showLineNumbers
Версия компилятора, число прогонов оптимизатора и версия EVM берутся со страницы обозревателя уже верифицированной реализации. Если реализация нигде не верифицирована, обратитесь к foundry.toml или скриптам деплоя разворачивающего проекта.

Устранение неполадок