> ## 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.

# Foundry का उपयोग करके Smart Contract सत्यापन

> Foundry-deployed contracts को Tenderly के verification API के माध्यम से सार्वजनिक नेटवर्क्स पर निजी या सार्वजनिक रूप से forge verify-contract के साथ सत्यापित करें।

<Info>
  **इन पर काम करता है:** सार्वजनिक नेटवर्क (mainnets और testnets)। किसी Virtual Environment पर contracts सत्यापित करने के लिए, [Deploy and verify contracts](/virtual-environments/develop/deploy-contracts) और [Verify proxy contracts with Foundry](/virtual-environments/develop/verify-proxy-contracts) देखें।
</Info>

Tenderly, Foundry के `forge create`, `forge script`, और `forge verify-contract` commands के साथ deploy किए गए smart contracts को अपने Etherscan-compatible verification API के माध्यम से सत्यापित करता है। सत्यापन या तो निजी होता है (source केवल आपके Tenderly प्रोजेक्ट के अंदर दिखाई देता है) या सार्वजनिक (link वाले किसी भी व्यक्ति को दिखाई देता है)।

## शुरू करने से पहले

आपको अपने Tenderly account और project [slugs](/platform/account/projects/slug), एक [Tenderly access key](/platform/account/projects/api-tokens) (Dashboard → Account Settings → Authorization), और लक्ष्य नेटवर्क पर एक funded account चाहिए।

Tenderly का verifier उस metadata hash की तुलना करता है जिसे Solidity compiler deploy किए गए bytecode में जोड़ता है, आपके द्वारा सबमिट किए गए source के साथ। compile किए गए output में metadata रखें, और compiler settings को pin करें ताकि वे deploy समय और verify समय के बीच drift न हों:

```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 के डिफ़ॉल्ट हैं, लेकिन कुछ templates उन्हें हटा देते हैं; `bytecode_hash = "none"` सत्यापन को तोड़ देता है। deploy और verify के बीच compiler-setting drift के कारण `Bytecode does not match deployed contract` विफलताएँ होती हैं।

नीचे दिए गए उदाहरण Base Sepolia (chain ID `84532`) का उपयोग करते हैं। environment सेट अप करें:

```bash title=".env" showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
BASE_SEPOLIA_RPC=https://sepolia.base.org
PRIVATE_KEY=...                           # a funded key on the target network

TENDERLY_ACCOUNT=...                      # your account slug
TENDERLY_PROJECT=...                      # your project slug
TENDERLY_ACCESS_KEY=...                   # from Account Settings -> Authorization

TENDERLY_PRIVATE_VERIFIER_URL=https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT}/project/${TENDERLY_PROJECT}/etherscan/verify/network/84532
TENDERLY_PUBLIC_VERIFIER_URL=${TENDERLY_PRIVATE_VERIFIER_URL}/public
```

## Verifier URL

हर Foundry verification command Tenderly के verification API की ओर इंगित करने वाला `--verifier-url` और authentication के लिए `--etherscan-api-key $TENDERLY_ACCESS_KEY` लेता है:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
https://api.tenderly.co/api/v1/account/$TENDERLY_ACCOUNT/project/$TENDERLY_PROJECT/etherscan/verify/network/$NETWORK_ID
```

प्रत्येक URL segment एक मान से mapped है जिसे आप Dashboard से पढ़ सकते हैं:

| Segment                     | यह क्या है                                                                                                                                      |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `account/$TENDERLY_ACCOUNT` | आपका Tenderly account (user या organization) [slug](/platform/account/projects/slug)। Case-sensitive।                                           |
| `project/$TENDERLY_PROJECT` | वह प्रोजेक्ट जिसके तहत सत्यापित contract file किया जाता है।                                                                                     |
| `network/$NETWORK_ID`       | वह chain जिस पर contract deploy है, decimal chain ID के रूप में (Ethereum Mainnet के लिए `1`, Base के लिए `8453`, Base Sepolia के लिए `84532`)। |
| कोई suffix नहीं             | निजी सत्यापन: contract केवल आपके प्रोजेक्ट के अंदर दिखाई देता है।                                                                               |
| `/public` suffix            | सार्वजनिक सत्यापन: contract source link वाले किसी भी व्यक्ति को दिखाई देता है, किसी Tenderly login की आवश्यकता नहीं।                            |

