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

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

आपको अपने Tenderly account और project slugs, एक Tenderly access key (Dashboard → Account Settings → Authorization), और लक्ष्य नेटवर्क पर एक funded account चाहिए। Tenderly का verifier उस metadata hash की तुलना करता है जिसे Solidity compiler deploy किए गए bytecode में जोड़ता है, आपके द्वारा सबमिट किए गए source के साथ। compile किए गए output में metadata रखें, और compiler settings को pin करें ताकि वे deploy समय और verify समय के बीच drift न हों:
foundry.toml
[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 सेट अप करें:
.env
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 लेता है:
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। 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 के अंतर्गत दिखाई देते हैं।
showLineNumbers
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 करता है जब तक सत्यापन समाप्त नहीं हो जाता और परिणाम प्रिंट करता है।
Foundry का output सफलता पर एक URL: https://etherscan.io/address/... line प्रिंट करता है। यह Etherscan-compatible flow का display quirk है; contract Tenderly पर सत्यापित हुआ था, Etherscan पर नहीं। Dashboard में Contracts के अंतर्गत पुष्टि करें।

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

verifier URL को /public-suffixed variant के लिए बदलें; और कुछ नहीं बदलता। सत्यापित source page link वाले किसी भी व्यक्ति द्वारा, बिना Tenderly login के, पहुँच योग्य हो जाता है।
showLineNumbers
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
सार्वजनिक सत्यापन अपरिवर्तनीय है। सार्वजनिक रूप से सत्यापित contract सार्वजनिक रहता है। निजी और सार्वजनिक सत्यापन स्वतंत्र records हैं: किसी निजी रूप से सत्यापित contract को सार्वजनिक बनाने के लिए, इसे /public URL के विरुद्ध पुनः सत्यापित करें।

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

forge create और forge script समान flags को inline स्वीकार करते हैं, इसलिए deployment और verification एक command के रूप में चलते हैं। forge verify-contract के विपरीत, दोनों constructor arguments को raw values के रूप में लेते हैं और आपके लिए उन्हें ABI-encode करते हैं:
showLineNumbers
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
--constructor-args को अंत में रखें। यह लालच से command line के बाकी हिस्से का उपभोग कर लेता है, इसलिए इसके बाद रखे गए किसी भी flag को एक और constructor argument के रूप में माना जाता है।
Multi-contract deployments के लिए, --slow के साथ forge script का उपयोग करें; script द्वारा deploy किया गया प्रत्येक contract स्वचालित रूप से broadcast log से लिए गए अपने constructor arguments के साथ सत्यापित हो जाता है। --slow के बिना, broadcast batching पिछले transaction की पुष्टि होने से पहले एक transaction सबमिट कर सकती है, जो verification चरण को race कर सकती है:
showLineNumbers
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 के साथ सत्यापित source को स्थानीय रूप से clone करें और इसे Tenderly के API के माध्यम से पुनः सत्यापित करें:
showLineNumbers
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 के विरुद्ध सत्यापित करें:
showLineNumbers
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 अनुभाग के तहत:
showLineNumbers
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 इसके साथ विफल हो जाता है:
Error: Failed to get standard json input
- cannot resolve file at "lib/openzeppelin-contracts-upgradeable/lib/..."
एक-line वाला src/Imports.sol बनाएँ जो contract को import करता है, फिर पुनः build करें:
src/Imports.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
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 से पुनर्निर्मित किया जा सकता है:
showLineNumbers
# 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 उत्पन्न करें और TENDERLY_ACCESS_KEY पुनः सेट करें।
not foundverifier 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 contentverifier ने एक 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 --forceContracts जो 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 इंगित करता है।