Virtual TestNets are live! ⚡️ Test and stage dapps on real-time production data.  Schedule Office Hours
Contract Verification
Foundry Verification

Foundry Contract Verification

Foundry is a smart contract development toolchain. Foundry’s command line tool Forge tests, builds, and deploys smart contracts.

Tenderly can verify smart contracts deployed with Foundry’s commands forge create, forge script or forge verify-contract. You can even use Tenderly’s development infrastructure and tools in conjunction with Foundry tooling.

Use the --slow flag when running Foundry scripts to prevent transaction batching. With this, a transaction is sent only after it’s preceding transaction is confirmed.

Verification URL

All Foundry commands that support verification require the --verification-url argument. You need to give it an Etherscan-compliant URL.

In this section you can find formats for verifier URLs on:

  • Forks
  • DevNets
  • TestNets
  • Public networks (mainnets and testnets)

Verification on Tenderly development infrastructure

Tenderly development, staging, and testing infrastructure - Forks, DevNets, and TestNets, expose an RPC URL for access. You get the Etherscan-compliant verification URL by:

  • adding /verify/etherscan to the URL,
  • replacing the $TENDERLY_ACCOUNT and $TENDERLY_PROJECT with the settings from your account. Follow this guide,
  • adhering to the following formats, depending on the technology you’re using:
## For TestNets
VERIFIER_URL=$TENDERLY_VIRTUAL_TESTNET_RPC/verify/etherscan
 
## For DevNets
VERIFIER_URL=https://api.tenderly.co/api/v1/account/$TENDERLY_ACCOUNT/project/$TENDERLY_PROJECT/etherscan/verify/devnet/<resourceId>
 
## For Forks
VERIFIER_URL=https://api.tenderly.co/api/v1/account/$TENDERLY_ACCOUNT/project/$TENDERLY_PROJECT/etherscan/verify/fork/<resourceId>

Examples:

## TestNets
https://virtual.base.rpc.tenderly.co/872ac073-1de1-4422-b01d-8d057781d77d/verify/etherscan
 
## For DevNets
## https://rpc.vnet.tenderly.co/devnet/test/c6a552cd-3064-4e95-9fb3-8cee2e317296/
 
https://api.tenderly.co/api/v1/account/$TENDERLY_ACCOUNT/project/$TENDERLY_PROJECT/etherscan/verify/devnet/c6a552cd-3064-4e95-9fb3-8cee2e317296/
 
## Forks
## Fork RPC: https://rpc.tenderly.co/fork/68cc4cd5-2a3b-441a-afbb-4dea745a22c2
https://api.tenderly.co/api/v1/account/$TENDERLY_ACCOUNT/project/$TENDERLY_PROJECT/etherscan/verify/fork/68cc4cd5-2a3b-441a-afbb-4dea745a22c2
 

Verification on public networks

Private verification mode on public mainnets/testnets. The verification URL has the following structure:

 
https://api.tenderly.co/api/v1/account/$TENDERLY_ACCOUNT/project/$TENDERLY_PROJECT/etherscan/verify/network/$NETWORK_ID

Public verification mode on public mainnets/testnets. The verification URL has the following structure:

 
https://api.tenderly.co/api/v1/account/$TENDERLY_ACCOUNT/project/$TENDERLY_PROJECT/etherscan/verify/network/$NETWORK_ID/public

Quickstart

In this quickstart, we’ll deploy and verify a smart contract on Tenderly TestNets. We’ll use a publicly available demo TestNet for this purpose.

Create a new Foundry project

forge init hello_foundry

Get your access key

To authenticate with Tenderly, generate an access key in the Dashboard. Follow this guide to learn how.

If you have the Tenderly CLI set up, you can also get the key from:

cat ~/.tenderly/config.yaml | grep access_key:

Extend foundry.toml

For verification to succeed, it’s necessary to configure cbor_metadata=true in foundry.toml.

Extend foundry.toml file to include the unknown_chain entry:

  • key: The Tenderly access token
  • chain: The chain ID in case you decided to follow the good practice of setting an independent chain ID when forking a network.
  • url: The TestNet RPC as the verification URL
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
cbor_metadata = true
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
 
[etherscan]
#                   Paste TENDERLY_ACCESS_TOKEN            Chain ID         Verifier URL: RPC_URL/verify/etherscan
unknown_chain = { key = "${TENDERLY_ACCESS_KEY}", chain = 84537357, url = "${TENDERLY_VIRTUAL_TESTNET_RPC_URL}/verify/etherscan" }

Set up environment variables

Set up the following environment variables that hold:

  • RPC URL
  • Tenderly Verifier URL according to these formats
  • Tenderly Access Token