## निजी सत्यापन

निजी रूप से सत्यापित contracts केवल आपके प्रोजेक्ट के सदस्यों को Dashboard में **Contracts** के अंतर्गत दिखाई देते हैं।

```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
COUNTER_ADDRESS=0x...   # the deployed contract address

forge verify-contract $COUNTER_ADDRESS src/Counter.sol:Counter \
  --verifier-url       $TENDERLY_PRIVATE_VERIFIER_URL \
  --etherscan-api-key  $TENDERLY_ACCESS_KEY \
  --constructor-args   $(cast abi-encode "constructor(uint256)" 7) \
  --watch
```

`forge verify-contract` constructor arguments को **पहले से ABI-encoded** के रूप में अपेक्षित करता है; उन्हें उत्पन्न करने के लिए `cast abi-encode` का उपयोग करें। `--watch` verifier को तब तक poll करता है जब तक सत्यापन समाप्त नहीं हो जाता और परिणाम प्रिंट करता है।

<Note>
  Foundry का output सफलता पर एक `URL: https://etherscan.io/address/...` line प्रिंट करता है। यह Etherscan-compatible flow का display quirk है; contract Tenderly पर सत्यापित हुआ था, Etherscan पर नहीं। Dashboard में **Contracts** के अंतर्गत पुष्टि करें।
</Note>

## सार्वजनिक सत्यापन

verifier URL को `/public`-suffixed variant के लिए बदलें; और कुछ नहीं बदलता। सत्यापित source page link वाले किसी भी व्यक्ति द्वारा, बिना Tenderly login के, पहुँच योग्य हो जाता है।

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

<Warning>
  सार्वजनिक सत्यापन अपरिवर्तनीय है। सार्वजनिक रूप से सत्यापित contract सार्वजनिक रहता है। निजी और सार्वजनिक सत्यापन स्वतंत्र records हैं: किसी निजी रूप से सत्यापित contract को सार्वजनिक बनाने के लिए, इसे `/public` URL के विरुद्ध पुनः सत्यापित करें।
</Warning>

## एक चरण में deploy और verify करें

`forge create` और `forge script` समान flags को inline स्वीकार करते हैं, इसलिए deployment और verification एक command के रूप में चलते हैं। `forge verify-contract` के विपरीत, दोनों constructor arguments को raw values के रूप में लेते हैं और आपके लिए उन्हें ABI-encode करते हैं:

```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
forge create src/Counter.sol:Counter \
  --rpc-url            $BASE_SEPOLIA_RPC \
  --private-key        $PRIVATE_KEY \
  --broadcast \
  --verify \
  --verifier-url       $TENDERLY_PRIVATE_VERIFIER_URL \
  --etherscan-api-key  $TENDERLY_ACCESS_KEY \
  --constructor-args   7
```

<Warning>
  `--constructor-args` को अंत में रखें। यह लालच से command line के बाकी हिस्से का उपभोग कर लेता है, इसलिए इसके बाद रखे गए किसी भी flag को एक और constructor argument के रूप में माना जाता है।
</Warning>

