Zenpower Contracts - Deployment Guide

Last updated 19 Dec 2025, 15:01

This guide walks you through deploying the Zenpower smart contracts to Sepolia testnet and Ethereum mainnet.

Table of Contents

  1. Prerequisites
  2. Environment Setup
  3. Pre-Deployment Checklist
  4. Sepolia Testnet Deployment
  5. Mainnet Deployment
  6. Post-Deployment Steps
  7. Troubleshooting

Prerequisites

Required Tools

  • Foundry - Install from getfoundry.sh
  • Git - For version control
  • Make - For running deployment commands

Required Accounts

  • Deployer Wallet - Hot wallet with ETH for deployment gas
  • Admin Multisig - For DEFAULT_ADMIN_ROLE (production)
  • Pauser Multisig - For PAUSER_ROLE (production)
  • Signer Wallet - Backend hot wallet for TheForge attestations
  • Etherscan API Key - For contract verification

Required Funds

  • Sepolia Testnet: ~0.1 Sepolia ETH (get from faucet)
  • Mainnet: ~0.5 ETH for deployment gas (estimate, depends on gas prices)

Environment Setup

1. Clone and Setup

cd /opt/zenpower/contracts
cp .env.example .env

2. Configure .env File

Edit .env with your values:

# Deployer private key (NEVER commit this!)
PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE

# For testnet, you can use the same address for all roles
# For mainnet, use proper multisigs
ADMIN_ADDRESS=0xYOUR_ADMIN_ADDRESS
PAUSER_ADDRESS=0xYOUR_PAUSER_ADDRESS
SIGNER_ADDRESS=0xYOUR_SIGNER_ADDRESS

# RPC URLs (get from Alchemy, Infura, etc.)
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY
MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY

# Etherscan API key
ETHERSCAN_API_KEY=YOUR_ETHERSCAN_API_KEY

3. Verify Configuration

make check-env

This should show green checkmarks for all required variables.

Pre-Deployment Checklist

Code Quality

  • All contracts compiled successfully (make build)
  • All tests passing (make test)
  • Code formatted (make fmt)
  • Gas reports reviewed (make test-gas)
  • Contract sizes under limit (make sizes)

Security (Mainnet Only)

  • Security audit completed by reputable firm
  • Audit findings addressed
  • Community review period completed
  • Emergency procedures documented
  • Multisigs tested and operational
  • Backup signers identified

Configuration

  • Environment variables set correctly
  • Deployer wallet has sufficient ETH
  • Admin/Pauser addresses are multisigs (mainnet)
  • Signer wallet secured properly
  • RPC endpoints tested and working

Sepolia Testnet Deployment

Step 1: Verify Environment

# Check environment configuration
make check-env

# Verify your deployer address has Sepolia ETH
cast balance $(cast wallet address $PRIVATE_KEY) --rpc-url $SEPOLIA_RPC_URL

Step 2: Dry Run

# Simulate deployment without broadcasting
make deploy-sepolia-dry

Review the output carefully:

  • Check all addresses
  • Verify constructor arguments
  • Confirm gas estimates are reasonable

Step 3: Deploy to Sepolia

# Deploy with automatic verification
make deploy-sepolia

This will:

  1. Deploy ZenpowerTreasury
  2. Deploy ZENCOIN
  3. Deploy ZenpowerGovernor
  4. Deploy TheForge
  5. Grant MINTER_ROLE to TheForge
  6. Update Treasury roles
  7. Verify all contracts on Etherscan

Step 4: Save Deployed Addresses

Copy the addresses from the output and add them to your .env:

SEPOLIA_TREASURY_ADDRESS=0x...
SEPOLIA_ZENCOIN_ADDRESS=0x...
SEPOLIA_GOVERNOR_ADDRESS=0x...
SEPOLIA_FORGE_ADDRESS=0x...

Step 5: Verify Deployment

# Check all contracts are verified on Etherscan
# Visit the Etherscan links from the deployment output

# Test basic functionality
cast call $SEPOLIA_ZENCOIN_ADDRESS "name()(string)" --rpc-url $SEPOLIA_RPC_URL
cast call $SEPOLIA_ZENCOIN_ADDRESS "symbol()(string)" --rpc-url $SEPOLIA_RPC_URL
cast call $SEPOLIA_ZENCOIN_ADDRESS "totalSupply()(uint256)" --rpc-url $SEPOLIA_RPC_URL

Mainnet Deployment

WARNING: Deploying to mainnet uses real ETH and creates production contracts. Triple-check everything!

Step 1: Final Pre-Deployment Checks

# Run comprehensive checks
make pre-deploy-check

# This runs:
# - make build
# - make test
# - make check-env

All must pass before proceeding.

Step 2: Update Configuration for Production

In your .env, ensure:

# Use production multisigs, NOT hot wallets!
ADMIN_ADDRESS=0xYOUR_PRODUCTION_MULTISIG_ADDRESS
PAUSER_ADDRESS=0xYOUR_ETHICS_BOARD_MULTISIG_ADDRESS
SIGNER_ADDRESS=0xYOUR_BACKEND_SIGNER_ADDRESS

