Tutoriel·7 min de lecture·Par Solingo

Understanding Gas in Ethereum — How It Actually Works

Gas price, gas limit, base fee, priority fee, EIP-1559 — demystify Ethereum gas once and for all.

# Understanding Gas in Ethereum — How It Actually Works

Gas confuses every beginner. "Why did I pay $50 for a failed transaction?" "What's the difference between gas price and gas limit?" This guide explains Ethereum gas from first principles.

What is Gas?

Gas is the computational effort required to execute operations on Ethereum.

Think of it like gasoline for your car:

  • Gas units = liters of gasoline
  • Gas price = price per liter
  • Total cost = units × price

In Ethereum:

  • Gas units = computational steps
  • Gas price = ETH per unit
  • Total cost = gas used × gas price

Why Does Gas Exist?

Two reasons:

1. Prevent Spam

Without gas, someone could deploy this:

contract InfiniteLoop {

function attack() public {

while (true) {} // Would freeze the network forever

}

}

Gas limits execution time. When gas runs out, execution stops.

2. Compensate Validators

Validators include your transaction in a block. They deserve payment for:

  • Running the computation
  • Storing state changes
  • Bandwidth costs

Gas Units vs ETH

Gas units measure computational work. They're the same regardless of ETH price.

Example operations:

| Operation | Gas Cost |

|-----------|----------|

| Addition (a + b) | 3 |

| Multiplication | 5 |

| SSTORE (write to storage) | 20,000 (cold) / 5,000 (warm) |

| SLOAD (read from storage) | 2,100 (cold) / 100 (warm) |

| Transfer ETH | 21,000 |

| Deploy contract | 32,000 + code size |

A simple transfer() uses ~21,000 gas. A complex DeFi swap might use 200,000 gas.

EIP-1559: The London Upgrade (2021)

Before EIP-1559, you set one gas price. Now there are TWO components:

Total Fee = (Base Fee + Priority Fee) × Gas Used

Base Fee

  • Determined by network demand, not users
  • Burned (removed from circulation)
  • Adjusts every block based on congestion:

- Block > 50% full → base fee increases 12.5%

- Block < 50% full → base fee decreases 12.5%

Currently ~10-50 gwei depending on congestion.

Priority Fee (Tip)

  • Set by users to incentivize validators
  • Paid to validators (not burned)
  • Higher tip = faster inclusion

Typically 1-2 gwei in normal times.

Gas Limit vs Gas Used

Gas Limit

The maximum gas you authorize.

// You set: Gas Limit = 100,000

// Actual execution uses: 67,000

// You pay for: 67,000 (not 100,000)

// Refund: 33,000 worth of gas

If execution needs 120,000 but your limit is 100,000:

  • Transaction fails (reverts)
  • You still pay for the 100,000 gas attempted
  • 🔥 This is why failed transactions cost money

Best practice: Set limit 20-50% higher than estimate.

Gas Used

The actual amount consumed.

function transfer(address to, uint256 amount) external {

balances[msg.sender] -= amount; // SSTORE: 5,000 gas

balances[to] += amount; // SSTORE: 20,000 gas

// Total: ~25,000 + overhead

}

You only pay for gas actually used (up to your limit).

Calculating Transaction Cost

Before EIP-1559 (Legacy)

Cost = Gas Used × Gas Price

Example:

100,000 gas × 50 gwei = 5,000,000 gwei = 0.005 ETH

After EIP-1559

Max Fee Per Gas = Base Fee + Max Priority Fee

Cost = Gas Used × (Base Fee + Priority Fee)

Example:

Base Fee: 30 gwei

Priority Fee: 2 gwei

Gas Used: 100,000

Cost = 100,000 × 32 gwei = 3,200,000 gwei = 0.0032 ETH

Setting Fees in Wallets

You specify:

  • Max Fee Per Gas: Absolute maximum you'll pay (e.g., 100 gwei)
  • Max Priority Fee: Maximum tip to validator (e.g., 2 gwei)

If base fee is 30 gwei and you set max fee 100 gwei:

  • Actual fee = 30 + 2 = 32 gwei
  • You save 68 gwei per gas unit
  • Wallet refunds the difference

Block Gas Limit

Each block has a maximum total gas (currently 30 million).

Block Gas Limit: 30,000,000

Average Transaction: 100,000 gas

Transactions per block: ~300

If demand exceeds block space → base fee increases → fewer transactions → congestion clears.

Common Operation Costs

Storage Operations (Most Expensive)

contract Storage {

uint256 public value; // First write: 20,000 gas

function set(uint256 newValue) external {

value = newValue; // Update: 5,000 gas

}

function get() external view returns (uint256) {

return value; // Read: 2,100 gas (first time), 100 gas (subsequent)

}

}

Cold access (first time in a transaction): expensive

Warm access (subsequent times): cheap

ERC-20 Transfer

function transfer(address to, uint256 amount) external {

// 2 SSTORE operations + overhead

// Total: ~45,000-65,000 gas

}

Uniswap Swap

router.swapExactTokensForTokens(...);

// Multiple contracts, complex math, storage updates

// Total: ~150,000-250,000 gas

NFT Mint

nft.mint();

