Arc

Setting Up Hardhat and Foundry for Arc

Last verified: September 16, 2026By the TrustSwap Team
Today on Arc: mainnet countdown, ARC token news, and every launch — covered daily. → Read today’s briefing

Arc is EVM-compatible, so Hardhat and Foundry work the way they always have — you add a network entry, point it at an RPC, and deploy. The two things that differ are the gas token and the decimals: fees on Arc are paid in USDC, and the native balance carries 18 decimals at the protocol level rather than the 6 you see on ERC-20 USDC elsewhere. This guide covers both toolchains end to end, with the real mainnet network entry alongside the testnet one you use for rehearsal.

Arc mainnet has been live since September 16, 2026. This page gives you the real mainnet network entry for both toolchains, alongside the testnet entry you'll want for rehearsal before spending real USDC. Last reviewed: September 2026.

What you need before you configure anything

Arc mainnet parameters are published and stable: chain ID 5042 (0x13b2), RPC endpoint https://rpc.mainnet.arc.io, block explorer https://explorer.arc.io. Gas is native USDC with 18 decimals; there is no mainnet faucet, so your deployer needs a real funded balance. Testnet parameters are also published and stable: chain ID 5042002, RPC endpoint rpc.testnet.arc.io, block explorer testnet.arcscan.app, and a faucet at faucet.circle.com.

Do not guess a chain ID or hand-type one from memory. A wrong chain ID does not fail loudly; it either refuses to broadcast or, worse, signs a transaction whose replay-protection domain does not match the chain you think you are on. Copy it from docs.arc.io.

For rehearsal, you need testnet USDC to pay for gas. There is no ETH on Arc, on testnet or mainnet. Paste your deployer's 0x… address into the address field at faucet.circle.com, select the Arc testnet network, and confirm the drip landed with cast balance $DEPLOYER --rpc-url https://rpc.testnet.arc.io — a non-zero result means you are funded. A deploy from an unfunded account is the most common first-run error, and the RPC reports it as a bare insufficient funds for gas string rather than anything more helpful. If you have not used the testnet before, the Arc testnet guide walks through faucet access and network basics.

How do you configure Hardhat for Arc?

Hardhat needs a network entry with the RPC URL, the chain ID, and an accounts source. Nothing about Arc requires a custom Hardhat plugin for deployment itself; the standard hardhat-toolbox stack is sufficient. Below is a hardhat.config.ts with both networks defined.

// hardhat.config.ts
import type { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import * as dotenv from "dotenv";
dotenv.config();

const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.26",
    settings: {
      optimizer: { enabled: true, runs: 200 },
      // Pin evmVersion explicitly rather than relying on the
      // compiler default, so verification metadata is reproducible.
      // Confirm the highest fork Arc accepts against Circle's docs.
      evmVersion: "cancun",
    },
  },
  networks: {
    arc: {
      url: process.env.ARC_MAINNET_RPC ?? "https://rpc.mainnet.arc.io",
      chainId: 5042,
      accounts: process.env.DEPLOYER_KEY ? [process.env.DEPLOYER_KEY] : [],
    },
    arcTestnet: {
      url: process.env.ARC_TESTNET_RPC ?? "https://rpc.testnet.arc.io",
      chainId: 5042002,
      accounts: process.env.DEPLOYER_KEY ? [process.env.DEPLOYER_KEY] : [],
    },
  },
};

export default config;

Pin evmVersion rather than inheriting it, for two reasons. A compiler default that emits an opcode the chain has not enabled produces a deploy that reverts with no useful message. And the default moves: Solidity's 0.8.30 release in May 2025 changed it from cancun to prague in step with Ethereum's Pectra upgrade, per the Solidity team's release announcement, so a routine compiler bump can silently change the bytecode you ship.

Which fork Arc mainnet accepts is worth checking directly rather than taking from a guide — Circle's Arc developer documentation (docs.arc.io) is the source of record. cancun above is a conservative starting point, not a verified ceiling. If a contract that deploys on Ethereum reverts on Arc with no revert reason, step the evmVersion down one and recompile before looking anywhere else.

A minimal deploy script and the commands to run it:

// scripts/deploy.ts
import { ethers } from "hardhat";

async function main() {
  const [deployer] = await ethers.getSigners();
  const balance = await ethers.provider.getBalance(deployer.address);

  Native balance is USDC with 18 decimals at the protocol level.
  formatEther is correct here; formatUnits(balance, 6) is not.
  console.log("deployer:", deployer.address);
  console.log("gas balance (USDC):", ethers.formatEther(balance));

  const factory = await ethers.getContractFactory("MyToken");
  const contract = await factory.deploy("MyToken", "MTK", 18);
  await contract.waitForDeployment();

  console.log("deployed to:", await contract.getAddress());
}

