Skip to main content
This guide covers deploying the Agora DAO contracts using Hardhat on various networks.

Prerequisites

Before deploying, ensure you have:
  1. Node.js and Yarn installed
  2. A funded wallet for deployment
  3. RPC provider access (Alchemy, Infura, etc.)
  4. Etherscan API key for verification (optional)

Quick start

1

Generate a deployment account

cd packages/hardhat
yarn account:generate
This creates an encrypted private key and stores it in .env
2

Fund your deployment account

yarn account
This displays your address and balance on all configured networks
3

Deploy to a network

yarn deploy --network sepolia
Deploys contracts to Sepolia testnet
4

Verify contracts (optional)

yarn verify --network sepolia
Verifies source code on Etherscan

Available commands

From packages/hardhat/package.json:
Key deployment commands
{
  "scripts": {
    "deploy": "ts-node scripts/runHardhatDeployWithPK.ts",
    "compile": "hardhat compile",
    "verify": "hardhat etherscan-verify",
    "hardhat-verify": "hardhat verify",
    "test": "REPORT_GAS=true hardhat test --network hardhat",
    "clean": "hardhat clean"
  }
}
Compiles all Solidity contracts in contracts/ directory.
yarn compile
Output: Artifacts in artifacts/ and type definitions in typechain-types/
Runs deployment scripts in deploy/ directory in order.
# Deploy to local Hardhat network
yarn deploy

# Deploy to specific network
yarn deploy --network sepolia
yarn deploy --network base
yarn deploy --network polygonAmoy
Scripts are executed in alphabetical order:
  1. 00_deploy_agora_factory.ts
  2. 01_deploy_agora_dao.ts
Verifies deployed contracts on Etherscan-compatible explorers.
yarn verify --network sepolia
Requires ETHERSCAN_V2_API_KEY in .env
Runs test suite with gas reporting.
yarn test
Tests are located in test/ directory

Network configuration

Supported networks from hardhat.config.ts:48-129:

Mainnet networks

Ethereum

yarn deploy --network mainnet

Arbitrum

yarn deploy --network arbitrum

Optimism

yarn deploy --network optimism

Polygon

yarn deploy --network polygon

Base

yarn deploy --network base

Scroll

yarn deploy --network scroll

Celo

yarn deploy --network celo

Gnosis

yarn deploy --network gnosis

Testnet networks

Sepolia

yarn deploy --network sepolia

Arbitrum Sepolia

yarn deploy --network arbitrumSepolia

Optimism Sepolia

yarn deploy --network optimismSepolia

Polygon Amoy

yarn deploy --network polygonAmoy

Base Sepolia

yarn deploy --network baseSepolia

Scroll Sepolia

yarn deploy --network scrollSepolia

Network configuration details

All networks use Alchemy RPC endpoints (except Gnosis, Chiado, Base, and Celo which use public RPCs):
From hardhat.config.ts:61-64
sepolia: {
  url: `https://eth-sepolia.g.alchemy.com/v2/${providerApiKey}`,
  accounts: [deployerPrivateKey],
}
Set your Alchemy API key in .env:
ALCHEMY_API_KEY=your_api_key_here

Constructor parameters

AgoraDaoFactory

The factory contract requires one parameter: the initial owner address.
From AgoraDaoFactory.sol:43
constructor(address initialOwner) Ownable(initialOwner) {
    daoCategories.push("SERVICE");
    daoCategories.push("GOVERNANCE");
    daoCategories.push("SOCIAL IMPACT");
    daoCategories.push("ENERGY");
}
Deployment script (deploy/00_deploy_agora_factory.ts:25-34):
await deploy("AgoraDaoFactory", {
  from: deployer,
  args: [deployer],  // Sets deployer as initial owner
  log: true,
  autoMine: true,
});
The deployer address is automatically used as the initial owner. This can be changed to a multisig or DAO governance address.

AgoraDao

Individual DAO contracts require two parameters:
From AgoraDao.sol:27-32
constructor(address _fabric, address _creator) {
    fabric = _fabric;                           // Parent factory address
    _grantRole(DEFAULT_ADMIN_ROLE, _creator);  // Grant admin to creator
    userCounter++;
}
Deployment script (deploy/01_deploy_agora_dao.ts:25-34):
await deploy("AgoraDao", {
  from: deployer,
  args: [
    "0x486dd25072a665db79330b1DEDc4Bac473148019",  // Factory address
    "0x486dd25072a665db79330b1DEDc4Bac473148019"   // Creator address
  ],
  log: true,
  autoMine: true,
});
In production, individual DAOs are created via AgoraDaoFactory.createDao(), not directly deployed. The deployment script above is for testing purposes only.