// Create new token, update mappings, emit event

// Total: ~50,000-150,000 gas

How to Estimate Gas

Method 1: Wallet Simulation

Wallets (MetaMask, Rainbow) simulate the transaction and estimate gas.

Method 2: eth_estimateGas RPC

const provider = new ethers.JsonRpcProvider("https://...");

const gasEstimate = await provider.estimateGas({

to: contractAddress,

data: encodedFunctionCall,

from: userAddress,

});

console.log(Estimated gas: ${gasEstimate});

Method 3: Foundry Gas Reports

forge test --gas-report
| Function  | Gas     |

|-----------|---------|

| mint | 51,234 |

| transfer | 34,567 |

How to Save Gas

1. Use calldata Instead of memory

// ❌ Expensive

function process(uint256[] memory data) external {

// Copies to memory: costs gas

}

// ✅ Cheap

function process(uint256[] calldata data) external {

// Reads directly from transaction data

}

Savings: ~50 gas per array element.

2. Pack Storage Variables

// ❌ Uses 3 storage slots (3 × 20,000 gas)

contract Inefficient {

uint128 a;

uint256 b;

uint128 c;

}

// ✅ Uses 2 storage slots (2 × 20,000 gas)

contract Efficient {

uint128 a;

uint128 c;

uint256 b;

}

Each slot is 32 bytes. Pack small variables together.

3. Use Events Instead of Storage

// ❌ Storage: 20,000 gas

mapping(uint256 => string) public messages;

function log(uint256 id, string memory message) external {

messages[id] = message;

}

// ✅ Events: ~375 gas

event Message(uint256 indexed id, string message);

function log(uint256 id, string memory message) external {

emit Message(id, message);

}

Use events for data you don't need to query on-chain.

4. Batch Operations

// ❌ Multiple transactions

token.transfer(user1, 100);

token.transfer(user2, 100);

token.transfer(user3, 100);

// 3 × 21,000 base cost = 63,000 gas wasted

// ✅ Single transaction

token.batchTransfer([user1, user2, user3], [100, 100, 100]);

// 1 × 21,000 base cost

5. Use unchecked for Safe Math

// ❌ Overflow checks on every operation

for (uint i = 0; i < 1000; i++) {

// i++ includes overflow check

}

// ✅ Skip checks when overflow impossible

for (uint i = 0; i < 1000;) {

// ... logic

unchecked { i++; }

}

Savings: ~20 gas per operation.

6. Short-Circuit Conditionals

// ❌ Evaluates both conditions

if (expensiveCheck() && cheapCheck()) {}

// ✅ Short-circuits if first is false

if (cheapCheck() && expensiveCheck()) {}

maxFeePerGas vs maxPriorityFeePerGas

When sending a transaction:

await contract.mint({

maxFeePerGas: ethers.parseUnits("100", "gwei"), // Max total

maxPriorityFeePerGas: ethers.parseUnits("2", "gwei"), // Max tip

});

Scenario 1: Normal Congestion

Base Fee: 30 gwei

Your Max Fee: 100 gwei

Your Max Priority: 2 gwei

Actual Fee Paid: 30 + 2 = 32 gwei

Refund: 68 gwei per gas unit

Scenario 2: High Congestion

Base Fee: 95 gwei

Your Max Fee: 100 gwei

Your Max Priority: 2 gwei

Actual Fee Paid: 95 + 2 = 97 gwei

Refund: 3 gwei per gas unit

Scenario 3: Extreme Congestion

Base Fee: 120 gwei

Your Max Fee: 100 gwei

Result: Transaction NOT included (max fee too low)

Gas Tokens (Deprecated)

Before EIP-1559, "gas tokens" (CHI, GST2) exploited storage refunds to save gas. They're obsolete now.

Layer 2 Solutions

L2s (Arbitrum, Optimism, Base) reduce gas by 10-100x:

| Network | Transfer Cost |

|---------|---------------|

| Ethereum | 0.001 ETH ($3) |

| Arbitrum | 0.0001 ETH ($0.30) |

| Optimism | 0.0001 ETH ($0.30) |

| Base | 0.00005 ETH ($0.15) |

Same code, cheaper execution.

Common Questions

"Why did my failed transaction cost gas?"

Validators still executed your code (until it failed). They deserve payment for that work.

"Why is gas so high right now?"

High demand → blocks full → base fee increases. Check etherscan.io/gastracker for current prices.

"Should I set max fee very high?"

No need. You only pay baseFee + priorityFee, excess is refunded. But set it high enough to cover potential base fee increases.

"How do I get instant inclusion?"

Set a high priority fee (5-10 gwei). Validators prioritize high tips.

Summary

  • Gas units = computational work (constant)
  • Gas price = ETH cost per unit (variable)
  • Base fee = burned, adjusts with congestion
  • Priority fee = tip to validators
  • Gas limit = max you authorize (you're refunded unused)
  • Gas used = actual amount consumed

Pro tip: Use gwei.io or ultrasound.money to check current gas prices before transacting.

Next: Learn gas optimization techniques to write efficient smart contracts!

Prêt à mettre en pratique ?

Applique ces concepts avec des exercices interactifs sur Solingo.

Commencer gratuitement