Deploying EVM Contracts with Foundry
Deploy an EVM smart contract using Foundry for compilation and a TypeScript script integrating the Fordefi 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
Prerequisites
Ensure the following are installed:
- Node.js and npm
- TypeScript:
npm install -g typescript
- Foundry. (Installation Guide).
- Fordefi API Signer and User:
- Learn more about API User
- Learn more about API Signer
- Private key file (
private.pem
) - Fordefi EVM Vault address
Installation
Install all dependencies:
npm install --save-dev typescript ts-node @types/node
npm install ethers @fordefi/web3-provider dotenv
Environment variables
Create a .env
file:
FORDEFI_API_USER_TOKEN=your_token_here
Store the Fordefi API Signer private key in ./fordefi_secret/private.pem
.
TypeScript configuration
Create tsconfig.json
:
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"strict": true,
"resolveJsonModule": true
}
}
Deploy the contract
Create script/deploy.ts
:
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:
forge build
Deploy your contract:
npx ts-node script/deploy.ts
You're done!