EVM Gas, Fees & Tokens — A Complete Guide
EVM Gas, Fees & Tokens — A Complete Guide
This article is written for developers and deployers, providing an in-depth explanation of gas fees, unit systems, wei, native tokens, ERC-20 tokens, and their interrelationships on EVM chains. It covers everything from foundational concepts to the latest upgrades as of 2025 (EIP-4844, ERC-4337, Pectra, EIP-7702).
If you have ever confused gas units with wei, or were unsure what unit a gas limit is measured in, this guide will clarify these concepts once and for all.
Table of Contents
- 1. Native Tokens vs ERC-20 Tokens
- 2. Understanding Wei — The Smallest Unit
- 3. Gas — The Unit of Computation
- 4. Transaction Fees — Putting It All Together
- 5. Three Meanings of "Gas" — A Common Source of Confusion
- 6. LayerZero Cross-Chain Gas — Enforced Options Context
- 7. Quick Reference Cheat Sheet
- 8. The Modern Gas Landscape (2025)
- 9. Developer Gas Optimization Practices
- 10. Common Pitfalls and Debugging
- References
1. Native Tokens vs ERC-20 Tokens
In the EVM ecosystem, the word "token" encompasses two fundamentally different things: native tokens and ERC-20 tokens. Understanding the distinction between them is the first step to mastering the gas fee system.
1.1 Native Tokens
Every EVM-compatible chain has one and only one native token. It is the chain’s own "currency," existing at the protocol level and not dependent on any smart contract.
Core Characteristics:
- One per chain: Ethereum’s ETH, BSC’s BNB, Polygon’s MATIC (now renamed to POL), Avalanche’s AVAX, Arbitrum’s ETH, etc.
- Exists at the protocol layer: Native tokens are not smart contracts; they are built into the blockchain protocol. When nodes validate blocks, the transfer logic for native tokens is handled directly by the protocol code
- Used to pay gas fees: All transactions (including interactions with ERC-20 tokens, NFTs, DeFi protocols) must use native tokens to pay gas fees. This is a hard requirement of the EVM (before account abstraction, there was no way to substitute other tokens; see Section 8.2)
- Simple value transfer: Sending native tokens only requires specifying the amount in the transaction’s
valuefield, without calling any contract function - Account balance field: Every Ethereum account (EOA or contract account) has a built-in
balancefield that records the amount of native tokens it holds. This field is maintained directly by the protocol
Example — Sending native tokens (no contract call needed):
1 | // Using viem to send 0.1 ETH — specify value directly in the transaction, no data field needed |
1.2 ERC-20 Tokens
ERC-20 tokens are smart contract-based tokens that follow the standardized interface defined by the ERC-20 standard. They are the cornerstone of the DeFi ecosystem.
Core Characteristics:
- Smart contract implementation: Each ERC-20 token is an independent smart contract deployed on-chain with its own unique contract address. For example, USDT on Ethereum mainnet is at
0xdAC17F958D2ee523a2206206994597C13D831ec7 - Standard interface: All ERC-20 tokens implement the same interface functions:
transfer(),transferFrom(),approve(),balanceOf(),totalSupply(),allowance(), etc. - Transfer via contract functions: Sending ERC-20 tokens requires calling the token contract’s
transfer()ortransferFrom()function, which is entirely different from sending native tokens - Internal balance mapping: The token contract maintains a
mapping(address => uint256)that records how many tokens each address holds. This is contract state, not protocol-level balance - Requires native tokens to pay gas: Any interaction with ERC-20 tokens (transfers, approvals, queries) is an on-chain transaction that requires native tokens to pay gas fees. This means even if you hold a large amount of USDT, you cannot transfer it without ETH (on Ethereum)
Common ERC-20 Token Examples:
| Token | Type | Description |
|---|---|---|
| USDT | Stablecoin | USD-pegged stablecoin |
| USDC | Stablecoin | USD stablecoin issued by Circle |
| WETH | Wrapped Token | ERC-20 version of ETH |
| WBNB | Wrapped Token | ERC-20 version of BNB |
| UNI | Governance Token | Uniswap governance token |
| CAKE | Governance Token | PancakeSwap governance token |
| LINK | Utility Token | Chainlink oracle token |
| DAI | Stablecoin | Decentralized stablecoin |
Example — Sending ERC-20 tokens (contract call required):
1 | // Using viem to send 100 USDT — must call USDT contract's transfer function |
1.3 Wrapped Native Tokens (WETH, WBNB)
Wrapped Native Tokens are ERC-20 versions of native tokens, always backed 1:1. They exist to solve an important interface compatibility problem.
Why are wrapped tokens needed?
Native tokens (such as ETH) do not conform to the ERC-20 standard interface. However, DeFi protocols (DEXs, lending platforms, liquidity pools) are typically designed assuming all tokens follow the ERC-20 interface. To allow native tokens to participate in these protocols, a "wrapped" version that follows the ERC-20 standard is needed.
Wrapped tokens by chain:
| Chain | Native Token | Wrapped Token | Wrapper Contract |
|---|---|---|---|
| Ethereum | ETH | WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
| BSC | BNB | WBNB | 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c |
| Polygon | MATIC | WMATIC | 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270 |
| Avalanche | AVAX | WAVAX | 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7 |
| Arbitrum | ETH | WETH | 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 |
Wrapping process:
- The user sends native ETH to the WETH contract (via the
deposit()function or by sending directly) - The contract receives and holds the native ETH
- The contract mints an equal amount of WETH (ERC-20 token) to the user
- Result: ETH held by the contract = total circulating WETH supply
Unwrapping process:
- The user calls the WETH contract’s
withdraw()function - The contract burns the user’s WETH
- The contract sends an equal amount of native ETH back to the user
1 | // WETH contract core logic (simplified) |
1.4 Key Differences Summary Table
| Aspect | Native Token | ERC-20 Token |
|---|---|---|
| Storage Location | Protocol-level balance (balance field of each account) |
Smart contract internal mapping (mapping(address => uint256)) |
| Transfer Method | value field in the transaction |
Call the contract’s transfer() or transferFrom() function |
| Gas Payment | Yes (only native tokens can pay gas) | No (must use native tokens to pay gas) |
| Contract Address | None (built into the chain’s protocol layer) | Has its own contract address |
| Creation Method | Chain genesis or protocol consensus | Deploy a smart contract |
| Standard Interface | No unified standard | ERC-20 standard interface |
| Approval Mechanism | No approval needed (send directly) | Requires approve() before third-party usage |
| Examples | ETH, BNB, MATIC, AVAX | USDT, USDC, WETH, WBNB, UNI, CAKE |
2. Understanding Wei — The Smallest Unit
2.1 Denomination System
Just as the US dollar has "dollars" and "cents" as denominations, Ethereum has its own denomination system. Wei is the smallest denomination unit, like "cents" for the dollar — but the difference is that ETH has 18 decimal places, while the dollar only has 2.
Complete Ethereum denomination table:
| Unit | Wei Value | Scientific Notation | Practical Use |
|---|---|---|---|
| wei | 1 | 10^0 | Base unit for EVM internal operations |
| kwei (babbage) | 1,000 | 10^3 | Rarely used |
| mwei (lovelace) | 1,000,000 | 10^6 | Rarely used |
| gwei (shannon) | 1,000,000,000 | 10^9 | Standard unit for gas price |
| szabo | 1,000,000,000,000 | 10^12 | Historical unit, rarely used |
| finney | 1,000,000,000,000,000 | 10^15 | Historical unit, rarely used |
| ether | 1,000,000,000,000,000,000 | 10^18 | Human-readable standard unit |
Key Takeaway: Wei is to ETH what cents are to dollars — except with 18 decimal places instead of 2.
In daily use, you only need to remember three units: wei (EVM internal), gwei (gas price), ether (user interface).
2.2 Why Wei Is Needed
The EVM uses wei as the base unit not by arbitrary choice, but by technical necessity:
- The EVM does not support floating-point numbers: All arithmetic operations in the Ethereum Virtual Machine are integer operations (
uint256). There is no floating-point type, no decimal point. This is to guarantee determinism — floating-point operations on different hardware may produce different results, but integer operations are always consistent - 18 decimal places provide sufficient precision: 18 decimal places means you can represent precision down to 0.000000000000000001 ETH, which is crucial for micro-transactions and precise calculations in DeFi protocols
- All values are stored and computed in wei: The EVM has no concept of "ETH" internally, only wei. When a wallet displays "1 ETH," the EVM actually stores and processes
1,000,000,000,000,000,000wei (i.e.,1e18) - Avoiding precision loss: If floating-point numbers were used,
0.1 + 0.2might equal0.30000000000000004. In financial systems, such precision loss is unacceptable. Integer wei arithmetic is completely precise
1 | // EVM internal: all integer operations |
2.3 Common Conversions and Practical Examples
Basic conversion relationships:
1 | 1 ETH = 1,000,000,000 gwei = 1,000,000,000,000,000,000 wei |
Practical scenario examples:
| Scenario | ETH Value | Gwei Value | Wei Value |
|---|---|---|---|
| 1 ETH | 1 | 1,000,000,000 | 1,000,000,000,000,000,000 |
| One-thousandth of an ETH | 0.001 | 1,000,000 | 1,000,000,000,000,000 |
| Gas price 5 gwei | 0.000000005 | 5 | 5,000,000,000 |
| Gas price 30 gwei | 0.00000003 | 30 | 30,000,000,000 |
| Simple transfer fee (5 gwei) | 0.000105 | 105,000 | 105,000,000,000,000 |
Conversions in code:
1 | import { parseEther, formatEther, parseGwei, formatGwei } from 'viem'; |
2.4 ERC-20 Token Decimals Are Not Always 18
This is an extremely important point. Although ETH and most native tokens use 18 decimal places, the decimal count for ERC-20 tokens is defined by each token contract individually and varies.
Common tokens and their decimals:
| Token | Decimals | Smallest Unit Value for 1 Token | Notes |
|---|---|---|---|
| ETH (Native) | 18 | 1,000,000,000,000,000,000 | Standard 18 decimals |
| BNB (Native) | 18 | 1,000,000,000,000,000,000 | Standard 18 decimals |
| WETH | 18 | 1,000,000,000,000,000,000 | Same as ETH |
| UNI | 18 | 1,000,000,000,000,000,000 | Standard 18 decimals |
| LINK | 18 | 1,000,000,000,000,000,000 | Standard 18 decimals |
| DAI | 18 | 1,000,000,000,000,000,000 | Standard 18 decimals |
| USDT | 6 | 1,000,000 | Note: not 18! |
| USDC | 6 | 1,000,000 | Note: not 18! |
| WBTC | 8 | 100,000,000 | Note: not 18! |
Why do decimals differ?
- USDT/USDC use 6 decimals because they are pegged to the US dollar, and dollar precision typically goes to cents (2 decimals), so 6 decimals is more than sufficient
- WBTC uses 8 decimals because Bitcoin natively uses 8 decimals (1 BTC = 100,000,000 satoshis)
Code must handle different decimal places:
1 | // Wrong example: assuming all tokens have 18 decimals |
Critical Reminder: When writing code that deals with token amounts, always call the token contract’s
decimals()function to get the correct decimal count. Assuming 18 decimals is one of the most common mistakes in DeFi development.
3. Gas — The Unit of Computation
3.1 What Is Gas?
Gas is an abstract unit of measurement in the EVM, used to quantify the computational work required to execute a smart contract or transaction. Understanding this is crucial:
- Gas is not a token: You cannot "hold" gas, "transfer" gas, or see a gas balance in your wallet
- Gas is not a currency: Gas has no market price; you cannot buy or sell gas on an exchange
- Gas is not a denomination of ETH: Gas is not wei, not gwei, and not ether. They are entirely different measurement systems
- Gas measures computation: Think of it as "CPU cycles" or "computational steps" — it measures how much work the EVM needs to do to execute a given operation
Analogy:
Imagine you are shopping at a supermarket. Each item has a "weight" (in grams), and you are pushing a cart with a weight limit:
- Item weight (grams) is analogous to Gas units — measuring the "heft" of each operation
- Price per gram ($/gram) is analogous to Gas price (gwei) — the market-determined unit price
- Total cost ($) is analogous to Gas fee (ETH/BNB) — the actual amount you pay
- Cart weight limit is analogous to Gas limit — the maximum load you are willing to bear
Every EVM opcode has a fixed gas cost defined by the Ethereum protocol. These costs reflect the computational complexity and resource consumption of each operation.
3.2 Gas Cost per Operation
Below are the gas costs for common EVM opcodes. These values are defined by the Ethereum Yellow Paper and subsequent EIP upgrades:
| Operation | Gas Cost | Description |
|---|---|---|
| ADD / SUB | 3 | Simple arithmetic (addition, subtraction) |
| MUL / DIV | 5 | Multiplication, division |
| ADDMOD / MULMOD | 8 | Modular arithmetic |
| EXP | 10 + 50 x byte count | Exponentiation, cost increases with exponent size |
| SHA3 (KECCAK256) | 30 + 6 x word count | Hashing, used for mapping key computation, etc. |
| BALANCE | 2,600 | Query address balance (cold access after EIP-2929) |
| SLOAD | 2,100 | Read a 256-bit value from storage (cold access) |
| SLOAD (warm access) | 100 | Re-reading the same storage slot in the same transaction |
| SSTORE (new value) | 20,000 | Write a value to a previously zero storage slot — most expensive common operation |
| SSTORE (update) | 5,000 | Update an existing value in a storage slot |
| SSTORE (clear to zero) | 5,000 + refund | Set a storage slot to zero (eligible for gas refund) |
| LOG0 | 375 | Emit event with no indexed parameters |
| LOG1 | 750 | Emit event with 1 indexed parameter |
| LOG2 | 1,125 | Emit event with 2 indexed parameters |
| CALL | 2,600 | Call another contract (cold access) |
| CREATE | 32,000 | Deploy a new contract (excluding contract code gas) |
| CREATE2 | 32,000 | Deploy a new contract to a deterministic address |
| SELFDESTRUCT | 5,000 | Destroy a contract (deprecated) |
| PUSH0 | 2 | Added by EIP-3855: Push zero value, saves 1 gas over PUSH1 0x00 |
| TLOAD | 100 | Added by EIP-1153: Read transient storage (see Section 8.4) |
| TSTORE | 100 | Added by EIP-1153: Write transient storage |
| Base transaction | 21,000 | Minimum cost for every transaction |
| Transaction data (zero byte) | 4 / byte | Zero bytes in transaction calldata |
| Transaction data (non-zero byte) | 16 / byte | Non-zero bytes in transaction calldata |
Key Observation: Storage operations (SSTORE) are the most expensive. Writing a new storage slot (20,000 gas) costs nearly 7,000 times more than a simple addition (3 gas). This is why the core strategy for Solidity gas optimization is to minimize storage writes. The transient storage (TLOAD/TSTORE) introduced by EIP-1153 offers an alternative for temporary data within a transaction at only 100 gas per operation.
3.3 Gas Limit vs Actual Usage
This is one of the most commonly confused concepts among developers. Every transaction has two gas-related values:
Gas Limit:
- Set by the user (or dApp) before sending the transaction
- Represents "the maximum gas I am willing to spend on this transaction"
- Acts as a safety cap to prevent unexpectedly excessive gas consumption
- Wallets typically auto-estimate and set a reasonable value
Actual Usage (Gas Used):
- Can only be determined after the transaction finishes executing
- Represents the gas actually consumed by the transaction
- Always less than or equal to the gas limit
Three scenarios:
| Scenario | Result | Fee |
|---|---|---|
| Actual usage < Gas limit | Transaction succeeds, unused gas is refunded | Only pay for actual usage |
| Actual usage = Gas limit | Transaction succeeds (just barely) | Pay for the full gas limit |
| Actual usage > Gas limit | Transaction reverts | All gas is consumed, no refund, but state changes are rolled back |
Concrete example:
1 | Scenario: ERC-20 transfer, gas price 5 gwei |
Best Practice: Do not set the gas limit too low (the transaction will fail and you lose the gas fee), and do not set it excessively high (although the excess is refunded, some edge cases can cause unexpectedly high consumption). Most wallets’ auto-estimates add a safety buffer on top of the actual requirement (typically 20-30%).
3.4 Why Gas Is Needed
The gas mechanism is not an optional design — it solves fundamental problems facing blockchains:
1. The Halting Problem
The EVM is a Turing-complete virtual machine, meaning it can execute arbitrarily complex programs — including infinite loops. In computation theory, it is impossible to determine in advance whether an arbitrary program will terminate (this is the "Halting Problem").
The gas mechanism elegantly solves this: every operation consumes gas, and the gas limit caps the total execution. No matter how complex a program is, execution must stop when gas runs out.
1 | // Without gas mechanism, this contract runs forever |
2. Preventing Resource Abuse
Every validator node in the network must execute the code in transactions. Without an execution cost, attackers could flood the network with computationally intensive transactions to paralyze it (DoS attack). Gas fees make such attacks economically infeasible.
3. Block Space Market
Each block has a gas cap (currently about 36 million gas on Ethereum, increased to 36 million after the Pectra upgrade). When the network is busy, users compete for limited block space. The gas price mechanism creates an efficient market: transactions willing to pay a higher gas price are processed first.
4. Incentivizing Validators
Validators (or miners) consume real computational resources to execute transactions. Gas fees compensate their costs and provide profit incentives, ensuring the network continues to operate.
3.5 Typical Gas Usage by Transaction Type
The following data is based on approximate on-chain statistics to help you estimate the cost of various operations:
| Transaction Type | Typical Gas Usage | At 5 gwei (BSC) | At 30 gwei (ETH) |
|---|---|---|---|
| Simple ETH/BNB transfer | 21,000 | 0.000105 BNB | 0.00063 ETH |
| ERC-20 token transfer | ~65,000 | 0.000325 BNB | 0.00195 ETH |
| ERC-20 approve | ~46,000 | 0.00023 BNB | 0.00138 ETH |
| DEX swap (simple path) | ~150,000 | 0.00075 BNB | 0.0045 ETH |
| DEX swap (multi-hop path) | ~300,000 | 0.0015 BNB | 0.009 ETH |
| Add liquidity | ~200,000-300,000 | 0.001-0.0015 BNB | 0.006-0.009 ETH |
| Remove liquidity | ~150,000-250,000 | 0.00075-0.00125 BNB | 0.0045-0.0075 ETH |
| NFT mint (single) | ~100,000-150,000 | 0.0005-0.00075 BNB | 0.003-0.0045 ETH |
| NFT batch mint | ~150,000-500,000 | 0.00075-0.0025 BNB | 0.0045-0.015 ETH |
| ERC-20 contract deployment | ~1,000,000-2,000,000 | 0.005-0.01 BNB | 0.03-0.06 ETH |
| Complex contract deployment | ~3,000,000-5,000,000 | 0.015-0.025 BNB | 0.09-0.15 ETH |
Note: The fees above are denominated in native tokens. The actual dollar cost depends on the native token’s market price. Transactions on BSC are typically 10-100x cheaper than on Ethereum, which is one reason many projects choose BSC or Layer 2.
4. Transaction Fees — Putting It All Together
Now that we understand gas (computation unit) and wei (token denomination), let’s see how they combine to form actual transaction fees.
4.1 Legacy Fee Model (Pre-EIP-1559)
Before Ethereum’s London Upgrade (EIP-1559) in 2021, and in the model still used by chains like BSC, fee calculation is straightforward:
1 | Transaction Fee = Actual Gas Used x Gas Price |
- Actual Gas Used: In gas units (pure number, no denomination)
- Gas Price: In gwei (set by user or suggested by wallet)
- Transaction Fee: In native token (ETH, BNB, etc.)
Full calculation example:
1 | Scenario: A DEX swap on BSC |
In this model, users set a gas price, and miners prioritize higher-bidding transactions. This led to a problem: during network congestion, users had to keep raising their bids to ensure their transactions were included, causing gas prices to fluctuate wildly and become unpredictable.
4.2 EIP-1559 Fee Model (Post-London Upgrade)
Ethereum introduced EIP-1559 in the August 2021 London Upgrade, fundamentally changing the fee mechanism. This model introduces two core concepts:
1 | Transaction Fee = Actual Gas Used x (Base Fee + Priority Fee) |
Base Fee:
- Automatically calculated by the protocol based on the previous block’s utilization rate; users cannot set it
- If the previous block was more than 50% full, the base fee increases (up to 12.5%); below 50% full, the base fee decreases
- The base fee is burned: Permanently removed from the ETH total supply, given to no one. This makes ETH potentially deflationary during periods of high usage
- Makes gas prices more predictable — users can see the current base fee and reasonably estimate the next block’s fee
Priority Fee / Tip:
- Set by the user
- Paid to the validator (not burned)
- Incentivizes validators to include your transaction in a block
- When the network is not busy, a small priority fee (e.g., 1-2 gwei) suffices
Max Fee (maxFeePerGas):
- The maximum total fee per gas unit the user is willing to pay
- Must be greater than or equal to Base Fee + Priority Fee
- If the max fee > actual cost (base fee + priority fee), the excess is refunded
Full calculation example:
1 | Scenario: A DEX swap on Ethereum |
4.3 BSC Fee Model
BSC (BNB Smart Chain) uses a simplified fee model close to the legacy model, but with its own characteristics:
- Extremely low gas price: BSC’s typical gas price is 3-5 gwei, while Ethereum typically runs at 20-50 gwei or higher
- Short block time: BSC produces a block approximately every 3 seconds (Ethereum ~12 seconds); faster blocks mean more block space supply
- Basic formula:
Fee = Actual Gas Used x Gas Price - BNB token price is much lower than ETH: Even with the same gas units, the dollar cost of BNB-denominated fees is lower
1 | BSC Example: Deploy a token contract |
This is why many developers and users choose to deploy and interact on BSC — the cost difference can be 30x or more.
4.4 Cross-Chain Fee Comparison
The following comparison shows typical fee levels across different EVM chains. Note that gas prices and token prices fluctuate; the values below are approximate references for 2025:
| Chain | Typical Gas Price | Simple Transfer Cost (Native Token) | Simple Transfer Cost (USD Approx.) | DEX Swap Cost (USD Approx.) |
|---|---|---|---|---|
| Ethereum | 20-50 gwei | 0.00042-0.00105 ETH | $0.50-$2.00 | $5-$30 |
| BSC | 3-5 gwei | 0.000063-0.000105 BNB | $0.01-$0.02 | $0.10-$0.30 |
| Polygon | 30-50 gwei | 0.00063-0.00105 MATIC | $0.001-$0.005 | $0.01-$0.05 |
| Arbitrum | 0.1-0.5 gwei | 0.0000021-0.0000105 ETH | $0.01-$0.05 | $0.10-$0.50 |
| Optimism | 0.01-0.1 gwei | 0.00000021-0.0000021 ETH | $0.001-$0.01 | $0.01-$0.10 |
| Base | 0.01-0.05 gwei | 0.00000021-0.00000105 ETH | $0.001-$0.01 | $0.01-$0.10 |
| Avalanche C-Chain | 25-30 gwei | 0.000525-0.00063 AVAX | $0.01-$0.03 | $0.10-$0.30 |
Note: Layer 2 chains (Arbitrum, Optimism, Base) have extremely low gas prices, but they also have additional L1 data posting fees (the cost of submitting transaction data to the Ethereum mainnet). The USD approximations in the table above include this component. Since the implementation of EIP-4844 (Dencun Upgrade), L2 data posting fees have dropped by approximately 90%.
5. Three Meanings of "Gas" — A Common Source of Confusion
This is possibly the most important section of this guide. In everyday conversation, documentation, and even code comments, the word "gas" is often used loosely, but it can actually refer to three entirely different meanings. Confusing them is one of the most common sources of errors in EVM development.
5.1 Terminology Disambiguation
| Term | Actual Meaning | Unit | Order of Magnitude | Example |
|---|---|---|---|---|
| Gas (units / gas units) | Computation budget / workload measurement | Abstract dimensionless unit | Tens of thousands to millions | "This transaction used 200,000 gas" |
| Gas price | Cost per gas unit | gwei (= 10^9 wei) | Single digits to hundreds | "The current gas price is 5 gwei" |
| Gas fee | Actual total cost in native token | ETH / BNB / MATIC | Decimal values | "I paid 0.001 BNB in gas fees" |
Mathematical relationship between the three:
1 | Gas fee (ETH/BNB) = Gas units x Gas price (gwei) x 10^-9 |
Common confusion scenarios:
1 | "I set 200,000 gas" |
5.2 Real-World Analogy
Use the analogy of filling up a car with fuel to understand these three concepts:
| Filling Up a Car | EVM Gas | Relationship |
|---|---|---|
| Distance traveled (km) | Gas units | How long your trip is / how complex the computation is |
| Fuel price ($/liter) | Gas price (gwei) | Market-determined unit price |
| Fuel consumption (liters/100km) | Gas cost per operation | Fixed consumption rate |
| Total fuel cost ($) | Gas fee (ETH/BNB) | The actual amount you pay from your wallet |
| Fuel tank capacity (liters) | Gas limit | The maximum consumption you are willing to bear |
Extended analogy:
1 | "I set a gas limit of 200,000 gas" |
Core Takeaway: When you see or set a gas-related value, first confirm which meaning it represents (units? price? fee?). 200,000 gas units, 200,000 gwei, and 200,000 wei are completely different orders of magnitude.
6. LayerZero Cross-Chain Gas — Enforced Options Context
Cross-chain communication adds a new layer of complexity to the gas concept. In the LayerZero protocol, a single cross-chain transaction involves execution on two chains, while the user only pays fees on the source chain. Understanding this mechanism is critical for correctly configuring NativeOFT and cross-chain swaps.
6.1 Why Cross-Chain Requires Gas Limits
When NativeOFT (Native OFT tokens) sends a cross-chain message via LayerZero, the entire flow is as follows:
- Source chain: User calls
send()orinitiateSwap()→ consumes source chain gas → emits a LayerZero message - LayerZero network: Security verification layer (DVN) verifies the message
- Destination chain: LayerZero Executor calls the destination contract → consumes destination chain gas
The key question: Who pays for the gas on the destination chain?
The answer is: The source chain user pays in advance. The LZ fee paid by the user on the source chain includes the gas cost for destination chain execution. The LayerZero Executor uses these prepaid fees to execute transactions on the destination chain.
The purpose of setEnforcedOptions is to tell the LayerZero protocol: "When executing my contract code on the destination chain, at least allocate X gas units." This ensures sufficient gas on the destination chain to complete the operation, preventing cross-chain transactions from failing due to insufficient gas.
6.2 What the Numbers Mean
Let’s break down the gas limit values in a cross-chain swap:
1 | Enforced Options configuration example: |
Important Distinction:
200,000and500,000are gas units (abstract computation amount), not wei or gwei. They tell the LayerZero Executor "allocate at least this much computation budget for destination chain operations." The actual fee (in destination chain native token) depends on the destination chain’s gas price at the time.
6.3 How LayerZero Fees Work
The msg.value the user pays on the source chain when sending a cross-chain transaction includes multiple components:
1 | msg.value composition when user pays on source chain: |
Relationship between Enforced Options and quoteSend():
1 | 1. Contract admin calls setEnforcedOptions() |
6.4 Practical Example: BSC Testnet to Sepolia Cross-Chain Swap
Below is a full fee breakdown of a cross-chain swap transaction, helping you understand how all the parts come together:
1 | Scenario: Cross-chain swap from BSC testnet to Sepolia testnet |
7. Quick Reference Cheat Sheet
Conversion Formulas
1 | ================================================= |
Common Value Reference
1 | ================================================= |
ERC-20 Approval Flow
Code Examples (viem/ethers.js v6)
1 | import { parseEther, parseGwei, formatEther, formatGwei, parseUnits, formatUnits } from 'viem'; |
8. The Modern Gas Landscape (2025)
The Ethereum ecosystem underwent several major protocol upgrades in 2024-2025 that profoundly changed the gas fee landscape. This chapter covers the latest developments as of 2025.
8.1 EIP-4844: Proto-Danksharding and Blob Transactions
Background
EIP-4844 (also known as Proto-Danksharding) was introduced to the Ethereum mainnet in the March 2024 Dencun Upgrade. It introduced a brand new transaction type — Type 3 (blob transactions), designed specifically for Layer 2 Rollup data publishing scenarios.
Core Mechanism
Before EIP-4844, L2 Rollups (such as Arbitrum, Optimism, Base) needed to publish transaction data as calldata to the Ethereum mainnet, which was extremely expensive because calldata is permanently stored on-chain.
EIP-4844 introduced blobs (Binary Large Objects) — a form of temporary data storage. Blob data is processed by the consensus layer and automatically pruned after approximately 18 days, without permanently occupying on-chain space.
1 | Before EIP-4844 (L2 data publishing): |
Blob Gas Market
Blobs have their own independent fee market that runs in parallel with the EIP-1559 regular gas market:
- Each block can contain a maximum of 6 blobs (target of 3)
- Each blob is 128 KB in size
- Blob gas has its own independent base fee, with an adjustment mechanism similar to EIP-1559
- When blob space utilization exceeds the target, the blob gas price rises; otherwise it falls
1 | // Using viem to send blob transactions |
Impact on Developers
- L2 fees dropped dramatically: If your dApp is deployed on L2, user experience improves significantly
- L2-first strategy is even more justified: L2’s cost advantage has widened further
- New gas estimation dimension: Need to consider both execution gas and blob gas
8.2 Account Abstraction (ERC-4337) and Gas Sponsorship
Gas Pain Points of Traditional EOAs
In the traditional model, only EOAs (Externally Owned Accounts, i.e., regular accounts controlled by private keys) can initiate transactions, and they must hold native tokens to pay gas. This creates severe UX issues:
- New users need to acquire native tokens before they can do anything
- Users holding ERC-20 tokens but no ETH cannot transfer
- Each chain requires independently prepared gas funds
ERC-4337 Account Abstraction
ERC-4337 introduced an account abstraction scheme that requires no protocol-level modifications, changing the gas payment model through the following core components:
1 | ERC-4337 core components: |
Code Example: Using a Paymaster to Sponsor Gas
1 | // Construct a UserOperation sponsored by Paymaster |
Impact on the Gas Landscape
| Aspect | Traditional EOA | ERC-4337 Smart Account |
|---|---|---|
| Gas Payer | Must be the transaction initiator | Can be a third-party Paymaster |
| Payment Token | Native token only | Can be ERC-20 (via Paymaster) |
| New User Experience | Must acquire ETH/BNB first | Can onboard with zero gas |
| Batch Operations | Each transaction pays gas separately | Can batch-bundle, amortizing gas cost |
8.3 Pectra Upgrade and EIP-7702
Pectra Upgrade Overview (2025)
Pectra is Ethereum’s major upgrade planned for 2025, merging improvements from Prague (execution layer) and Electra (consensus layer). Key impacts on gas include:
- Block gas limit increase: From approximately 30 million to 36 million, adding about 20% more block space
- Blob count increase: Target blobs per block increased from 3 to 6, maximum from 6 to 9
- EIP-7702: Introduces temporary smart contract capabilities for EOAs
EIP-7702: Smart EOAs
EIP-7702 allows an EOA to temporarily "delegate" to a smart contract’s code within a single transaction. This means ordinary EOA wallets can gain some benefits of account abstraction without migrating to a smart contract wallet.
1 | EIP-7702 how it works: |
1 | // EIP-7702 example: EOA temporarily delegates to batch execution contract |
8.4 Modern Gas-Optimized Opcodes
EIP-1153: Transient Storage
The TLOAD and TSTORE opcodes introduced in the Dencun Upgrade provide temporary storage within the same transaction, automatically cleared when the transaction ends.
1 | // Traditional approach: use SSTORE for reentrancy lock |
EIP-3855: PUSH0 Opcode
The Shanghai Upgrade introduced PUSH0, specifically for pushing a zero value onto the stack. Previously, PUSH1 0x00 (3 gas) was required; now PUSH0 (2 gas) suffices.
1 | // PUSH0 automatically used by Solidity 0.8.20+ |
8.5 Flashbots, MEV, and Gas
How MEV (Maximal Extractable Value) Affects Gas
MEV is the ability of validators/searchers to extract additional profit by reordering, inserting, or censoring transactions. MEV directly affects the gas market:
1 | Relationship between MEV and Gas: |
Flashbots and MEV Protection
Flashbots is one of the most important MEV infrastructure projects in the Ethereum ecosystem. It provides MEV protection and more efficient block space auctions:
1 | // Send private transaction via Flashbots (avoid sandwich attacks) |
8.6 Access Lists (EIP-2930)
EIP-2930 introduced Access Lists, allowing transactions to pre-declare the storage slots and contract addresses they will access. This can reduce the gas cost of cold access.
1 | Access List gas savings principle: |
1 | // Using viem to create transaction with Access List |
9. Developer Gas Optimization Practices
This chapter provides practical Solidity gas optimization tips, with quantitative gas savings analysis for each technique.
9.1 Storage Optimization
1. Variable Packing (Storage Packing)
EVM storage is organized in 32-byte (256-bit) slots. If multiple small variables can fit into the same slot, only one SSTORE/SLOAD operation is needed.
1 | // Bad: each variable occupies independent storage slot (3 slots = 3 SSTORE operations) |
2. Using immutable and constant
1 | // constant: determined at compile time, embedded in bytecode (no storage slot) |
3. Using mappings instead of arrays for lookups
1 | // Bad: iterate array to search — O(n) complexity, gas grows with array length |
9.2 Calldata and Memory Optimization
1. Using calldata instead of memory for read-only external function parameters
1 | // Bad: memory copies data to memory (extra gas) |
2. Shorter revert messages or custom errors
1 | // Bad: long string revert messages consume lots of calldata and deployment bytecode |
9.3 Loops and Batch Operations
1. Cache storage variables locally
1 | // Bad: read storage variable every loop iteration |
2. unchecked blocks for provably safe arithmetic
1 | // Solidity 0.8+ has overflow check enabled by default (approximately 30 extra gas per arithmetic operation) |
9.4 Compiler and Deployment Optimization
1. Solidity Optimizer Settings
1 | // Optimizer config in hardhat.config.js / foundry.toml |
2. Using proxy patterns to reduce deployment cost
1 | // When need to deploy many contracts with same logic (e.g., factory pattern) |
10. Common Pitfalls and Debugging
10.1 Gas Estimation Failures
Scenario 1: eth_estimateGas returns an error
1 | // Problem: gas estimation failure usually means transaction will revert |
Scenario 2: Gas estimation returns an abnormally high value
1 | // Problem: estimation returns 30,000,000 gas (close to block limit) |
10.2 Stuck Transactions and Replacement
Transaction stuck in mempool
1 | // Transaction stuck usually because gas price too low or nonce issue |
Nonce gap issue
1 | // Problem: nonce 3 transaction fails, but nonce 4, 5 have already been sent |
10.3 Contract Interaction Pitfalls
Pitfall 1: Forgetting to check existing allowance before approve
1 | // Problem: some tokens (like USDT) don't allow approve from non-zero value to another non-zero value |
Pitfall 2: Setting maxFeePerGas too low in EIP-1559 transactions
1 | // Problem: baseFee may rise between when you send transaction and when it's included |
Pitfall 3: Ignoring L1 data fees on L2
1 | // Problem: on Arbitrum/Optimism/Base, transaction fees consist of two parts: |
Transaction Lifecycle
References
Core Specifications
- Ethereum Yellow Paper — Gas Costs — The authoritative specification for EVM opcodes and their gas costs
- EIP-1559 Specification — Complete specification for base fee, priority fee, and fee burn mechanism
- EIP-4844 Specification — Proto-Danksharding and blob transaction specification
- EIP-7702 Specification — Temporary smart contract code delegation for EOAs
- ERC-4337 Specification — Account abstraction without protocol-level modifications
- EIP-2929 Specification — Gas cost increases for state access opcodes (cold/warm access)
- EIP-2930 Specification — Access Lists transaction type
- EIP-1153 Specification — Transient storage opcodes (TLOAD/TSTORE)
- EIP-3855 Specification — PUSH0 opcode
Developer Resources
- ERC-20 Standard — Complete specification of the ERC-20 token standard
- LayerZero V2 Documentation — Enforced Options — Official guide for LayerZero cross-chain gas configuration
- Solidity Documentation — Gas Optimization — How the Solidity compiler optimizer works
- viem Documentation — Utility Functions — Usage guide for
parseEther,formatEther, and other utility functions - Flashbots Documentation — MEV protection and the Flashbots ecosystem
- Pimlico Documentation — ERC-4337 Bundler and Paymaster infrastructure
Tools
- Etherscan Gas Tracker — Real-time Ethereum gas price monitoring
- ultrasound.money — ETH supply and EIP-1559 burn statistics
- L2Fees.info — Real-time Layer 2 fee comparison
- evm.codes — EVM opcode reference and gas cost lookup