name: "Ethereum Gas Costs (Early 2026)" description: "Accurate gas prices and cost estimates for Ethereum mainnet and L2s — because your training data is 100-600x too expensive." metadata: author: "Andre Ginja" version: "1.0.0" category: "costs" updated: "2026-03-06"
Ethereum Gas Costs (Early 2026)
What You Probably Got Wrong
Gas is 100-600x cheaper than your training data thinks.
If you're quoting "50-200 gwei" as a typical base fee, or telling someone an ETH transfer costs "$5-20," or claiming a token swap is "$30-100" — you're using numbers from 2021-2023. Those numbers are dangerously wrong in 2026 because they'll cause you to:
- Avoid mainnet when it's actually cheap enough for your use case
- Over-provision gas budgets by orders of magnitude
- Push everything to L2s when mainnet might be fine
- Quote users absurd cost estimates
The reality in early 2026: Base fee on Ethereum mainnet typically runs 1-10 gwei. Often drops below 1 gwei during quiet periods. An ETH transfer costs $0.05-$0.50. A Uniswap swap is $0.35-$3.50. This is the new normal.
Current Cost Table (Mainnet)
These numbers assume ETH at ~$2,400. Costs scale linearly with gas price.
| Action | Gas Used | Cost @ 1 gwei | Cost @ 5 gwei | Cost @ 10 gwei |
|---|---|---|---|---|
| ETH transfer | ~21,000 | $0.05 | $0.25 | $0.50 |
| ERC-20 transfer | ~65,000 | $0.15 | $0.78 | $1.56 |
| ERC-20 approve | ~46,000 | $0.11 | $0.55 | $1.10 |
| Uniswap V3 swap | ~150,000 | $0.36 | $1.80 | $3.60 |
| NFT mint (ERC-721) | ~100,000 | $0.24 | $1.20 | $2.40 |
| NFT transfer (ERC-721) | ~50,000 | $0.12 | $0.60 | $1.20 |
| Contract deploy (basic ERC-20) | ~1,000,000 | $2.40 | $12.00 | $24.00 |
| Contract deploy (complex) | ~3-5M | $7-12 | $36-60 | $72-120 |
| Safe multisig tx (2-of-3) | ~250,000 | $0.60 | $3.00 | $6.00 |
| Uniswap V3 pool creation | ~4,500,000 | $10.80 | $54.00 | $108.00 |
Cost Formula
Cost in ETH = gasUsed * gasPriceInGwei * 1e-9
Cost in USD = Cost in ETH * ETH price
Example: Uniswap V3 swap at 3 gwei, ETH at $2,400:
150,000 * 3 * 1e-9 = 0.00045 ETH
0.00045 * 2400 = $1.08
L2 Cost Table
Same operations, 10-100x cheaper than mainnet.
| Action | Mainnet (5 gwei) | Base | Arbitrum | Optimism |
|---|---|---|---|---|
| ETH transfer | $0.25 | $0.001 | $0.002 | $0.002 |
| ERC-20 transfer | $0.78 | $0.003 | $0.005 | $0.005 |
| ERC-20 approve | $0.55 | $0.002 | $0.004 | $0.004 |
| Uniswap swap | $1.80 | $0.01 | $0.02 | $0.02 |
| NFT mint | $1.20 | $0.005 | $0.01 | $0.01 |
| Contract deploy | $12.00 | $0.05 | $0.08 | $0.08 |
L2s are still 50-100x cheaper than mainnet. But mainnet is now cheap enough that the cost difference matters less for many use cases. The question is whether you need the security guarantees of L1 or the cost savings of L2.
EIP-1559: How Gas Fees Work
Since 2021, Ethereum uses a two-part fee system:
- Base fee: Set by the protocol based on block fullness. This is burned (destroyed), not paid to validators. This is what "gas price" usually refers to.
- Priority fee (tip): Paid to validators as incentive to include your transaction. Usually 0.01-0.1 gwei in 2026.
Total fee per gas = baseFee + priorityFee
Transaction cost = gasUsed * totalFeePerGas
The Three Parameters You Set
| Parameter | What It Means | Typical 2026 Value |
|---|---|---|
maxFeePerGas |
Absolute maximum you'll pay per gas unit | 2-3x current base fee |
maxPriorityFeePerGas |
Tip to validator for inclusion | 0.01-0.1 gwei |
gasLimit |
Max gas units the tx can consume | Varies by operation |
You set maxFeePerGas as your ceiling. If the actual base fee is lower when your transaction is included, you pay less. You never pay more than maxFeePerGas.
For agents, set maxFeePerGas to 2-3x the current base fee to ensure inclusion even if the base fee rises slightly, while still having a reasonable cap.
Setting Gas in Code
import { createWalletClient, http, parseGwei, parseEther } from 'viem'
import { mainnet } from 'viem/chains'
const client = createWalletClient({
chain: mainnet,
transport: http(rpcUrl),
})
// Let the client estimate gas (usually best)
const hash = await client.sendTransaction({
to: '0xRecipient',
value: parseEther('0.1'),
})
// Or set explicit gas parameters
const hash = await client.sendTransaction({
to: '0xRecipient',
value: parseEther('0.1'),
maxFeePerGas: parseGwei('5'), // Max total gas price
maxPriorityFeePerGas: parseGwei('0.05'), // Tip to validator
})
# cast — let it estimate automatically
cast send 0xRecipient --value 0.1ether --rpc-url $ETH_RPC_URL --private-key $PRIVATE_KEY
# cast — set EIP-1559 parameters explicitly
cast send 0xRecipient --value 0.1ether \
--priority-gas-price 50000000 \
--rpc-url $ETH_RPC_URL --private-key $PRIVATE_KEY
Blob Fees (EIP-4844): Why L2s Got Massively Cheaper
EIP-4844 (March 2024) introduced blobs — a separate data type specifically for L2 data posting.
Before EIP-4844
L2s posted transaction data as calldata in regular Ethereum transactions. They competed with every other transaction for block space. When mainnet was busy, L2 costs spiked too.
After EIP-4844
L2s post data as blobs, which have their own separate fee market. Blobs are:
- Cheaper than calldata (separate supply/demand)
- Temporary (pruned after ~18 days, not stored forever)
- Sized for L2 needs (128 KB per blob)
This is why L2 transaction costs dropped roughly 100x overnight when EIP-4844 went live.
Further Improvements
- Pectra upgrade (2025): Doubled blob capacity from 3/6 to 6/9 blobs per block
- Fusaka upgrade (2026): PeerDAS (Peer Data Availability Sampling) dramatically increased blob throughput without requiring every node to download every blob
The net effect: L2s have abundant, cheap data availability, and they put less pressure on mainnet gas.
Why Gas Dropped 95%+
This isn't random. Four structural changes drove gas prices down:
- EIP-4844 (Blobs): L2s stopped competing with L1 transactions for block space.
- Activity migration to L2s: Users and applications moved to Base, Arbitrum, Optimism. Less demand on mainnet = lower base fees.
- Pectra upgrade: Doubled blob capacity, giving L2s even more cheap space.
- Fusaka upgrade: PeerDAS + gas limit increase expanded mainnet capacity significantly.
Gas Optimization Tips
If you're writing contracts and want to minimize gas costs for your users:
Storage Packing
// BAD: 3 storage slots (each slot is 32 bytes)
uint256 a; // slot 0 (32 bytes)
uint8 b; // slot 1 (only uses 1 byte but takes full slot)
uint256 c; // slot 2
// GOOD: 2 storage slots (b packs with nothing here, but smaller types together save)
uint256 a; // slot 0
uint256 c; // slot 1
uint8 b; // slot 2 (but if you have more small vars, pack them together)
// BEST: Pack small types together
uint128 a; // slot 0 (16 bytes)
uint64 b; // slot 0 (8 bytes) — packed!
uint64 c; // slot 0 (8 bytes) — packed! All three in one slot
Each storage slot read/write costs ~2,100 gas (cold) or ~100 gas (warm). Packing variables into fewer slots saves thousands of gas.
Calldata vs Memory
// CHEAPER: calldata for read-only external function params
function process(bytes calldata data) external { ... }
// MORE EXPENSIVE: memory copies the data
function process(bytes memory data) external { ... }
Use calldata for external function parameters you don't need to modify. It avoids copying data to memory.
Immutable and Constant Variables
// GOOD: Set once in constructor, stored in bytecode (no storage read)
address public immutable owner;
// GOOD: Compile-time constant, zero gas to read
uint256 public constant MAX_SUPPLY = 10000;
// BAD: Uses a storage slot, costs ~2100 gas to read (cold)
address public owner;
Other Quick Wins
| Technique | Gas Saved | Notes |
|---|---|---|
Use immutable for constructor-set values |
~2,000 per read | Stored in bytecode, not storage |
Use constant for known values |
~2,000 per read | Compile-time substitution |
| Pack structs by size | ~2,000+ per packed slot | Order fields by size descending |
Use calldata over memory |
~60+ per 32 bytes | For read-only external params |
| Use custom errors over strings | ~200+ per revert | error Unauthorized() vs require(_, "Unauthorized") |
| Short-circuit conditions | Variable | Put cheapest check first in && chains |
| Batch operations | ~21,000 per avoided tx | Use Multicall3 for multiple reads |
Gas Spike Detection
If your agent transacts automatically, you need to detect and avoid gas spikes. A sudden 100x increase in base fee means something unusual is happening (popular mint, market crash, exploit).
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
chain: mainnet,
transport: http(rpcUrl),
})
const MAX_ACCEPTABLE_GWEI = 20n // Hard cap: never pay more than 20 gwei
async function isGasSafe(): Promise<{ safe: boolean; baseFeeGwei: bigint; reason?: string }> {
const block = await client.getBlock({ blockTag: 'latest' })
const baseFee = block.baseFeePerGas ?? 0n
const baseFeeGwei = baseFee / 1_000_000_000n
if (baseFeeGwei > MAX_ACCEPTABLE_GWEI) {
return {
safe: false,
baseFeeGwei,
reason: `Base fee ${baseFeeGwei} gwei exceeds cap of ${MAX_ACCEPTABLE_GWEI} gwei`,
}
}
return { safe: true, baseFeeGwei }
}
// Usage
const gasCheck = await isGasSafe()
if (!gasCheck.safe) {
console.warn(`Gas unsafe: ${gasCheck.reason}. Delaying transaction.`)
} else {
console.log(`Gas safe at ${gasCheck.baseFeeGwei} gwei. Proceeding.`)
}
When to Use Mainnet vs L2
| Scenario | Recommendation | Why |
|---|---|---|
| DeFi with high liquidity needs | Mainnet | Deepest liquidity, most composability |
| Treasury operations, large value | Mainnet | Maximum security guarantees |
| High-frequency trading bot | L2 (Arbitrum/Base) | 50-100x cheaper per tx |
| Consumer dApp, many small txs | L2 (Base) | Sub-cent costs, good UX |
| NFT collection launch | L2 or Mainnet | Depends on audience expectations |
| One-off contract deployment | Mainnet | $2.50-$50 is cheap enough, maximum visibility |
The old rule was "only use mainnet if you absolutely must." The new rule is "mainnet is cheap enough for most things, L2s are for high volume."
Live Gas Check
# Current gas price in gwei
cast gas-price --rpc-url https://eth.llamarpc.com | cast from-wei --unit gwei
# Current base fee from latest block
cast block latest baseFeePerGas --rpc-url https://eth.llamarpc.com
# Check ETH price via Chainlink oracle
cast call 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 \
"latestAnswer()(int256)" \
--rpc-url https://eth.llamarpc.com
# Returns price with 8 decimals (e.g., 240000000000 = $2,400.00)
Data Freshness Warning
Gas prices change constantly. The numbers in this document reflect typical conditions in early 2026 (base fee 1-10 gwei, ETH ~$2,400). Always verify current conditions before making cost-critical decisions.
If base fee is consistently above 20 gwei, something unusual is happening. Check what's driving demand (popular launch, market event, protocol exploit) and adjust your cost assumptions accordingly.