Skip to main content
Works on: Virtual Environments and public networks (mainnets and testnets). The same plugin handles both; point it at the right network in hardhat.config.ts.
This guide will walk you through proxy contract verification using @tenderly/hardhat-tenderly.

Requirements

Automatic proxy verification works out of the box on @tenderly/hardhat-tenderly:
  • >= 1.10.0 (Ethers 5 line)
  • >= 2.1.0 (Ethers 6 line)
It only works when you deploy proxies with @openzeppelin/hardhat-upgrades. Hardhat Ignition is not supported for proxy verification yet. If you’re on a lower plugin version and can’t upgrade, use the manual workaround below.

Automatic verification

The plugin verifies three proxy patterns: TransparentUpgradeableProxy, UUPSUpgradeableProxy, and BeaconProxy.

Workaround for lower versions

When using @tenderly/hardhat-tenderly at versions < 1.10.0 and < 2.1.0, this workaround will enable automatic verification. You need to verify the following:
  • The proxy contract (e.g. OpenZeppelin’s proxies)
  • Implementation behind the proxy
  • Any dependencies the implementation has
  • New implementation instances deployed with upgrades
The verification process varies depending on the proxy contract type and the implementation.

Overview

In this guide, we’ll use an example Hardhat project and the @tenderly/hardhat-tenderly plugin to demonstrate the verification of OpenZeppelin’s UUPSUpgradeable, TransparentUpgradeableProxy, and BeaconProxy alternatives.
Proxy contracts need to be verified manually. Turn off automatic verification like so:
example.ts
To obtain the address of the deployed implementation, use the @openzeppelin/upgrades-core package and getImplementationAddress function. Verifying the proxy implementation is usually straightforward; verify it just like any other contract.
example.ts
To verify the proxy instance, you need to complete these two preliminary steps:
  1. Load the exact smart contract of the proxy depending on the type of proxy you’re using, so it gets compiled. You’ll need to import the proxy contracts through the compiler by creating a dummy .sol file.
  2. Modify hardhat.config.ts to specify the settings OpenZepplin contracts were compiled with.
Once these steps are completed, you can proceed to verify the proxy just as you would any other contract.
example.ts

Verify by proxy type

These code samples show how to verify the implementation and the proxy for OpenZeppelin’s three proxy patterns. The examples use a proxied Vault contract that references an ERC-20 token (TToken).

UUPS proxy

To verify the UUPS proxy and the underlying information, call the hardhat-tenderly plugin twice:
  1. To verify the implementation, you need to provide the following:
  • name of your proxied contract (in our case Vault)
  • Address where the contract was deployed using the getImplementationAddress method from @openzeppelin/upgrades-core.
  1. To verify the proxy, provide the following:
  • ERC1967Proxy as the proxy contract name
  • Address of the proxy proxy.address
example.ts

Complete Code Sample

Here’s a complete Hardhat test that does the following:
  • Deploys the TToken (needed for the vault)
  • Deploys Vault as a proxy, initialized with the TToken contract
  • Verifies the proxy (ERC1967Proxy) instance deployed at await proxy.getAddress()
  • Verifies the implementation instance Vault, deployed at getImplementationAddress(ethers.provider, await proxy.getAddress())
  • Upgrades the proxy to VaultV2
example.ts

Transparent proxy

To verify the UUPS proxy and the underlying information, call hardhat-tenderly while passing two contracts: Vault for the implementation, and TransparentUpgradeableProxy for the proxy itself.
example.ts
  1. To verify the implementation, provide the following:
  • name of your proxied contract (in our case Vault)
  • Address where the contract was deployed, using the getImplementationAddress method from @openzeppelin/upgrades-core.
  1. To verify the proxy, provide the following:
  • TransparentUpgradeableProxy as the proxy contract name
  • Address of the proxy await proxy.getAddress()

Complete Code Sample

example.ts

Beacon proxy

To verify the Beacon proxy and the underlying information, you have to verify two contracts: the Vault (implementation) and OpenZepplin’s UpgradableBeacon:
example.ts

Complete Code Sample

example.ts