Documentation Index
Fetch the complete documentation index at: https://docs.arc.io/llms.txt
Use this file to discover all available pages before exploring further.
Arc uses USDC as its native gas token, so fees are inherently denominated in
USD. The eth_gasPrice and eth_feeHistory RPCs return values in USDC wei (18
decimals). The EWMA fee smoothing model keeps fees predictable—dramatic spikes
are unlikely. Display fees as $X.XX (or ~$0.01), never as “Gwei” or “ETH.”
Prerequisites
Before you begin:
- You have an RPC endpoint for Arc.
- You are using an EIP-1559-compatible library (viem, ethers.js, or equivalent).
- You understand that Arc’s native currency is USDC, not ETH.
Steps
Step 1. Fetch the current gas price
Use eth_gasPrice for a single value or eth_feeHistory for historical base
fees and priority fee percentiles.
import { createPublicClient, http, formatUnits } from "viem";
import { arc } from "viem/chains";
const client = createPublicClient({
chain: arc,
transport: http("https://rpc.arc.circle.com"),
});
// Simple: current gas price in USDC wei
const gasPrice = await client.getGasPrice();
console.log("Gas price (wei):", gasPrice);
// Detailed: recent base fee history
const feeHistory = await client.getFeeHistory({
blockCount: 4,
rewardPercentiles: [25, 50, 75],
});
console.log("Latest base fee (wei):", feeHistory.baseFeePerGas.at(-1));
Step 2. Estimate gas for the transaction
Use eth_estimateGas to determine how much gas your transaction requires.
// Native USDC transfer: ~21,000 gas
const simpleTransferGas = 21_000n;
// ERC-20 token transfer or contract call: use estimateGas
const contractGas = await client.estimateGas({
account: "0xYourAddress",
to: "0xContractAddress",
data: encodedCalldata,
});
Typical gas costs:
| Transaction type | Approximate gas |
|---|
| Native USDC send | 21,000 |
| ERC-20 transfer | ~65,000 |
| Contract interaction | Varies—always estimate |
Step 3. Build EIP-1559 fee parameters
Arc supports EIP-1559 transactions. Set maxFeePerGas and
maxPriorityFeePerGas:
const latestBlock = await client.getBlock();
const baseFee = latestBlock.baseFeePerGas!;
// 2x base fee is generous—Arc's EWMA smoothing keeps fees stable
const maxFeePerGas = baseFee * 2n;
// Priority fee of 0 is acceptable on Arc (validators don't require tips)
const maxPriorityFeePerGas = 0n;
The effective gas price is baseFeePerGas + priorityFee. The base fee has a
minimum of 20 Gwei in USDC terms. Because Arc uses an EWMA (exponentially
weighted moving average) model to adjust the base fee gradually, fee spikes
are smoothed out and prices remain predictable.
Step 4. Calculate the maximum fee in USD
Multiply the gas limit by maxFeePerGas, then convert from 18-decimal USDC wei
to a dollar amount.
function calculateMaxFeeUsd(gasLimit: bigint, maxFeePerGas: bigint): string {
const maxCostWei = gasLimit * maxFeePerGas;
// USDC has 18 decimals as the native gas token on Arc
// Since 1 USDC = $1, the numeric value IS the USD cost
const usdCost = formatUnits(maxCostWei, 18);
return usdCost;
}
// Example: simple transfer
const maxFee = calculateMaxFeeUsd(21_000n, maxFeePerGas);
console.log(`Max fee: $${Number(maxFee).toFixed(6)}`);
Show fees as a dollar amount. Use ~ to indicate the value is an estimate.
function formatFeeDisplay(gasLimit: bigint, maxFeePerGas: bigint): string {
const maxCostWei = gasLimit * maxFeePerGas;
const usdValue = Number(formatUnits(maxCostWei, 18));
if (usdValue < 0.01) {
return "< $0.01";
}
return `~$${usdValue.toFixed(2)}`;
}
Standard libraries like ethers.js and viem label the native currency as “ETH”
by default. You must override this in your UI. Displaying “0.00042 ETH”
instead of ”~$0.01” confuses users and misrepresents the cost.
Worked examples
Simple USDC transfer
// Given: base fee = 20 Gwei (minimum), gas limit = 21,000
const baseFee = 20_000_000_000n; // 20 Gwei in wei
const gasLimit = 21_000n;
const maxFeePerGas = baseFee * 2n; // 40 Gwei
const maxCostWei = gasLimit * maxFeePerGas;
// 21,000 * 40,000,000,000 = 840,000,000,000,000 wei
// = 0.00000084 USDC = $0.00000084
const display = formatFeeDisplay(gasLimit, maxFeePerGas);
// Output: "< $0.01"
Contract interaction
// Given: base fee = 500,000 Gwei (0.0005 USDC), gas limit = 65,000
const baseFee = 500_000_000_000_000n; // 500,000 Gwei in wei
const gasLimit = 65_000n;
const maxFeePerGas = baseFee * 2n; // 1,000,000 Gwei
const maxCostWei = gasLimit * maxFeePerGas;
// 65,000 * 1,000,000,000,000,000 = 65,000,000,000,000,000,000 wei
// = 0.065 USDC = $0.065
const display = formatFeeDisplay(gasLimit, maxFeePerGas);
// Output: "~$0.07"
Users are only charged gasUsed * effectiveGasPrice. The difference between
maxFeePerGas and the actual effective gas price is refunded. It’s safe to
show the maximum estimate in your UI with language like “Max fee” or “Up to.”
See also