main().catch((e) => {
  console.error(e);
  process.exitCode = 1;
});
npx hardhat compile

# Testnet rehearsal
npx hardhat run scripts/deploy.ts --network arcTestnet

# Mainnet
npx hardhat run scripts/deploy.ts --network arc

A successful run prints Compiled N Solidity files successfully, then the script's deployer: and gas balance (USDC): lines, then deployed to: 0x…. If the gas balance prints as 0.0, stop — the deploy that follows will fail.

How do you configure Foundry for Arc?

Foundry keeps network configuration in foundry.toml under [rpc_endpoints], with chain selection handled per-command by the --rpc-url flag. Foundry reads the chain ID from the node rather than from config for most operations, which removes one class of mistake — but --chain still matters for verification and for cheatcodes that fork.

# foundry.toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.26"
optimizer = true
optimizer_runs = 200
evm_version = "cancun" # pin explicitly; confirm Arc's accepted fork

[rpc_endpoints]
arc = "https://rpc.mainnet.arc.io"
arc_testnet = "https://rpc.testnet.arc.io"

[etherscan]
# Explorer verification config. explorer.arc.io is the mainnet explorer,
# testnet.arcscan.app the testnet one. See the note below on verifier
# compatibility — confirm whether each speaks the Etherscan or Blockscout API shape.
arc = { key = "${ARCSCAN_API_KEY}", chain = 5042, url = "https://explorer.arc.io/api" } # confirm the verifier API shape against docs.arc.io
arc_testnet = { key = "${ARCSCAN_API_KEY}", chain = 5042002, url = "https://testnet.arcscan.app/api" }

That [etherscan] block assumes explorer.arc.io speaks the Etherscan verification API, because that is what Foundry's --etherscan-api-key path expects. Explorers split roughly two ways here: an Etherscan-compatible /api endpoint, which the config above targets, or a Blockscout backend, where you pass --verifier blockscout with a different URL path and no API key. Try Etherscan first; a rejection naming an unrecognised request, rather than a bytecode mismatch, means you want the other one. See how to verify a contract on Arcscan for the full flag-by-flag walkthrough.

# Environment
export ARC_TESTNET_RPC=https://rpc.testnet.arc.io
export DEPLOYER_KEY=0x...   # use a throwaway key on testnet

# Build and test
forge build
forge test -vvv

# Simulate against the live chain before broadcasting
forge script script/Deploy.s.sol:Deploy \
  --rpc-url arc_testnet

# Broadcast
forge script script/Deploy.s.sol:Deploy \
  --rpc-url arc_testnet \
  --private-key $DEPLOYER_KEY \
  --broadcast

# One-off deploy without a script
forge create src/MyToken.sol:MyToken \
  --rpc-url arc_testnet \
  --private-key $DEPLOYER_KEY \
  --constructor-args "MyToken" "MTK" 18

# Read the chain back
cast chain-id --rpc-url arc_testnet          # expect 5042002
cast chain-id --rpc-url arc                  # expect 5042
cast balance $DEPLOYER --rpc-url arc_testnet  # native USDC, 18 decimals
cast gas-price --rpc-url arc_testnet

cast chain-id is worth running as a habit before any mainnet broadcast, because it is the cheapest possible check that the RPC you configured is the chain you believe it is.

What actually differs from an Ethereum or Base setup?

Three things, and only three, matter in practice.

Gas is denominated in USDC. Fee estimation, msg.value, and every balance check still speak in the native unit — that unit is simply USDC rather than ether. On testnet, the average fee has run around $0.004 per transaction as of August 2026, so gas budgeting stops being a design constraint for most contracts. It does not stop being a correctness constraint: an unfunded deployer still fails.

The native token carries 18 decimals. This is the trap. ERC-20 USDC on Ethereum, Base and elsewhere is a 6-decimal token, so developers arriving from those chains reach for parseUnits(x, 6). On Arc's native gas balance that is wrong by twelve orders of magnitude. Use parseEther / formatEther for native amounts, and reserve 6-decimal handling for bridged ERC-20 USDC contracts if and when you interact with them. The 18-decimals explainer covers the full story, including why some wallets still label the native balance "ETH".

Finality is deterministic and sub-second. Arc uses Malachite consensus with roughly 780ms finality, so a transaction that is included is final — there is no probabilistic reorg window to wait out. In practice you can drop confirmation-count heuristics like waitForTransaction(hash, 12) down to a single confirmation for application code. Custodial and exchange-grade integrations are a different question: those desks set deposit-crediting policy from an issuer's published guidance rather than from the consensus property alone, and Circle has not published a recommended confirmation depth for Arc as of this writing. If you are crediting customer balances rather than updating a UI, take that number from Circle's documentation when it appears.