Deployment scripts

Deployment scripts are located in packages/hardhat/deploy/ and use Hardhat Deploy.

Factory deployment

File: deploy/00_deploy_agora_factory.ts
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

const deployAgoraDaoFactory: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
  const { deployer } = await hre.getNamedAccounts();
  const { deploy } = hre.deployments;

  await deploy("AgoraDaoFactory", {
    from: deployer,
    args: [deployer],  // initialOwner
    log: true,
    autoMine: true,
  });
};

export default deployAgoraDaoFactory;
deployAgoraDaoFactory.tags = ["AgoraDaoFactory"];
Usage:
# Deploy only the factory
yarn deploy --tags AgoraDaoFactory --network sepolia

Custom deployment script

To deploy with custom parameters:
deploy/00_deploy_agora_factory.ts
await deploy("AgoraDaoFactory", {
  from: deployer,
  args: [
    "0xYourMultisigAddress"  // Use multisig as owner
  ],
  log: true,
  autoMine: true,
});

Verification process

After deployment, verify your contracts on block explorers:

Automatic verification

yarn verify --network sepolia
This runs hardhat-deploy’s built-in verification using configuration from hardhat.config.ts:135-139:
verify: {
  etherscan: {
    apiKey: `${etherscanApiKey}`,
  },
}

Manual verification

For manual verification or troubleshooting:
yarn hardhat-verify --network sepolia \
  --contract contracts/AgoraDaoFactory.sol:AgoraDaoFactory \
  DEPLOYED_ADDRESS \
  CONSTRUCTOR_ARGS
Example:
yarn hardhat-verify --network sepolia \
  --contract contracts/AgoraDaoFactory.sol:AgoraDaoFactory \
  0x1234567890123456789012345678901234567890 \
  0xDeployerAddress

Etherscan API key

Set in .env:
ETHERSCAN_V2_API_KEY=your_api_key_here
Get API keys from:

Production deployment example

Complete deployment flow for production:
1

Import your deployment wallet

yarn account:import
Enter your private key when prompted (stored encrypted)
2

Configure environment

Edit .env:
ALCHEMY_API_KEY=your_alchemy_key
ETHERSCAN_V2_API_KEY=your_etherscan_key
3

Verify account balance

yarn account
Ensure sufficient balance on target network
4

Compile contracts

yarn compile
Verify successful compilation
5

Run tests

yarn test
Ensure all tests pass
6

Deploy to testnet first

yarn deploy --network sepolia
Test on testnet before mainnet
7

Verify on testnet

yarn verify --network sepolia
8

Deploy to mainnet

yarn deploy --network mainnet
Double-check network before confirming
9

Verify on mainnet

yarn verify --network mainnet
10

Transfer ownership (optional)

Transfer factory ownership to multisig or DAO governance

Post-deployment configuration

After deployment, you may want to:

Add custom DAO categories

// Only factory owner can add categories
agoraDaoFactory.addDaoCategory("DEFI");
agoraDaoFactory.addDaoCategory("NFT");

Transfer ownership

// Transfer to multisig or governance contract
agoraDaoFactory.transferOwnership(multisigAddress);

Create initial DAOs

agoraDaoFactory.createDao(
  "Example DAO",
  "A description of the DAO",
  0,  // categoryID (0 = SERVICE)
  "ipfs://QmImageHash"
);

Troubleshooting

Error: sender doesn't have enough funds to send txSolution: Fund your deployment account:
yarn account  # Get your address
Send ETH to the displayed address on your target network.
Error: nonce has already been usedSolution: Reset your local deployment state:
yarn clean
rm -rf deployments/[network_name]
Error: already verified or does not matchSolution: Ensure constructor args match exactly:
yarn hardhat-verify --network sepolia \
  --contract contracts/AgoraDaoFactory.sol:AgoraDaoFactory \
  ADDRESS \
  CORRECT_ARGS
Error: request failed or timeoutSolution: Check RPC endpoint:
  • Verify Alchemy API key in .env
  • Try alternative RPC (Infura, QuickNode)
  • Check network status

Gas optimization

The contracts are compiled with optimizer settings from hardhat.config.ts:31-36:
optimizer: {
  enabled: true,
  runs: 200,
}
Runs: 200 balances deployment cost vs runtime cost:
  • Lower runs (100) = cheaper deployment, higher execution cost
  • Higher runs (1000) = expensive deployment, cheaper execution
  • 200 is a good balance for most use cases
To view gas costs during testing:
REPORT_GAS=true yarn test

Next steps

Architecture

Understand contract structure and relationships

Overview

Return to smart contracts overview

Build docs developers (and LLMs) love