# 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](https://github.com/FordefiHQ/api-examples/tree/main/typescript/evm/fordefi-evm-contracts-deployer).

## Install Fordefi JSON-RPC provider and its requirements

- Run `npm install --save-dev @nomicfoundation/hardhat-ethers ethers` to install [Hardhat’s ethers](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-ethers#hardhat-ethers) package.
- Run `npm install --save @fordefi/web3-provider` to install [Fordefi’s provider](https://web3provider-docs.fordefi.com/classes/FordefiWeb3Provider.html).


## Prepare the Hardhat network configuration

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


```typescript
// 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:

```typescript
// 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](https://github.com/FordefiHQ/web3-provider?tab=readme-ov-file#api-reference). 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 `rpcUrl`can be taken from the Hardhat configuration.


```typescript
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`:

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

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


# Example

To deploy the `Lock`contract from Hardhat’s [example](https://hardhat.org/hardhat-runner/docs/guides/project-setup), defined in `contracts/Lock.sol`, you can use the following script. Note that the contract has two runtime values that are passed during deployment.


```typescript
// 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`