Deploying Smart Contracts to Polygon
Polygon PoS is not a separate L1, but a sidechain with its own validators that uses Ethereum as a checkpoint layer. From a developer's perspective: full EVM compatibility, MATIC as gas token, block time around 2 seconds, gas 10-100 times cheaper than Ethereum mainnet. Deploying a contract written for Ethereum to Polygon takes minutes.
Deployment Preparation
Network Configuration
Polygon has two public RPCs:
- Official:
https://polygon-rpc.com(often overloaded) - Recommended: Alchemy/Infura/QuickNode endpoints (more reliable)
In hardhat.config.ts:
import { HardhatUserConfig } from "hardhat/config"
const config: HardhatUserConfig = {
networks: {
polygon: {
url: process.env.POLYGON_RPC_URL || "https://polygon-rpc.com",
accounts: [process.env.DEPLOYER_PRIVATE_KEY!],
gasPrice: "auto", // or fixed value in gwei
chainId: 137
},
amoy: { // Polygon testnet (replaced Mumbai in 2024)
url: "https://rpc-amoy.polygon.technology",
accounts: [process.env.DEPLOYER_PRIVATE_KEY!],
chainId: 80002
}
},
etherscan: {
apiKey: {
polygon: process.env.POLYGONSCAN_API_KEY!,
polygonAmoy: process.env.POLYGONSCAN_API_KEY!
},
customChains: [
{
network: "polygonAmoy",
chainId: 80002,
urls: {
apiURL: "https://api-amoy.polygonscan.com/api",
browserURL: "https://amoy.polygonscan.com"
}
}
]
}
}
Important: Mumbai testnet was deprecated in April 2024. Use Amoy (chainId: 80002).
MATIC for Gas
For Amoy: free faucet at faucet.polygon.technology. For mainnet: bridge via Polygon Bridge (from Ethereum) or buy MATIC on exchange and withdraw directly to Polygon network.
Deployment
# Deploy to testnet
npx hardhat run scripts/deploy.ts --network amoy
# Verification on PolygonScan
npx hardhat verify --network amoy DEPLOYED_ADDRESS "constructor_arg1" "constructor_arg2"
# Deploy to mainnet
npx hardhat run scripts/deploy.ts --network polygon
npx hardhat verify --network polygon DEPLOYED_ADDRESS
Deploy script with address saving:
import { ethers } from "hardhat"
import fs from "fs"
async function main() {
const [deployer] = await ethers.getSigners()
console.log("Deploying with:", deployer.address)
console.log("MATIC balance:", ethers.formatEther(await deployer.provider.getBalance(deployer.address)))
const Contract = await ethers.getContractFactory("MyContract")
const contract = await Contract.deploy(/* constructor args */)
await contract.waitForDeployment()
const address = await contract.getAddress()
console.log("Deployed to:", address)
// Save address
const deployments = { polygon: { MyContract: address, deployedAt: new Date().toISOString() } }
fs.writeFileSync("deployments.json", JSON.stringify(deployments, null, 2))
}
main().catch(console.error)
Gas Price on Polygon
Polygon uses EIP-1559 with base fee. It is recommended not to set too low maxPriorityFeePerGas — otherwise transaction gets stuck in mempool:
// Get current gas settings
const feeData = await provider.getFeeData()
// maxFeePerGas = baseFee * 2 + maxPriorityFeePerGas (automatically via "auto")
Minimum baseFee on Polygon — 30 gwei (after EIP-1559 upgrade). During network congestion may rise to 300-500 gwei — but in MATIC it is still pennies relative to Ethereum.
Polygon zkEVM
If stronger binding to Ethereum security model is needed — Polygon zkEVM (chainId: 1101) provides validity proofs on L1. Full EVM equivalence (Type 2 zkEVM). Same tools, different RPCs and chainId. Deployment is similar but gas is 3-10 times cheaper than Ethereum mainnet.
Verification and Deployment Security
After deployment mandatory:
- Source code verification on PolygonScan — users and integrations can see ABI and source
- Check constructor: passed arguments match expected ones
- Smoke test basic functions via PolygonScan Read/Write Contract or hardhat task
Timeline
Deploying a ready contract to Polygon Amoy + verification: 2-4 hours (including network setup and getting test tokens). Deployment to mainnet with gas settings check and verification: 4-8 hours. From scratch, including deploy scripts and migrations: up to 2 days.







