Skip to main content

Deploy and Verify Smart Contracts with Hardhat 3

Hardhat is a development environment for compiling, testing, deploying, and verifying EVM smart contracts.

This guide shows how to deploy a contract to Telos with Hardhat 3 and verify it with Sourcify. It uses the current Telos RPC endpoints and the current Hardhat verification plugin. It does not use the legacy hardhat-deploy Sourcify task.

What you will do

  1. Create a Hardhat 3 project.
  2. Configure Telos mainnet and testnet.
  3. Deploy a Greeter contract.
  4. Verify the deployed contract with Sourcify.

Prerequisites

  • Node.js 22 or newer
  • A Telos EVM wallet with TLOS for gas
  • A private key for the network you want to deploy to
caution

Never commit private keys. Store them in .env, add .env to .gitignore, and use a funded testnet wallet while learning.

Create the project

mkdir telos-hardhat
cd telos-hardhat
npm init -y
npm pkg set type=module
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox-mocha-ethers dotenv

Create these folders:

mkdir contracts scripts

Configure Telos networks

Create hardhat.config.ts in the project root:

hardhat.config.ts
import "dotenv/config";
import { defineConfig } from "hardhat/config";
import hardhatToolboxMochaEthers from "@nomicfoundation/hardhat-toolbox-mocha-ethers";

const telosPrivateKey = process.env.TELOS_PRIVATE_KEY;
const telosTestnetPrivateKey = process.env.TELOS_TESTNET_PRIVATE_KEY;

export default defineConfig({
plugins: [hardhatToolboxMochaEthers],
solidity: {
version: "0.8.28",
},
networks: {
telos: {
type: "http",
url: "https://rpc.telos.net",
chainId: 40,
accounts: telosPrivateKey ? [telosPrivateKey] : [],
},
telosTestnet: {
type: "http",
url: "https://rpc.testnet.telos.net",
chainId: 41,
accounts: telosTestnetPrivateKey ? [telosTestnetPrivateKey] : [],
},
},
});

Create .env and add the private key for the network you will use:

.env
TELOS_TESTNET_PRIVATE_KEY=0xYOUR_TESTNET_PRIVATE_KEY
TELOS_PRIVATE_KEY=0xYOUR_MAINNET_PRIVATE_KEY

Add .env to .gitignore:

printf "\n.env\n" >> .gitignore

Add the contract

Create contracts/Greeter.sol:

contracts/Greeter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

contract Greeter {
string private greeting;

constructor(string memory initialGreeting) {
greeting = initialGreeting;
}

function greet() public view returns (string memory) {
return greeting;
}
}

Compile the contract:

npx hardhat compile

Expected result:

Compiled 1 Solidity file with solc 0.8.28

Add the deploy script

Create scripts/deploy.ts:

scripts/deploy.ts
import { network } from "hardhat";

const { ethers } = await network.create();

const greeter = await ethers.deployContract("Greeter", ["Hello, Telos!"]);
await greeter.waitForDeployment();

console.log(`Greeter deployed to ${await greeter.getAddress()}`);

Deploy to Telos testnet

Run the deployment script against Telos testnet:

npx hardhat --network telosTestnet run scripts/deploy.ts

Expected result:

Greeter deployed to 0x...

Save the deployed address. You need it for verification.

To deploy to mainnet instead, use:

npx hardhat --network telos run scripts/deploy.ts

Verify with Sourcify

Verify the testnet deployment:

npx hardhat --network telosTestnet verify sourcify DEPLOYED_CONTRACT_ADDRESS "Hello, Telos!"

Verify the mainnet deployment:

npx hardhat --network telos verify sourcify DEPLOYED_CONTRACT_ADDRESS "Hello, Telos!"

Replace DEPLOYED_CONTRACT_ADDRESS with the address printed by the deployment script.

The constructor arguments passed to verify sourcify must exactly match the constructor arguments used during deployment. In this guide, the constructor argument is "Hello, Telos!".

Check the contract in the explorer

Paste the deployed address into the explorer search bar. After verification is indexed, the contract source and ABI should be visible on the contract page.

Telos network reference

NetworkRPC URLChain IDExplorer
Telos mainnethttps://rpc.telos.net40https://www.teloscan.io/
Telos testnethttps://rpc.testnet.telos.net41https://testnet.teloscan.io/

Troubleshooting

https://testnet.telos.net/evm or https://mainnet.telos.net/evm returns 404

Those are legacy endpoints. Use the current RPC URLs:

  • Mainnet: https://rpc.telos.net
  • Testnet: https://rpc.testnet.telos.net

Hardhat cannot find an account

Check that your .env file exists, the variable name matches the network, and the private key starts with 0x.

  • telosTestnet uses TELOS_TESTNET_PRIVATE_KEY
  • telos uses TELOS_PRIVATE_KEY

Sourcify says the bytecode does not match

Recompile and verify with the same Solidity version and constructor arguments used for deployment. If you changed compiler settings after deploying, restore the deployment settings before verifying.

Verification is accepted but the explorer does not show the source immediately

Wait a few minutes and refresh the contract page. Indexing can lag behind the Sourcify response.