> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tenderly.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Деплой и верификация контрактов

> Разверните Solidity-контракты в Virtual Environment с помощью Foundry или Hardhat, с верификацией для Debugger, Gas Profiler и Simulator.

Разверните Solidity-контракты в Virtual Environment с помощью Foundry или Hardhat. Контракты, задеплоенные в Virtual Environment, называются **virtual contracts** и появляются в разделе **Contracts** на вкладке **Virtual Contracts**.

Верифицируйте контракты по мере деплоя. Верифицированные контракты открывают доступ к Debugger, Gas Profiler, Simulator и более информативным представлениям транзакций в обозревателе.

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

* [Virtual Environment](/virtual-environments/quickstart). Скопируйте её RPC URL из панели.
* [Пополненный адрес деплойера](/virtual-environments/unlimited-faucet) в этой Virtual Environment.

Для верификации в Virtual Environment не нужен отдельный access key: сам RPC URL является аутентификацией, а эндпоинт верификатора — это тот же URL с добавленным `/verify`.

<Warning>
  По умолчанию контракты, верифицированные в Virtual Environment, приватны. В зависимости от настроек видимости [публичного обозревателя](/virtual-environments/explorer#public-explorer), код может быть виден снаружи. Проверьте переключатель публичного обозревателя и [видимость верификации](/virtual-environments/explorer#public-explorer) перед верификацией того, что вы хотите оставить приватным.
</Warning>

## Деплой и верификация

<Tabs>
  <Tab title="Foundry">
    ### Настройте `foundry.toml`

    Верификатор Tenderly сопоставляет хеш метаданных, который компилятор Solidity добавляет к задеплоенному байткоду, с источником, который вы предоставляете. Сохраняйте метаданные в скомпилированном выводе, явно задавая `cbor_metadata` и `bytecode_hash`:

    ```toml title="foundry.toml" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    [profile.default]
    src = "src"
    out = "out"
    libs = ["lib"]
    solc_version = "0.8.24"
    optimizer = true
    optimizer_runs = 200

    # Required for Tenderly contract verification:
    # keep the CBOR metadata so the verifier can match the on-chain bytecode hash.
    cbor_metadata = true
    bytecode_hash = "ipfs"
    ```

    `cbor_metadata = true` и `bytecode_hash = "ipfs"` — значения Foundry по умолчанию, но некоторые шаблоны их убирают; `bytecode_hash = "none"` ломает верификацию. Зафиксируйте `solc_version` и настройки оптимизатора, чтобы повторная верификация компилировала тот же байткод.

    Если ваш проект использует библиотеки вроде OpenZeppelin, объявите remappings явно в `remappings.txt`:

    ```bash title="remappings.txt" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
    forge-std/=lib/forge-std/src/
    ```

    При автообнаружении remappings payload верификации может содержать иные строки remapping, чем использовала сборка, что приводит к ошибкам несоответствия байткода.

    ### Установите переменные окружения

    ```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    export TENDERLY_VIRTUAL_TESTNET_RPC=...   # paste your RPC URL
    export TENDERLY_VERIFIER_URL=$TENDERLY_VIRTUAL_TESTNET_RPC/verify
    export PRIVATE_KEY=...                    # deployer private key
    ```

    Проверьте соединение перед деплоем. `cast chain-id` должен вывести chain ID Virtual Environment, а баланс деплойера должен быть ненулевым:

    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    cast chain-id --rpc-url $TENDERLY_VIRTUAL_TESTNET_RPC
    cast balance <DEPLOYER_ADDRESS> --rpc-url $TENDERLY_VIRTUAL_TESTNET_RPC
    ```

    ### Деплой с `forge create`

    Запустите `forge create` с флагами верификации. Аргументы конструктора передаются как сырые значения; Foundry сам ABI-кодирует их и отправляет закодированную форму верификатору:

    ```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    forge create src/Counter.sol:Counter \
      --rpc-url $TENDERLY_VIRTUAL_TESTNET_RPC \
      --private-key $PRIVATE_KEY \
      --broadcast \
      --verify \
      --verifier custom \
      --verifier-url $TENDERLY_VERIFIER_URL \
      --constructor-args 42
    ```

    <Warning>
      Ставьте `--constructor-args` в конец. Он жадно поглощает остаток командной строки, поэтому любой флаг после него будет воспринят как ещё один аргумент конструктора.
    </Warning>

    ### Деплой с помощью Foundry-скрипта

    Используйте `forge script`, чтобы задеплоить несколько контрактов за один запуск. Каждое `new Foo(...)` в скрипте автоматически отправляется на верификацию, с правильными аргументами конструктора, взятыми из broadcast log. Импорты обрабатываются прозрачно: верификатор получает standard-JSON payload со всеми исходными файлами, которых коснулся компилятор, так что локальные и библиотечные импорты (например, OpenZeppelin) верифицируются без дополнительных шагов.

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

    ```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    forge script script/Counter.s.sol:CounterScript \
      --rpc-url $TENDERLY_VIRTUAL_TESTNET_RPC \
      --private-key $PRIVATE_KEY \
      --broadcast \
      --slow \
      --verify \
      --verifier custom \
      --verifier-url $TENDERLY_VERIFIER_URL
    ```

    ### Верификация уже задеплоенного контракта

    Уже развёрнутые контракты можно верифицировать через `forge verify-contract`. В отличие от `forge create`, эта команда ожидает аргументы конструктора **уже в ABI-кодированной форме**; используйте `cast abi-encode` для их получения:

    ```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    forge verify-contract $COUNTER_ADDRESS src/Counter.sol:Counter \
      --verifier custom \
      --verifier-url $TENDERLY_VERIFIER_URL \
      --constructor-args $(cast abi-encode "constructor(uint256)" 42) \
      --watch
    ```

    `--watch` опрашивает верификатор, пока верификация не завершится, и печатает результат. Для развёртываний с несколькими контрактами запускайте `forge verify-contract` по одному разу на каждый задеплоенный адрес.
  </Tab>

  <Tab title="Hardhat">
    <Info>
      Плагин `@tenderly/hardhat-tenderly` совместим с Hardhat до версии `2.22.0` включительно. См. [Hardhat verification](/contract-verification/hardhat#versions-and-compatibility) для матрицы поддерживаемых версий.

      ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      npm install hardhat@2.22.0
      ```
    </Info>

    ### Установите плагин и CLI

    Установите Tenderly Hardhat-плагин:

    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    npm install --save-dev @tenderly/hardhat-tenderly
    ```

    Установите [Tenderly CLI](https://github.com/Tenderly/tenderly-cli) и войдите в систему, чтобы плагин мог аутентифицироваться:

    <Tabs>
      <Tab title="macOS (Homebrew)">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        brew tap tenderly/tenderly
        brew install tenderly
        tenderly login
        ```
      </Tab>

      <Tab title="Linux">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        curl https://raw.githubusercontent.com/Tenderly/tenderly-cli/master/scripts/install-linux.sh | sudo sh
        tenderly login
        ```
      </Tab>

      <Tab title="Manual">
        Скачайте последний бинарник со страницы [релизов](https://github.com/Tenderly/tenderly-cli/releases), добавьте его в `$PATH`, затем выполните:

        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        tenderly login
        ```
      </Tab>
    </Tabs>

    ### Настройте Hardhat

    Добавьте `virtualMainnet` (или любое имя с префиксом `virtual` для ясности) в ваш блок `networks`, затем добавьте блок `tenderly` со слагами вашего [проекта и имени пользователя](/platform/account/projects/slug). Вызовите `tenderly.setup()` с `automaticVerifications: true`, чтобы контракты верифицировались при каждом деплое.

    ```typescript title="hardhat.config.ts" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as tenderly from "@tenderly/hardhat-tenderly";

    tenderly.setup({ automaticVerifications: true });

    const config: HardhatUserConfig = {
      solidity: "0.8.19",
      networks: {
        virtualMainnet: {
          url: process.env.TENDERLY_VIRTUAL_MAINNET_RPC!,
          chainId: 73571, // the Chain ID you selected at Virtual Environment creation
        },
      },
      tenderly: {
        project: "YOUR_PROJECT_SLUG",
        username: "YOUR_USERNAME_SLUG",
      },
    };

    export default config;
    ```

    ### Задеплойте

    Запустите ваш deploy-скрипт против сети, которую вы определили. При `automaticVerifications: true` плагин верифицирует контракты по мере деплоя.

    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    npx hardhat run scripts/deploy.ts --network virtualMainnet
    ```
  </Tab>
</Tabs>

## Проверьте панель

В Tenderly Dashboard откройте **Contracts** и выберите вкладку **Virtual Contracts**. Ваши только что задеплоенные контракты появятся там, со статусом верификации по каждому контракту.

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

| Симптом                                                                                           | Вероятная причина                                                                                                                                         | Решение                                                                                                                                                             |
| ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ответ верификатора `unauthorized` / `-32004`                                                      | Неверный URL верификатора. Частая ошибка — добавление `/verify/etherscan` вместо `/verify`.                                                               | Убедитесь, что URL верификатора заканчивается ровно на `/verify`.                                                                                                   |
| `Bytecode does not match deployed contract`                                                       | Присланный исходный код скомпилировался иначе, чем то, что задеплоено: несовпадение `optimizer_runs`, другая `solc_version` или удалённый хеш метаданных. | Зафиксируйте `solc_version`, `optimizer`, `optimizer_runs` и `bytecode_hash` в `foundry.toml`. Выполните `forge clean && forge build` перед повторной верификацией. |
| `Failed to deserialize content`                                                                   | Верификатор вернул строку ошибки, которую Foundry не может распарсить — обычно оборачивает upstream-ошибку авторизации или пути.                          | Проверьте URL и повторите запуск с `-vvvv`, чтобы увидеть сырой ответ.                                                                                              |
| `Dry run enabled, not broadcasting transaction` при `forge create`                                | Не передан `--broadcast` или его поглотил `--constructor-args`.                                                                                           | Переместите `--constructor-args` в конец, чтобы он был последним флагом.                                                                                            |
| Только первый контракт верифицируется в `forge script`                                            | Гонка RPC: вторая транзакция отправлена до получения чека первой.                                                                                         | Добавьте `--slow`.                                                                                                                                                  |
| Верификатор сообщает `OK`, но обозреватель по-прежнему показывает контракт как неверифицированный | Кеширование UI.                                                                                                                                           | Сделайте hard-refresh страницы обозревателя. Статус в ответе API является достоверным.                                                                              |

## Дальнейшие шаги

* [Верификация прокси-контрактов с Foundry](/virtual-environments/develop/verify-proxy-contracts): верификация UUPS-имплементации и её ERC1967-прокси, включая апгрейды.
* [Стейджинг контрактов](/virtual-environments/ci-cd/stage-contracts): поделитесь RPC-ссылкой и адресами контрактов с командой.
* [Стейджинг вашего dApp](/virtual-environments/ci-cd/stage-dapps): направьте фронтенд на Virtual Environment.
* [Форк Virtual Environment](/virtual-environments/develop/fork-testnet): ответвление от состояния Virtual Environment.