Everything else — opcodes, ABI encoding, CREATE2 address derivation, standard libraries — behaves as on any EVM chain. Arc's EVM compatibility page covers the equivalence claim in detail.

How should you structure testnet-to-mainnet promotion?

Keep the mainnet values out of the config file as literals and pull them from the environment, so a missing or wrong value fails at startup rather than silently deploying to the wrong place. The values themselves are settled — chain ID 5042, RPC https://rpc.mainnet.arc.io — but a preflight check is still worth keeping, since a typo in an env var is indistinguishable from a stale one until it broadcasts.

# .env.example — commit this, never commit .env
ARC_TESTNET_RPC=https://rpc.testnet.arc.io
ARC_MAINNET_RPC=https://rpc.mainnet.arc.io
ARC_MAINNET_CHAIN_ID=5042
DEPLOYER_KEY=
ARCSCAN_API_KEY=
# Preflight check before any mainnet broadcast
: "${ARC_MAINNET_RPC:?set ARC_MAINNET_RPC before deploying}"
: "${ARC_MAINNET_CHAIN_ID:?set ARC_MAINNET_CHAIN_ID before deploying}"
test "$(cast chain-id --rpc-url "$ARC_MAINNET_RPC")" = "$ARC_MAINNET_CHAIN_ID" \
  || { echo "chain id mismatch — refusing to deploy"; exit 1; }

Deploy to testnet, verify the bytecode, exercise the contract with real calls, then promote. Once the contract is live, verifying the source is the next step — see how to verify a contract on Arcscan for the flag-by-flag commands for both toolchains. If you are building the front end against the same contracts, viem and wagmi on Arc covers the client-side chain definition that has to match this config exactly.

FAQ

What is Arc's chain ID?

Arc mainnet's chain ID is 5042 (0x13b2), with RPC endpoint https://rpc.mainnet.arc.io. Arc's public testnet uses chain ID 5042002, with RPC endpoint rpc.testnet.arc.io. Verify either with cast chain-id against the RPC before broadcasting anything.

Do I need a special Hardhat or Foundry plugin for Arc?

No. Arc is EVM-compatible, so standard hardhat-toolbox and stock Foundry handle compilation, deployment and testing with only a network entry added. Source verification is the one area that depends on explorer-side support rather than your toolchain: @nomicfoundation/hardhat-verify reaches the explorer through a customChains entry you write yourself, and whether it answers the Etherscan-shaped request it sends is a property of the explorer, not the plugin. Budget for the explorer's manual upload form as a fallback if your first verification attempt doesn't go through — see verifying a contract on Arcscan.

How do I get gas to deploy on Arc testnet?

Request testnet USDC from faucet.circle.com against your deployer address, then confirm the balance on testnet.arcscan.app. Gas on Arc is paid in USDC, not ETH; testnet transactions averaged roughly $0.004 as of August 2026, so a small faucet drip covers many deploys.

Why does my balance look 12 orders of magnitude off?

Because you formatted it with 6 decimals. Arc's native gas balance uses 18 decimals at the protocol level, unlike the 6-decimal ERC-20 USDC deployed on other chains. Use formatEther / parseEther for native amounts on Arc.

Can I fork Arc mainnet in tests?

Yes, using the standard --fork-url flag in Foundry or hardhat_reset forking config, pointed at an Arc RPC endpoint. Forking testnet works against rpc.testnet.arc.io, and forking mainnet works against https://rpc.mainnet.arc.io, and a node that serves state at the block you pin. Test it: fork at a block a few thousand deep and read a historical balance. A missing-trie-node or unsupported-block error means you need an archive provider rather than the public endpoint.

Deploying a token on Arc? Team Finance handles minting, liquidity locks and vesting with audited contracts and flat USDC-quoted fees — see /arc/deploy-smart-contract for the deployment path, or /arc for the full Arc builder hub.Launch a token on Arc

Sources: Circle documentation and Arc developer docs (arc.io, developers.circle.com) for chain parameters, testnet endpoints and consensus design; Hardhat documentation (hardhat.org) and Foundry Book (book.getfoundry.sh) for toolchain configuration syntax; the Solidity 0.8.30 release announcement (soliditylang.org, May 2025) for the change of default EVM version from cancun to prague; Solidity compiler documentation (docs.soliditylang.org) for evmVersion behaviour; Arc testnet explorer testnet.arcscan.app for network status.

Last verified: September 16, 2026

Arc mainnet is live. Launch on it today.

Team Finance has secured $2.7B+ across 40,000+ projects since 2020. Mint the token, lock the liquidity, vest the team and run distribution — on a chain where the fees are quoted in dollars.

See everything Team Finance supports on ArcLaunch a token on ArcGet The Crypto AppArc Launchpad