Multi-contract deployments के लिए, `--slow` के साथ `forge script` का उपयोग करें; script द्वारा deploy किया गया प्रत्येक contract स्वचालित रूप से broadcast log से लिए गए अपने constructor arguments के साथ सत्यापित हो जाता है। [`--slow`](https://www.getfoundry.sh/reference/forge/script?highlight=slow#forge-script) के बिना, broadcast batching पिछले transaction की पुष्टि होने से पहले एक transaction सबमिट कर सकती है, जो verification चरण को race कर सकती है:

```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
forge script script/Deploy.s.sol:DeployScript \
  --rpc-url            $BASE_SEPOLIA_RPC \
  --private-key        $PRIVATE_KEY \
  --broadcast --slow \
  --verify \
  --verifier-url       $TENDERLY_PRIVATE_VERIFIER_URL \
  --etherscan-api-key  $TENDERLY_ACCESS_KEY
```

## ऐसा contract सत्यापित करें जिसे आपने deploy नहीं किया

जब कोई contract किसी सार्वजनिक explorer (Etherscan, Basescan) पर सत्यापित है लेकिन आपके Tenderly प्रोजेक्ट में नहीं है, तो [`forge clone`](https://www.getfoundry.sh/reference/forge/clone) के साथ सत्यापित source को स्थानीय रूप से clone करें और इसे Tenderly के API के माध्यम से पुनः सत्यापित करें:

```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
forge clone $CONTRACT_ADDRESS -e $ETHERSCAN_API_KEY --chain 1
```

`forge clone` source chain के Etherscan-compatible API से सत्यापित source को download करता है (प्रत्येक chain के लिए matching explorer की key का उपयोग करें), प्रोजेक्ट layout को पुनर्निर्मित करता है, और मूल deployer द्वारा उपयोग की गई compiler settings को pin करता है। यह पुष्टि करने के लिए कि यह compile होता है, cloned directory में `forge build` चलाएँ; import-resolution errors आमतौर पर `remappings.txt` तक trace करते हैं।

फिर Tenderly के विरुद्ध सत्यापित करें:

```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
forge verify-contract $CONTRACT_ADDRESS src/MyContract.sol:MyContract \
  --verifier-url       $TENDERLY_PRIVATE_VERIFIER_URL \
  --etherscan-api-key  $TENDERLY_ACCESS_KEY \
  --watch
```

यदि सत्यापन `Bytecode does not match deployed contract` के साथ विफल होता है, तो मूल compiler settings स्पष्ट रूप से पास करें। ये सभी explorer page पर सूचीबद्ध हैं जहाँ contract पहले से सत्यापित है, contract source code अनुभाग के तहत:

```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
forge verify-contract $CONTRACT_ADDRESS src/MyContract.sol:MyContract \
  --verifier-url       $TENDERLY_PRIVATE_VERIFIER_URL \
  --etherscan-api-key  $TENDERLY_ACCESS_KEY \
  --compiler-version   v0.8.27+commit.40a35a09 \
  --optimizer-runs     10000 \
  --evm-version        prague \
  --constructor-args   $ENCODED_ARGS \
  --watch
```

### Contracts जो `lib` directory में रहते हैं

`forge build` केवल वही compile करता है जो `src/` से पहुँच योग्य है। एक contract जो केवल `lib/` dependency के अंदर मौजूद है (एक proxy, एक मानक ERC implementation) कभी भी build cache में प्रवेश नहीं करता, और `forge verify-contract` इसके साथ विफल हो जाता है:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
Error: Failed to get standard json input
- cannot resolve file at "lib/openzeppelin-contracts-upgradeable/lib/..."
```

एक-line वाला `src/Imports.sol` बनाएँ जो contract को import करता है, फिर पुनः build करें:

```solidity title="src/Imports.sol" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
```

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
forge build --force
```

`Imports.sol` कभी भी verifier को नहीं भेजा जाता; यह केवल compiler को contract और उसकी dependencies को cache करने के लिए मजबूर करता है। फिर contract के पूर्ण `lib/` path का उपयोग करके सत्यापित करें, क्योंकि source वहीं भौतिक रूप से रहता है।

एक `TransparentUpgradeableProxy` के लिए जिसे आपने deploy नहीं किया, constructor `(address _logic, address initialOwner, bytes _data)` है, और इसका अधिकांश भाग chain state से पुनर्निर्मित किया जा सकता है:

```bash showLineNumbers theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# 1. _logic: the implementation address (ERC-1967 slot)
cast implementation $PROXY_ADDRESS --rpc-url $RPC_URL

# 2. initialOwner: owner of the ProxyAdmin contract
cast admin $PROXY_ADDRESS --rpc-url $RPC_URL                      # returns the ProxyAdmin
cast call $PROXY_ADMIN "owner()(address)" --rpc-url $RPC_URL      # returns initialOwner

# 3. _data: the initialize() calldata from the deployment transaction
#    (decode the factory calldata on the explorer; initialize(address) is selector 0xc4d66de8)

ENCODED_ARGS=$(cast abi-encode "constructor(address,address,bytes)" $LOGIC $INITIAL_OWNER $DATA)

forge verify-contract $PROXY_ADDRESS \
  lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy \
  --verifier-url       $TENDERLY_PRIVATE_VERIFIER_URL \
  --etherscan-api-key  $TENDERLY_ACCESS_KEY \
  --compiler-version   v0.8.27+commit.40a35a09 \
  --optimizer-runs     200 \
  --evm-version        shanghai \
  --constructor-args   $ENCODED_ARGS \
  --watch
```

Compiler संस्करण, optimizer runs, और EVM संस्करण पहले से सत्यापित implementation के explorer page से आते हैं। यदि implementation कहीं भी सत्यापित नहीं है, तो deploying project के `foundry.toml` या deployment scripts पर वापस जाएँ।

## समस्या निवारण

| लक्षण                                                                | संभावित कारण                                                                                                                                                       | समाधान                                                                                                                                                                                                                                          |
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `unauthorized`                                                       | गुम या गलत `--etherscan-api-key`, या access key निरस्त कर दी गई थी।                                                                                                | एक नई [access key](/platform/account/projects/api-tokens) उत्पन्न करें और `TENDERLY_ACCESS_KEY` पुनः सेट करें।                                                                                                                                  |
| `not found`                                                          | verifier URL में गलत account slug, project slug, या chain ID।                                                                                                      | प्रत्येक URL segment की पुनः जाँच करें। account slug case-sensitive है।                                                                                                                                                                         |
| `Bytecode does not match deployed contract`                          | सबमिट किया गया source deploy किए गए से अलग तरीके से compile हुआ: एक `optimizer_runs` mismatch, एक अलग `solc_version` या EVM संस्करण, या एक stripped metadata hash। | `foundry.toml` में `solc_version`, `optimizer`, `optimizer_runs`, और `bytecode_hash` को pin करें, या `--compiler-version --optimizer-runs --evm-version` स्पष्ट रूप से पास करें। पुनः सत्यापित करने से पहले `forge clean && forge build` चलाएँ। |
| `Failed to deserialize content`                                      | verifier ने एक error string लौटाया जिसे Foundry parse नहीं कर सकता, आमतौर पर एक upstream auth या path error को wrap करते हुए।                                      | URL की पुनः जाँच करें और raw response देखने के लिए `-vvvv` के साथ पुनः चलाएँ।                                                                                                                                                                   |
| `Failed to get standard json input - cannot resolve file at lib/...` | contract कभी भी `src/` से import नहीं किया जाता, इसलिए यह build cache से गायब है।                                                                                  | एक `src/Imports.sol` बनाएँ जो इसे import करे, फिर `forge build --force`। [Contracts जो `lib` directory में रहते हैं](#contracts-that-live-in-the-lib-directory) देखें।                                                                          |
| `forge create` पर `Dry run enabled, not broadcasting transaction`    | `--broadcast` पास नहीं किया गया, या `--constructor-args` द्वारा निगल लिया गया।                                                                                     | `--constructor-args` को अंतिम flag बनाने के लिए move करें।                                                                                                                                                                                      |
| `forge script` पर केवल पहला contract सत्यापित होता है                | RPC race: दूसरा transaction पहले receipt से पहले सबमिट किया गया था।                                                                                                | `--slow` जोड़ें।                                                                                                                                                                                                                                |
| सत्यापन सफल होता है लेकिन contract प्रोजेक्ट में दिखाई नहीं देता     | verifier URL में गलत project slug।                                                                                                                                 | सही slug के साथ पुनः सत्यापित करें। contract उस प्रोजेक्ट के तहत file किया जाता है जिसकी ओर URL इंगित करता है।                                                                                                                                  |
