How to Deploy Smart Contracts With $0 Gas Using Testnets
You don’t need real ETH to learn, build, test, and even run full CI/CD for Web3. In this practical guide, you’ll deploy contracts to modern Ethereum testnets (Sepolia, Holesky, Base Sepolia, Polygon Amoy, Optimism/Arbitrum Sepolia, zkSync Sepolia) and popular alt L1 testnets (Avalanche Fuji, BNB Testnet) using Remix, Hardhat, and Foundry all with $0 gas via faucets.
1) Why testnets still matter in 2025
Even with powerful local forks, public testnets remain the bridge between your laptop and the real world: public RPCs, mempool behavior, third-party indexers, explorers, bridge flows, gas markets, and the social “muscle memory” of deploying & verifying in shared infrastructure. They simulate users and bots you don’t control exactly where bugs appear.
2) The testnet map (Ethereum & friends)
Here are widely used 2025 testnets and where each shines. Always confirm current status in official docs.
| Ecosystem | Testnet | Chain ID | RPC (example) | Explorer | Use cases |
|---|---|---|---|---|---|
| Ethereum | Sepolia | 11155111 | https://rpc.sepolia.org (or provider) | sepolia.etherscan.io | Main EVM testnet; most tooling supports it |
| Ethereum | Holesky | 17000 | https://holesky.drpc.org | holesky.etherscan.io | Validator/staking-scale testing, high supply |
| Base (OP Stack) | Base Sepolia | 84532 | https://sepolia.base.org | sepolia.basescan.org | Build on Base with L2 specifics |
| Optimism | OP Sepolia | 11155420 | https://sepolia.optimism.io | OP-sepolia Etherscan | OP Stack dapps, withdrawal semantics |
| Arbitrum | Arbitrum Sepolia | 421614 | https://sepolia-rollup.arbitrum.io/rpc | sepolia.arbiscan.io | Arbitrum Nitro tooling & bridges |
| Polygon PoS | Amoy | 80002 | https://rpc-amoy.polygon.technology | Oklink Amoy | Polygon PoS testnet (replaces Mumbai) |
| zkSync | zkSync Sepolia | 300 | https://sepolia.era.zksync.dev | zkSync explorer | zkEVM features, paymasters, AA |
| Avalanche | Fuji | 43113 | https://api.avax-test.network/ext/bc/C/rpc | testnet.snowtrace.io | Subnets & C-Chain testing |
| BNB Chain | BNB Testnet | 97 | https://data-seed-prebsc-1-s1.binance.org:8545 | testnet.bscscan.com | Low-fee EVM tests & bridges |
Beware: Fake testnets and phishing faucets exist. Use official docs or reputable providers only.
3) Wallet & RPC setup (MetaMask + CLI)
MetaMask (UI)
- Install MetaMask from the official store: metamask.io
- Add a network: Settings → Networks → Add network → enter Chain ID, RPC, Explorer
- Fund with test ETH/MATIC/etc from the chain’s official faucet
CLI (Node.js / Foundry)
- Hardhat:
npm i -D hardhat,npx hardhat - Foundry: Foundry Book →
curl -L https://foundry.paradigm.xyz | bashthenfoundryup - Get a free RPC URL from providers (Alchemy/Infura/Ankr/QuickNode free tiers)
Separate keys: Use a dedicated test-only private key. Never reuse your real mainnet key.
4) Method A — Deploy with Remix (no installs)
Remix is the fastest on-ramp. Great for first-time deployments and quick iterations.
- Open remix.ethereum.org. Create a new file:
contracts/Token.sol. - Paste a simple ERC-20 (OpenZeppelin) or minimal contract.
- Compile with Solidity compiler ≥ the pragma version.
- Connect wallet: Deploy & Run → Environment: Injected Provider - MetaMask → ensure the testnet is selected.
- Deploy & confirm in MetaMask with test ETH.
Minimal example: Counter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Counter {
uint256 public value;
event Incremented(uint256 newValue);
function inc() external {
value += 1;
emit Incremented(value);
}
}
Heads-up: Remix is great for demos, but teams should graduate to Hardhat/Foundry for automated tests, scripts, and CI/CD.
5) Method B — Deploy with Hardhat
Hardhat provides batteries-included scaffolding, plugins, and task automation.
- Initialize a project:
mkdir hh-zero-gas && cd hh-zero-gas
npm init -y
npm i -D hardhat @nomicfoundation/hardhat-toolbox dotenv
npx hardhat # create a basic project
- Create
.envwith your test key & RPC:
SEPOLIA_RPC_URL="https://rpc.sepolia.org"
PRIVATE_KEY="0xYOUR_TEST_PRIVATE_KEY"
- Edit
hardhat.config.ts(or.js):
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import * as dotenv from "dotenv";
dotenv.config();
const config: HardhatUserConfig = {
solidity: "0.8.24",
networks: {
sepolia: {
url: process.env.SEPOLIA_RPC_URL!,
accounts: [process.env.PRIVATE_KEY!],
},
baseSepolia: {
url: "https://sepolia.base.org",
chainId: 84532,
accounts: [process.env.PRIVATE_KEY!],
},
},
etherscan: {
apiKey: {
sepolia: "YOUR_ETHERSCAN_KEY",
baseSepolia: "YOUR_BASESCAN_KEY"
}
}
};
export default config;
- Add a simple contract:
contracts/Greeter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Greeter {
string private greeting;
constructor(string memory _g) { greeting = _g; }
function greet() external view returns (string memory) { return greeting; }
}
- Create a deploy script:
scripts/deploy.ts
import { ethers } from "hardhat";
async function main() {
const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, testnet!");
await greeter.waitForDeployment();
console.log("Greeter deployed at:", await greeter.getAddress());
}
main().catch((e) => { console.error(e); process.exit(1); });
- Deploy to Sepolia for $0 (test ETH):
npx hardhat run scripts/deploy.ts --network sepolia
Tip: Keep separate accounts for each testnet to avoid nonce confusion and to compartmentalize leaks.
6) Method C — Deploy with Foundry (forge)
Foundry is lightweight, fast, and beloved for its fuzzing and invariant tests.
- Scaffold:
forge init fd-zero-gas
cd fd-zero-gas
forge install OpenZeppelin/openzeppelin-contracts --no-commit
- Add a contract:
src/Token.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
contract TestToken is ERC20 {
constructor() ERC20("TestToken", "TT") { _mint(msg.sender, 1_000_000 ether); }
}
- Configure RPC & key in
.envandfoundry.toml:
# .env
PRIVATE_KEY=0xYOUR_TEST_PRIVATE_KEY
SEPOLIA_RPC_URL=https://rpc.sepolia.org
# foundry.toml
[rpc_endpoints]
sepolia = "${SEPOLIA_RPC_URL}"
- Deploy with forge:
source .env
forge create --rpc-url $SEPOLIA_RPC_URL \
--private-key $PRIVATE_KEY \
src/Token.sol:TestToken
Verify (Foundry): forge verify-contract <addr> src/Token.sol:TestToken <ETHERSCAN_API_KEY> --chain sepolia
7) Verifying contracts on testnet explorers
Verification lets users & bots read your source on Etherscan/Basescan/etc. Most explorers mimic the Etherscan API.
Hardhat Etherscan plugin
npx hardhat verify --network sepolia 0xDepl0yEd... "Hello, testnet!"
Add each network’s API key in etherscan.apiKey config. For Base/OP/Arbitrum testnets use their specific keys.
Foundry
forge verify-contract 0xDepl0yEd... src/Token.sol:TestToken YOUR_KEY --chain sepolia
Read: Verify docs.
Constructor args: Remember to include them exactly. Mismatched bytecode = failed verification.
8) L2-specific quirks (OP Stack, Arbitrum, zk)
- OP Stack (Base/OP): Withdrawals are delayed; cross-domain messaging has special APIs. Test on Base Sepolia or OP Sepolia. Docs: docs.base.org, docs.optimism.io
- Arbitrum: Nitro-specific nuances; check gas estimation & aliases. Docs: docs.arbitrum.io
- zkSync: Different tooling packages and AA/paymaster features; use their hardhat plugin or Foundry templates. Docs: zkSync Era docs
- Polygon Amoy: PoS behavior and bridges differ from zkEVM; follow Polygon docs
Explorer variance: Etherscan-compatible explorers have different API hosts. Use the exact “testnet” key/URL for each explorer family (Basescan, Arbiscan, Snowtrace, etc.).
9) Where to get $0 testnet funds (official faucets)
Ethereum
- Sepolia faucet (via reputable providers): pk910, Alchemy, Infura
- Holesky info: Holesky Etherscan (see “faucet” in docs/community)
L2 & Alt L1
- Base Sepolia: Base faucets
- Optimism Sepolia: OP faucets
- Arbitrum Sepolia: Arbitrum faucets
- Polygon Amoy: Polygon faucet
- zkSync Sepolia: zkSync faucet info
- Avalanche Fuji: AVAX faucet
- BNB Testnet: BNB faucet
Never pay for test ETH/MATIC/BNB/AVAX. If someone sells it, it’s a scam.
10) Security hygiene for test keys
- Use a fresh test-only wallet (separate seed). Label it clearly.
- Store PRIVATE_KEY in
.env(never commit). Usedotenvordirenv. - Rotate keys if you paste them into online tools. Assume leaks; keep balances tiny.
- Bookmark official faucets; beware “airdrop drainer” sites.
- Simulate transactions; read signing prompts even on testnet.
11) Bonus — $0-gas CI/CD with forks & ephemeral chains
Combine local forks and testnets for robust pipelines:
Hardhat
// hardhat.config.ts
networks: {
hardhat: {
forking: { url: process.env.MAINNET_RPC! }, // read-only fork
},
}
Run test suites against real mainnet state without spending gas.
Foundry
forge test -vv --fork-url $MAINNET_RPC
Use cheatcodes (e.g., vm.roll, vm.prank) for precise scenarios.
Pattern: Unit tests ▶ Forked-integration tests ▶ Staging on public testnet ▶ Ship.
12) Troubleshooting playbook
| Symptom | Likely Cause | Fix |
|---|---|---|
| “insufficient funds for gas * price + value” on testnet | No test ETH in that account | Use the official faucet; ensure you’re on the correct testnet |
| Stuck pending tx | Low gas; conflicting nonce | Speed up or cancel; or MetaMask → Advanced → Reset account |
| Verification fails | Wrong compiler/optimizer/constructor args | Match exact settings; include constructor params; ensure bytecode hash matches |
| “Internal JSON-RPC error” | Provider outage/rate-limits | Switch RPC; check status page; retry later |
| L2 bridge tx not visible | Wrong explorer or layer | Use L2-appropriate explorer; confirm message status in bridge UI |
Quick RPC sanity checks (curl)
# Chain ID
curl -s -X POST https://rpc.sepolia.org \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
# Latest block
curl -s -X POST https://sepolia.base.org \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
13) FAQ
Are testnets “just as good” as mainnet?
No. They model the environment but lack real liquidity, MEV pressure, and some infra quirks. Use both forks and testnets.
Which testnet should I pick first?
Start with Sepolia (widest ecosystem support). If targeting Base, add Base Sepolia early. For Polygon, use Amoy.
Can I use a hardware wallet on testnet?
Yes, but most teams use hot test keys for speed. For public betas or demos, hardware adds safety.
Do faucets rate-limit?
Often yes. If you hit a limit, try again later or use another official faucet or provider faucet.
How do I test cross-chain apps?
Use the testnet versions of bridges and oracles. Many rollups provide testnet bridges that mimic production delays.
14) External docs & resources
- Remix IDE: remix.ethereum.org • Docs: Remix docs
- Hardhat: hardhat.org • Toolbox: guides
- Foundry: Foundry Book
- Etherscan (Sepolia): sepolia.etherscan.io
- Base docs & faucets: docs.base.org • faucets
- Optimism: docs.optimism.io • Arbitrum: docs.arbitrum.io
- Polygon Amoy: docs.polygon.technology • Faucet: faucet
- zkSync Era: era.zksync.io/docs
- Avalanche Fuji: docs.avax.network • faucet
- BNB Chain Testnet: BNB docs • faucet
- OpenZeppelin Contracts: docs.openzeppelin.com/contracts
