Deploy EVM Contracts with Hardhat

The following assumes you are using a Hardhat project configured as “TypeScript project (with Viem)”. Other types of projects might require minor modifications.

You can also find this tutorial in our API Examples repository on Github.

Install Fordefi JSON-RPC provider and its requirements

Prepare the Hardhat network configuration

Make sure your hardhat configuration hardhat.config.ts contains the network's URL and chain id as follows:

// hardhat.config.js
const config: HardhatUserConfig = {
  solidity: "0.8.24", // Other configurations..
  networks: {
    polygon: { 
      url: "https://polygon.llamarpc.com", // JSON-RPC URL
      chainId: 137, // Decimal value of the chain id
    }
  }
};

export default config;

Use the Fordefi Web3 provider as a signer in your deployment script

  1. In your deployment script, include the necessary dependencies:

    // scripts/deploy.ts
    import hre from "hardhat";
    import "@nomicfoundation/hardhat-ethers";
    import { HttpNetworkUserConfig } from "hardhat/types";
    import { EvmChainId, FordefiWeb3Provider } from "@fordefi/web3-provider";
  2. Create a Fordefi Web3 Provider. Make sure to correct set the parameter values, as described here. Specifically,

    • address should be the address of your Fordefi EVM vault used for deploying the contract
    • apiUserToken is the access token of your API User
    • apiPayloadSignKey should be set to the private key of your API User (this is the content of the pem file you have generated; make sure to set the private key as a single-line base64 string without any spaces).
    • chainId and rpcUrlcan be taken from the Hardhat configuration.

    const networkConfig = hre.network.config as HttpNetworkUserConfig;
    const fordefiProvider = new FordefiWeb3Provider({
      address: "<fordefi-vault-address>",
      apiUserToken: "<api-user-access-token>",
      apiPayloadSignKey: "<api-user-private-key.pem-file-contents>",
      chainId: networkConfig.chainId as EvmChainId,
      rpcUrl: networkConfig.url,
    });
    
  3. Create an ethers.Signer:

    const provider = new hre.ethers.BrowserProvider(fordefiProvider);
    const signer = await provider.getSigner();
  4. Use the ethers.Signer as a parameter to getContractFactory

    const factory = await hre.ethers.getContractFactory("<your-contract-name>", signer);
    const contract = await factory.deploy(/* any params */);

Example

To deploy the Lockcontract from Hardhat’s example, defined in contracts/Lock.sol, you can use the following script. Note that the contract has two runtime values that are passed during deployment.

// scripts/deploy.ts
import { parseEther } from "viem";
import hre from "hardhat";
import "@nomicfoundation/hardhat-ethers";
import { HttpNetworkUserConfig } from "hardhat/types";
import { EvmChainId, FordefiWeb3Provider } from "@fordefi/web3-provider";

// Some vars...
const JAN_1ST_2030 = 1893456000;
const ONE_GWEI: bigint = parseEther("0.001");

async function main() {
    const networkConfig = hre.network.config as HttpNetworkUserConfig;
    const fordefiProvider = new FordefiWeb3Provider({
      address: "<fordefi-vault-address>",
      apiUserToken: "<api-user-access-token>",
      apiPayloadSignKey: "<api-user-private-key.pem-file-contents>",
      chainId: networkConfig.chainId as EvmChainId,
      rpcUrl: networkConfig.url,
    });
    const provider = new hre.ethers.BrowserProvider(fordefiProvider);
    const signer = await provider.getSigner();
    const factory = await hre.ethers.getContractFactory("Lock", signer);
    console.log('Deploying Lock...');
    // Deploy contract with values. 
    const lock = await factory.deploy(JAN_1ST_2030, { value: ONE_GWEI });
    await lock.waitForDeployment();
    console.log('Lock deployed to:', await lock.getAddress());
}

main()
    .then(() => process.exit(0))
    .catch(error => {
        console.error(error);
        process.exit(1);
    });

Run the deployment script: npx hardhat run --network polygon scripts/deploy.ts