# 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 ```