# Use reliable mainnet RPC
MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY

Step 3: Dry Run on Mainnet

# Simulate mainnet deployment
make deploy-mainnet-dry

Review output extremely carefully:

  • Verify all addresses are correct
  • Check gas estimates (multiply by current gas price)
  • Ensure you have enough ETH in deployer wallet

Step 4: Deploy to Mainnet

# Deploy to mainnet (requires confirmation)
make deploy-mainnet

# You will be prompted to type: yes-deploy-mainnet

This will:

  1. Deploy all contracts
  2. Wire them together
  3. Verify on Etherscan
  4. Print deployment summary

DO NOT INTERRUPT THIS PROCESS

Step 5: Save Mainnet Addresses

Copy addresses to .env:

MAINNET_TREASURY_ADDRESS=0x...
MAINNET_ZENCOIN_ADDRESS=0x...
MAINNET_GOVERNOR_ADDRESS=0x...
MAINNET_FORGE_ADDRESS=0x...

IMPORTANT: Backup these addresses securely!

Post-Deployment Steps

1. Verify All Contracts

# Should happen automatically during deployment
# If not, run manually:
make verify-mainnet  # or verify-sepolia

2. Test Contract Functionality

# Check token details
cast call $MAINNET_ZENCOIN_ADDRESS "name()(string)" --rpc-url $MAINNET_RPC_URL
cast call $MAINNET_ZENCOIN_ADDRESS "symbol()(string)" --rpc-url $MAINNET_RPC_URL
cast call $MAINNET_ZENCOIN_ADDRESS "MAX_SUPPLY()(uint256)" --rpc-url $MAINNET_RPC_URL

# Check roles
cast call $MAINNET_ZENCOIN_ADDRESS "hasRole(bytes32,address)(bool)" \
  $(cast keccak "MINTER_ROLE") \
  $MAINNET_FORGE_ADDRESS \
  --rpc-url $MAINNET_RPC_URL

# Check governor configuration
cast call $MAINNET_GOVERNOR_ADDRESS "votingDelay()(uint256)" --rpc-url $MAINNET_RPC_URL
cast call $MAINNET_GOVERNOR_ADDRESS "votingPeriod()(uint256)" --rpc-url $MAINNET_RPC_URL

3. Announce Deployment

Create announcement with:

  • Contract addresses
  • Etherscan links
  • Deployment timestamp
  • Brief description of each contract
  • Links to documentation

4. Update Frontend/Backend

Update your application configuration with new contract addresses:

// Example: apps/api/config/contracts.ts
export const CONTRACTS = {
  ZENCOIN: "0x...",
  FORGE: "0x...",
  GOVERNOR: "0x...",
  TREASURY: "0x...",
};

5. Monitor Contracts

Set up monitoring for:

  • Total supply changes
  • Forge operations
  • Governance proposals
  • Role changes
  • Emergency pauses

Troubleshooting

Issue: "PRIVATE_KEY not set in .env"

Solution:

cp .env.example .env
# Edit .env and add your private key

Issue: "Insufficient funds for deployment"

Solution:

# Check your balance
cast balance $(cast wallet address $PRIVATE_KEY) --rpc-url $RPC_URL

# For Sepolia: Get testnet ETH from faucet
# For Mainnet: Add more ETH to deployer wallet

Issue: "Transaction underpriced"

Solution:

# Check current gas prices
cast gas-price --rpc-url $MAINNET_RPC_URL

# Add to .env:
export GAS_PRICE_GWEI=50  # Adjust based on network conditions

Issue: "Contract verification failed"

Solution:

# Verify manually
forge verify-contract <ADDRESS> <CONTRACT_NAME> \
  --constructor-args $(cast abi-encode "constructor(...)" ...) \
  --chain <sepolia|mainnet> \
  --etherscan-api-key $ETHERSCAN_API_KEY \
  --watch

Issue: "Nonce too low"

Solution:

# Reset nonce (be careful!)
# This usually happens if a transaction was stuck
# Cancel the stuck transaction in MetaMask or similar

Issue: Deployment script fails mid-way

Solution:

  1. DO NOT re-run the full script - it will fail on already deployed contracts
  2. Note which contracts were successfully deployed
  3. Comment out successful deployments in the script
  4. Re-run to complete remaining deployments
  5. Or: Deploy remaining contracts manually using forge create

Getting Help

If you encounter issues:

  1. Check Foundry documentation: https://book.getfoundry.sh
  2. Review deployment logs carefully
  3. Ask in Zenpower Discord: discord.gg/zenpower
  4. Create issue: https://github.com/zenpower-community/zenpower/issues

Security Reminders

  • NEVER commit .env file to git
  • NEVER share private keys with anyone
  • Use hardware wallets for production multisigs
  • Test thoroughly on testnet first
  • Have an emergency plan ready
  • Monitor contracts continuously after deployment

Good luck with your deployment!

"What if being kind was the optimal strategy?"