# Gas Repricing Evaluation
## Summary
[EIP-7904](https://eips.ethereum.org/EIPS/eip-7904), proposed in Glamsterdam, introduces a set of EIPs aiming to update gas costs with actual computational overhead for each opcode.
This doc provides a preliminary analysis on the EELS + EEST repo (After the Weld), to explore how we can simplify and accelerate the gas repricing process for faster iteration.
## Problems
- Some EEST test cases have not yet supported the Osaka fork for eip-7825
- The existing benchmark test cases hard-code gas costs, which will break whenever related constants are updated.
- There are currently two separate data sources for gas information, eels and eest both maintain their own gas tables.
## Goals
- Refactor all benchmark test to support eip7825.
- Remove hard-coded gas costs in benchmark tests to enable faster and safer updates.
- Unify gas constants into a single source of truth.
## Evaluation
### 1. Failing Benchmark Tests due to EIP7825
Related issue: https://github.com/ethereum/execution-spec-tests/pull/2160
### 2. Hard-coded Gas Cost in Benchmark Tests
Computation Tests:
- test_block_full_access_list_and_data: `G_ACCESS_LIST_ADDRESS`, `G_ACCESS_LIST_STORAGE`
- test_worst_case_auth_block: `G_AUTHORIZATION`, `R_AUTHORIZATION_EXISTING_AUTHORITY`
- `test_worst_bytecode_single_opcode`, `test_worst_creates_collisions`: opcode costs
- `test_worst_keccak`, `test_worst_precompile_only_data_input`, `test_amortized_bn128_pairings`: opcode costs
- `test_worst_stateful_opcodes`: stateful opcode cost aggregation
Stateful Tests:
- General Refactoring for bloatnet tests required
Proposed solution: https://github.com/ethereum/execution-specs/issues/1479
---
### 3. Single-Source Data for Gas Constants
**Execution Spec Gas Module**
- Location: `src/ethereum/forks/{fork}/vm/gas.py`
- Data Types: `Uint`, `U64`, `U256`
**Test Framework Gas Module**
- Location: `src/ethereum_spec_tests/ethereum_test_forks/gas_costs.py`
- Data Types: `int`
#### Data Structure Comparison
**Execution Spec Module Structure**
```python
# Constants
GAS_JUMPDEST = Uint(1)
GAS_BASE = Uint(2)
# Data Classes
@dataclass
class ExtendMemory:
cost: Uint
expand_by: Uint
@dataclass
class MessageCallGas:
cost: Uint
sub_call: Uint
# Calculation Functions
def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint
def calculate_gas_extend_memory(...) -> ExtendMemory
def calculate_message_call_gas(...) -> MessageCallGas
def calculate_excess_blob_gas(...) -> U64
```
**Test Framework Module Structure**
```python
@dataclass(kw_only=True, frozen=True)
class GasCosts:
# Core opcodes
G_JUMPDEST: int
G_BASE: int
G_VERY_LOW: int
G_LOW: int
G_MID: int
G_HIGH: int
# Storage operations
G_WARM_ACCOUNT_ACCESS: int
G_COLD_ACCOUNT_ACCESS: int
G_ACCESS_LIST_ADDRESS: int
G_ACCESS_LIST_STORAGE: int
...
```
Gas Constants Mapping
### Direct Mappings
| Execution Spec | Test Framework | Value | Description |
|----------------|----------------|-------|-------------|
| `GAS_JUMPDEST` | `G_JUMPDEST` | 1 | Jump destination opcode |
| `GAS_BASE` | `G_BASE` | 2 | Base operation cost |
| `GAS_VERY_LOW` | `G_VERY_LOW` | 3 | Very low cost operations |
| `GAS_LOW` | `G_LOW` | 5 | Low cost operations |
| `GAS_MID` | `G_MID` | 8 | Medium cost operations |
| `GAS_HIGH` | `G_HIGH` | 10 | High cost operations |
| `GAS_MEMORY` | `G_MEMORY` | 3 | Memory allocation cost |
| `GAS_CREATE` | `G_CREATE` | 32000 | Contract creation cost |
| `GAS_CODE_DEPOSIT` | `G_CODE_DEPOSIT_BYTE` | 200 | Code deposit per byte |
| `GAS_CALL_VALUE` | `G_CALL_VALUE` | 9000 | Value transfer cost |
| `GAS_CALL_STIPEND` | `G_CALL_STIPEND` | 2300 | Call stipend |
| `GAS_NEW_ACCOUNT` | `G_NEW_ACCOUNT` | 25000 | New account creation |
| `GAS_SELF_DESTRUCT` | `G_SELF_DESTRUCT` | 5000 | Self-destruct cost |
| `GAS_LOG` | `G_LOG` | 375 | Log operation cost |
| `GAS_LOG_DATA` | `G_LOG_DATA` | 8 | Log data cost per byte |
| `GAS_LOG_TOPIC` | `G_LOG_TOPIC` | 375 | Log topic cost |
| `GAS_KECCAK256` | `G_KECCAK_256` | 30 | Keccak256 base cost |
| `GAS_KECCAK256_WORD` | `G_KECCAK_256_WORD` | 6 | Keccak256 per word |
| `GAS_COPY` | `G_COPY` | 3 | Copy operation cost |
| `GAS_BLOCK_HASH` | `G_BLOCKHASH` | 20 | Block hash cost |
**Storage Operations Mapping**
| Execution Spec | Test Framework | Value | Description |
|----------------|----------------|-------|-------------|
| `GAS_STORAGE_SET` | `G_STORAGE_SET` | 20000 | Storage slot set cost |
| `GAS_STORAGE_UPDATE` | `G_STORAGE_RESET` | 5000 | Storage slot update cost |
| `GAS_STORAGE_CLEAR_REFUND` | `R_STORAGE_CLEAR` | 4800 | Storage clear refund |
| `GAS_COLD_SLOAD` | `G_COLD_SLOAD` | 2100 | Cold storage load |
| `GAS_WARM_ACCESS` | `G_WARM_ACCOUNT_ACCESS` | 100 | Warm account access |
| `GAS_COLD_ACCOUNT_ACCESS` | `G_COLD_ACCOUNT_ACCESS` | 2600 | Cold account access |
**Exponentiation Mapping**
| Execution Spec | Test Framework | Value | Description |
|----------------|----------------|-------|-------------|
| `GAS_EXPONENTIATION` | `G_EXP` | 10 | Exponentiation base cost |
| `GAS_EXPONENTIATION_PER_BYTE` | `G_EXP_BYTE` | 50 | Exponentiation per byte |
#### Execution Spec Only Features
**Blob Gas (EIP-4844)**
```python
GAS_PER_BLOB = U64(2**17) # 131,072
BLOB_SCHEDULE_TARGET = U64(6)
TARGET_BLOB_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET
BLOB_BASE_COST = Uint(2**13) # 8,192
BLOB_SCHEDULE_MAX = U64(9)
MIN_BLOB_GASPRICE = Uint(1)
BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716)
```
**BLS Signature Operations (EIP-2537)**
```python
GAS_BLS_G1_ADD = Uint(375)
GAS_BLS_G1_MUL = Uint(12000)
GAS_BLS_G1_MAP = Uint(5500)
GAS_BLS_G2_ADD = Uint(600)
GAS_BLS_G2_MUL = Uint(22500)
GAS_BLS_G2_MAP = Uint(23800)
```
**Advanced Precompiles**
```python
GAS_P256VERIFY = Uint(6900) # P256 signature verification
GAS_POINT_EVALUATION = Uint(50000) # KZG point evaluation
GAS_BLOBHASH_OPCODE = Uint(3) # BLOBHASH opcode
```
**Cryptographic Operations**
```python
GAS_SHA256 = Uint(60)
GAS_SHA256_WORD = Uint(12)
GAS_RIPEMD160 = Uint(600)
GAS_RIPEMD160_WORD = Uint(120)
GAS_IDENTITY = Uint(15)
GAS_IDENTITY_WORD = Uint(3)
GAS_ECRECOVER = Uint(3000)
```
**Memory and Execution**
```python
GAS_RETURN_DATA_COPY = Uint(3)
GAS_FAST_STEP = Uint(5)
GAS_BLAKE2_PER_ROUND = Uint(1)
GAS_INIT_CODE_WORD_COST = Uint(2)
```
**Self-Destruct Operations**
```python
GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000)
```
#### Test Framework Only Features
**Transaction Data Costs**
```python
G_TX_DATA_ZERO: int = 4
G_TX_DATA_NON_ZERO: int = 68
G_TX_DATA_STANDARD_TOKEN_COST: int = 0
G_TX_DATA_FLOOR_TOKEN_COST: int = 0
G_TRANSACTION: int = 21000
G_TRANSACTION_CREATE: int = 32000
```
**Access List Costs (EIP-2930)**
```python
G_ACCESS_LIST_ADDRESS: int = 2400
G_ACCESS_LIST_STORAGE: int = 1900
```
**Authorization Costs**
```python
G_AUTHORIZATION: int = 25000
R_AUTHORIZATION_EXISTING_AUTHORITY: int = 12500
```