# Deploy EVM Contracts with Foundry

Deploy an EVM smart contract using **Foundry** for compilation and a **TypeScript** script integrating the [Fordefi Web3 Provider](https://github.com/FordefiHQ/web3-provider) for signing transactions with your Fordefi EVM Vault.

The deployment process involves:

- Foundry for contract compilation (`forge build`)
- TypeScript for the deployment script
- Fordefi Web3 Provider for transaction handling
- A Fordefi vault as the signer


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).

## Prerequisites

Ensure the following are installed:

1. Node.js and npm
2. TypeScript:

```sh
npm install -g typescript
```
3. Foundry. ([Installation Guide](https://book.getfoundry.sh/getting-started/installation)).
4. Fordefi API Signer and User:
  - [Learn more about API User](https://docs.fordefi.com/developers/getting-started/create-an-api-user)
  - [Learn more about API Signer](https://docs.fordefi.com/developers/getting-started/set-up-an-api-signer)
  - Private key file (`private.pem`)
  - Fordefi EVM Vault address


## Installation

Install all dependencies:

```sh
npm install --save-dev typescript ts-node @types/node
npm install ethers @fordefi/web3-provider dotenv
```

### Environment variables

Create a `.env` file:

```env
FORDEFI_API_USER_TOKEN=your_token_here
```

Store the Fordefi API Signer private key in `./fordefi_secret/private.pem`.

### TypeScript configuration

Create `tsconfig.json`:

```json
{
  "compilerOptions": {
    "target": "es2020",
    "module": "commonjs",
    "esModuleInterop": true,
    "strict": true,
    "resolveJsonModule": true
  }
}
```

## Deploy the contract

Create `script/deploy.ts`:

```typescript
import fs from "fs";
import path from "path";
import dotenv from "dotenv";
dotenv.config();
import { FordefiWeb3Provider, FordefiProviderConfig } from "@fordefi/web3-provider";
import { ethers } from "ethers";


// 1. Configure your Fordefi secrets
const FORDEFI_API_USER_TOKEN = process.env.FORDEFI_API_USER_TOKEN ?? 
  (() => { throw new Error("FORDEFI_API_USER_TOKEN is not set"); })();
const privateKeyFilePath = "./fordefi_secret/private.pem";
const PEM_PRIVATE_KEY = fs.readFileSync(privateKeyFilePath, "utf8") ??
  (() => { throw new Error("PEM_PRIVATE_KEY is not set"); })();


// 2. Chain ID configuration
//    Example: deploying on Polygon Mainnet (chainId=137)
const chainId = 137;


// 3. Construct FordefiWeb3Provider config
const config: FordefiProviderConfig = {
  chainId,
  address: "0x...", // Your Fordefi EVM Vault address
  apiUserToken: FORDEFI_API_USER_TOKEN,
  apiPayloadSignKey: PEM_PRIVATE_KEY,
  rpcUrl: "https://polygon-rpc.com/" // Fallback RPC
};

async function main() {
  // A) Create the Fordefi provider
  const fordefiProvider = new FordefiWeb3Provider(config);

  // B) Wrap the fordefiProvider with Ethers.js and get the signer
  const provider = new ethers.BrowserProvider(fordefiProvider);
  const signer = await provider.getSigner();

  // C) Load the Foundry artifact from `out/Counter.sol/Counter.json`
  const lockArtifactPath = path.join(__dirname, "..", "out", "Counter.sol", "Counter.json");
  const lockArtifact = JSON.parse(fs.readFileSync(lockArtifactPath, "utf8"));

  // D) Get Foundry bytecode from `artifact.bytecode.object`,
  const abi = lockArtifact.abi;
  let bytecode = lockArtifact.bytecode;
  if (bytecode && bytecode.object) {
    bytecode = bytecode.object;
  }

  // E) Deploy with Ethers
  const factory = new ethers.ContractFactory(abi, bytecode, signer);
  console.log("Deploying contract...");
  const lock = await factory.deploy();

  console.log("Contract deployed to:", await lock.getAddress());
}

main()
  .then(() => process.exit(0))
  .catch((err) => {
    console.error("Error deploying contract:", err);
    process.exit(1);
  });
```

Compile your contract:

```sh
forge build
```

Deploy your contract:

```sh
npx ts-node script/deploy.ts
```

You're done!