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/etherscanto the URL, - replacing the
$TENDERLY_ACCOUNTand$TENDERLY_PROJECTwith 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
When verifying on private or public networks, use appropriate verifier URL. To verify publicly, your URL must end with /public.
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_IDPublic 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/publicQuickstart
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_foundryGet 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 tokenchain: 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 hereFund 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 \
--slowVerifying 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:
- the contract name (
Counter) --rpc-urlwith the RPC URL of the network--etherscan-api-keyand pass the value of your Tenderly API token--private-keyand pass the deployer’s private key- the
--verifyflag --verifier-urlwith 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_URLVerify existing contracts with forge verify-contract
To verify a deployed contract, use forge verify-contract and use the following options:
- The contract address (
$COUNTER_ADDRESS) - The contract name (
Counter) --etherscan-api-keyand pass the value of your Tenderly access token--watchto make the script await the verification status--verifier-urlwith 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 \
--watchVerify 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:
- The fully qualified path to the Solidity class containing the script (
script/Counter.s.sol:CounterScript) --rpc-urlwith the RPC URL of the network--etherscan-api-keyand pass the value of your Tenderly access token- the
--verifyflag --verifier-urlwith 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