TENDERLY_VIRTUAL_TESTNET_RPC_URL=... # Virtual TestNet RPC URL
TENDERLY_VERIFIER_URL=$TENDERLY_VIRTUAL_TESTNET_RPC_URL/verify/etherscan
 
TENDERLY_ACCESS_TOKEN= # paste your access key here

Fund your account

Use the TestNet’s unlimited faucet to set a new balance for any account on the network.

The following command funds 0xE58b9ee93700A616b50509C8292977FA7a0f8ce1 that we’ll use throughout this example. Replace it with

curl $RPC_URL \
-X POST \
-H "Content-Type: application/json" \
-d '{
    "jsonrpc": "2.0",
    "method": "tenderly_setBalance",
    "params": [["0xE58b9ee93700A616b50509C8292977FA7a0f8ce1"], "0xDE0B6B3A7640000"],
    "id": "1234"
}'

Deploy and verify the contract

Finally, deploy the contract using forge create.

# Demo private key for address 0xE58b9ee93700A616b50509C8292977FA7a0f8ce1
# Make sure to use the correct private key if using a different account.
# Make sure your funded the account using tenderly_setBalance
PRIVATE_KEY=bd3a24f40aa009e82b67af2ce17c9e2c794f1958d802c9481bc551ef76e8f03f
 
forge create Counter \
--rpc-url $RPC_URL \
--etherscan-api-key $TENDERLY_ACCESS_TOKEN \
--private-key $PRIVATE_KEY  \
--verify \
--verifier-url $TENDERLY_VERIFIER_URL \
--slow

Verifying with Foundry

In this section, you’ll find examples of how to run Foundry commands with Tenderly verification included.

💡

Check if you’ve set up your foundry.toml file for verification on Tenderly infrastructure.

Deploy and verify contracts with forge create

Verify your smart contract alongside the deployment with forge create, and use the following options:

  1. the contract name (Counter)
  2. --rpc-url with the RPC URL of the network
  3. --etherscan-api-key and pass the value of your Tenderly API token
  4. --private-key and pass the deployer’s private key
  5. the --verify flag
  6. --verifier-url with the verification URL ($TENDERLY_VERIFIER_URL). Learn about the Verification URL.
forge create Counter \
    --rpc-url $RPC_URL\
    --etherscan-api-key $TENDERLY_ACCESS_TOKEN \
    --private-key $PRIVATE_KEY  \
    --verify \
    --verifier-url $TENDERLY_VERIFIER_URL

Verify existing contracts with forge verify-contract

To verify a deployed contract, use forge verify-contract and use the following options:

  1. The contract address ($COUNTER_ADDRESS)
  2. The contract name (Counter)
  3. --etherscan-api-key and pass the value of your Tenderly access token
  4. --watch to make the script await the verification status
  5. --verifier-url with the verification URL ($TENDERLY_VERIFIER_URL). Learn about the Verification URL.
COUNTER_ADDRESS=0x...
 
forge verify-contract $COUNTER_ADDRESS  \
Counter \
--etherscan-api-key $TENDERLY_ACCESS_TOKEN \
--verifier-url $TENDERLY_VERIFIER_URL \
--watch

Verify contracts from Foundry scripts with forge script

When your Foundry scripts include contract deployments, you can opt-in to get them verified when you run the script.

Use the following options to forge script:

  1. The fully qualified path to the Solidity class containing the script (script/Counter.s.sol:CounterScript)
  2. --rpc-url with the RPC URL of the network
  3. --etherscan-api-key and pass the value of your Tenderly access token
  4. the --verify flag
  5. --verifier-url with the verification URL ($TENDERLY_VERIFIER_URL) in one of these formats.

Before running the script, modify script/Counter.s.sol so it deploys the Counter contract:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
 
import "forge-std/Script.sol";
import "../src/Counter.sol";
 
contract CounterScript is Script {
    function run() public {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);
 
        Counter counter = new Counter();
 
        vm.stopBroadcast();
    }
}

Then, run the following script. Verification will automatically pick up any contract deployed in script execution.

Use the --slow flag when running Foundry scripts to prevent transaction batching. With this, a transaction is sent only after it’s preceding transaction is confirmed.

# Demo private key for address 0xE58b9ee93700A616b50509C8292977FA7a0f8ce1
# Make sure to use the correct private key if using a different account
# Make sure your funded the account using tenderly_setBalance
PRIVATE_KEY=bd3a24f40aa009e82b67af2ce17c9e2c794f1958d802c9481bc551ef76e8f03f
 
forge script script/Counter.s.sol:CounterScript \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY  \
--etherscan-api-key $TENDERLY_ACCESS_TOKEN \
--broadcast \
--verify \
--verifier-url $TENDERLY_VERIFIER_URL \
--slow