From b26e5f20b8884e95de3e018dc032c339e7141b5b Mon Sep 17 00:00:00 2001 From: LouisTsai Date: Fri, 31 Oct 2025 15:29:04 +0800 Subject: [PATCH 1/4] refactor: unify gas cost variable name --- .../execution_testing/forks/forks/forks.py | 124 ++++++++------ .../src/execution_testing/forks/gas_costs.py | 87 +++++----- .../tools/utility/generators.py | 10 +- src/ethereum/forks/osaka/vm/gas.py | 16 ++ .../test_block_access_lists.py | 8 +- .../test_block_access_lists_opcodes.py | 62 +++---- tests/benchmark/compute/helpers.py | 14 +- .../compute/instruction/test_account_query.py | 16 +- .../compute/instruction/test_keccak.py | 8 +- .../compute/instruction/test_storage.py | 28 +-- .../compute/instruction/test_system.py | 103 +++++------ .../compute/precompile/test_alt_bn128.py | 2 +- .../scenario/test_transaction_types.py | 11 +- .../stateful/bloatnet/test_multi_opcode.py | 162 +++++++++--------- .../stateful/bloatnet/test_single_opcode.py | 108 ++++++------ .../eip2929_gas_cost_increases/test_call.py | 4 +- .../test_precompile_warming.py | 6 +- tests/berlin/eip2930_access_list/test_acl.py | 20 +-- .../test_mcopy_memory_expansion.py | 4 +- tests/frontier/opcodes/test_call.py | 26 +-- .../eip7823_modexp_upper_bounds/conftest.py | 8 +- .../test_tx_gas_limit.py | 18 +- .../eip7883_modexp_gas_increase/conftest.py | 12 +- .../test_modexp_thresholds_transition.py | 6 +- .../test_count_leading_zeros.py | 6 +- .../test_refunds.py | 10 +- .../eip7702_set_code_tx/test_eip_mainnet.py | 6 +- tests/prague/eip7702_set_code_tx/test_gas.py | 12 +- .../test_set_code_txs_2.py | 38 ++-- .../eip3860_initcode/test_initcode.py | 15 +- .../test_txcreate_failures.py | 22 +-- 31 files changed, 506 insertions(+), 466 deletions(-) diff --git a/packages/testing/src/execution_testing/forks/forks/forks.py b/packages/testing/src/execution_testing/forks/forks/forks.py index badea03972..4a7ae5f087 100644 --- a/packages/testing/src/execution_testing/forks/forks/forks.py +++ b/packages/testing/src/execution_testing/forks/forks/forks.py @@ -115,46 +115,45 @@ def gas_costs( """ del block_number, timestamp return GasCosts( - G_JUMPDEST=1, - G_BASE=2, - G_VERY_LOW=3, - G_LOW=5, - G_MID=8, - G_HIGH=10, - G_WARM_ACCOUNT_ACCESS=100, - G_COLD_ACCOUNT_ACCESS=2_600, - G_ACCESS_LIST_ADDRESS=2_400, - G_ACCESS_LIST_STORAGE=1_900, - G_WARM_SLOAD=100, - G_COLD_SLOAD=2_100, - G_STORAGE_SET=20_000, - G_STORAGE_RESET=2_900, - R_STORAGE_CLEAR=4_800, - G_SELF_DESTRUCT=5_000, - G_CREATE=32_000, - G_CODE_DEPOSIT_BYTE=200, - G_INITCODE_WORD=2, - G_CALL_VALUE=9_000, - G_CALL_STIPEND=2_300, - G_NEW_ACCOUNT=25_000, - G_EXP=10, - G_EXP_BYTE=50, - G_MEMORY=3, + GAS_JUMPDEST=1, + GAS_BASE=2, + GAS_VERY_LOW=3, + GAS_LOW=5, + GAS_MID=8, + GAS_HIGH=10, + GAS_WARM_ACCESS=100, + GAS_COLD_ACCOUNT_ACCESS=2_600, + TX_ACCESS_LIST_ADDRESS_COST=2_400, + TX_ACCESS_LIST_STORAGE_KEY_COST=1_900, + GAS_COLD_SLOAD=2_100, + GAS_STORAGE_SET=20_000, + GAS_STORAGE_UPDATE=2_900, + GAS_STORAGE_CLEAR_REFUND=4_800, + GAS_SELF_DESTRUCT=5_000, + GAS_CREATE=32_000, + GAS_CODE_DEPOSIT=200, + GAS_INIT_CODE_WORD_COST=2, + GAS_CALL_VALUE=9_000, + GAS_CALL_STIPEND=2_300, + GAS_NEW_ACCOUNT=25_000, + GAS_EXPONENTIATION=10, + GAS_EXPONENTIATION_PER_BYTE=50, + GAS_MEMORY=3, G_TX_DATA_ZERO=4, G_TX_DATA_NON_ZERO=68, - G_TX_DATA_STANDARD_TOKEN_COST=0, - G_TX_DATA_FLOOR_TOKEN_COST=0, - G_TRANSACTION=21_000, - G_TRANSACTION_CREATE=32_000, - G_LOG=375, - G_LOG_DATA=8, - G_LOG_TOPIC=375, - G_KECCAK_256=30, - G_KECCAK_256_WORD=6, - G_COPY=3, - G_BLOCKHASH=20, - G_AUTHORIZATION=0, - R_AUTHORIZATION_EXISTING_AUTHORITY=0, + STANDARD_CALLDATA_TOKEN_COST=0, + FLOOR_CALLDATA_COST=0, + TX_BASE_COST=21_000, + TX_CREATE_COST=32_000, + GAS_LOG=375, + GAS_LOG_DATA=8, + GAS_LOG_TOPIC=375, + GAS_KECCAK256=30, + GAS_KECCAK256_WORD=6, + GAS_COPY=3, + GAS_BLOCK_HASH=20, + PER_EMPTY_ACCOUNT_COST=0, + PER_AUTH_BASE_COST=0, ) @classmethod @@ -176,7 +175,7 @@ def fn(*, new_bytes: int, previous_bytes: int = 0) -> int: previous_words = ceiling_division(previous_bytes, 32) def c(w: int) -> int: - return (gas_costs.G_MEMORY * w) + ((w * w) // 512) + return (gas_costs.GAS_MEMORY * w) + ((w * w) // 512) return c(new_words) - c(previous_words) @@ -295,11 +294,12 @@ def fn( f"Authorizations are not supported in {cls.name()}" ) - intrinsic_cost: int = gas_costs.G_TRANSACTION + intrinsic_cost: int = gas_costs.TX_BASE_COST if contract_creation: - intrinsic_cost += gas_costs.G_INITCODE_WORD * ceiling_division( - len(Bytes(calldata)), 32 + intrinsic_cost += ( + gas_costs.GAS_INIT_CODE_WORD_COST + * ceiling_division(len(Bytes(calldata)), 32) ) return intrinsic_cost + calldata_gas_calculator(data=calldata) @@ -923,7 +923,7 @@ def fn( authorization_list_or_count=authorization_list_or_count, ) if contract_creation: - intrinsic_cost += gas_costs.G_TRANSACTION_CREATE + intrinsic_cost += gas_costs.TX_CREATE_COST return intrinsic_cost return fn @@ -1155,9 +1155,11 @@ def fn( ) if access_list is not None: for access in access_list: - intrinsic_cost += gas_costs.G_ACCESS_LIST_ADDRESS + intrinsic_cost += gas_costs.TX_ACCESS_LIST_ADDRESS_COST for _ in access.storage_keys: - intrinsic_cost += gas_costs.G_ACCESS_LIST_STORAGE + intrinsic_cost += ( + gas_costs.TX_ACCESS_LIST_STORAGE_KEY_COST + ) return intrinsic_cost return fn @@ -1853,10 +1855,10 @@ def gas_costs( super(Prague, cls).gas_costs( block_number=block_number, timestamp=timestamp ), - G_TX_DATA_STANDARD_TOKEN_COST=4, # https://eips.ethereum.org/EIPS/eip-7623 - G_TX_DATA_FLOOR_TOKEN_COST=10, - G_AUTHORIZATION=25_000, - R_AUTHORIZATION_EXISTING_AUTHORITY=12_500, + STANDARD_CALLDATA_TOKEN_COST=4, # https://eips.ethereum.org/EIPS/eip-7623 + FLOOR_CALLDATA_COST=10, + PER_EMPTY_ACCOUNT_COST=25_000, + PER_AUTH_BASE_COST=12_500, ) @classmethod @@ -1919,8 +1921,8 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int: else: tokens += 4 if floor: - return tokens * gas_costs.G_TX_DATA_FLOOR_TOKEN_COST - return tokens * gas_costs.G_TX_DATA_STANDARD_TOKEN_COST + return tokens * gas_costs.FLOOR_CALLDATA_COST + return tokens * gas_costs.STANDARD_CALLDATA_TOKEN_COST return fn @@ -1942,7 +1944,7 @@ def transaction_data_floor_cost_calculator( def fn(*, data: BytesConvertible) -> int: return ( calldata_gas_calculator(data=data, floor=True) - + gas_costs.G_TRANSACTION + + gas_costs.TX_BASE_COST ) return fn @@ -1987,7 +1989,8 @@ def fn( authorization_list_or_count ) intrinsic_cost += ( - authorization_list_or_count * gas_costs.G_AUTHORIZATION + authorization_list_or_count + * gas_costs.PER_EMPTY_ACCOUNT_COST ) if return_cost_deducted_prior_execution: @@ -2325,6 +2328,21 @@ def blob_base_cost( del block_number, timestamp return 2**13 # EIP-7918 new parameter + @classmethod + def gas_costs( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> GasCosts: + """Return the gas costs for the fork.""" + from ethereum.forks.osaka.vm import gas as g + from dataclasses import fields + + kwargs = {} + for field in fields(GasCosts): + if hasattr(g, field.name): + kwargs[field.name] = int(getattr(g, field.name)) + + return GasCosts(**kwargs) + class BPO1(Osaka, bpo_fork=True): """Mainnet BPO1 fork - Blob Parameter Only fork 1.""" diff --git a/packages/testing/src/execution_testing/forks/gas_costs.py b/packages/testing/src/execution_testing/forks/gas_costs.py index b3c7429a72..6fa19c47ca 100644 --- a/packages/testing/src/execution_testing/forks/gas_costs.py +++ b/packages/testing/src/execution_testing/forks/gas_costs.py @@ -7,56 +7,55 @@ class GasCosts: """Class that contains the gas cost constants for any fork.""" - G_JUMPDEST: int - G_BASE: int - G_VERY_LOW: int - G_LOW: int - G_MID: int - G_HIGH: int - G_WARM_ACCOUNT_ACCESS: int - G_COLD_ACCOUNT_ACCESS: int - G_ACCESS_LIST_ADDRESS: int - G_ACCESS_LIST_STORAGE: int - G_WARM_SLOAD: int - G_COLD_SLOAD: int - G_STORAGE_SET: int - G_STORAGE_RESET: int - - R_STORAGE_CLEAR: int - - G_SELF_DESTRUCT: int - G_CREATE: int - - G_CODE_DEPOSIT_BYTE: int - G_INITCODE_WORD: int - - G_CALL_VALUE: int - G_CALL_STIPEND: int - G_NEW_ACCOUNT: int - - G_EXP: int - G_EXP_BYTE: int - - G_MEMORY: int + GAS_JUMPDEST: int + GAS_BASE: int + GAS_VERY_LOW: int + GAS_LOW: int + GAS_MID: int + GAS_HIGH: int + GAS_WARM_ACCESS: int + GAS_COLD_ACCOUNT_ACCESS: int + TX_ACCESS_LIST_ADDRESS_COST: int + TX_ACCESS_LIST_STORAGE_KEY_COST: int + GAS_COLD_SLOAD: int + GAS_STORAGE_SET: int + GAS_STORAGE_UPDATE: int + + GAS_STORAGE_CLEAR_REFUND: int + + GAS_SELF_DESTRUCT: int + GAS_CREATE: int + + GAS_CODE_DEPOSIT: int + GAS_INIT_CODE_WORD_COST: int + + GAS_CALL_VALUE: int + GAS_CALL_STIPEND: int + GAS_NEW_ACCOUNT: int + + GAS_EXPONENTIATION: int + GAS_EXPONENTIATION_PER_BYTE: int + + GAS_MEMORY: int G_TX_DATA_ZERO: int G_TX_DATA_NON_ZERO: int - G_TX_DATA_STANDARD_TOKEN_COST: int - G_TX_DATA_FLOOR_TOKEN_COST: int + STANDARD_CALLDATA_TOKEN_COST: int + FLOOR_CALLDATA_COST: int - G_TRANSACTION: int - G_TRANSACTION_CREATE: int + TX_BASE_COST: int + TX_CREATE_COST: int - G_LOG: int - G_LOG_DATA: int - G_LOG_TOPIC: int + GAS_LOG: int + GAS_LOG_DATA: int + GAS_LOG_TOPIC: int - G_KECCAK_256: int - G_KECCAK_256_WORD: int + GAS_KECCAK256: int + GAS_KECCAK256_WORD: int - G_COPY: int - G_BLOCKHASH: int + GAS_COPY: int + GAS_BLOCK_HASH: int - G_AUTHORIZATION: int + PER_EMPTY_ACCOUNT_COST: int - R_AUTHORIZATION_EXISTING_AUTHORITY: int + PER_AUTH_BASE_COST: int diff --git a/packages/testing/src/execution_testing/tools/utility/generators.py b/packages/testing/src/execution_testing/tools/utility/generators.py index e0a501cd1f..ddc794d300 100644 --- a/packages/testing/src/execution_testing/tools/utility/generators.py +++ b/packages/testing/src/execution_testing/tools/utility/generators.py @@ -347,9 +347,9 @@ def wrapper( # code will only work once, so if the system contract is re- # executed in a subsequent block, it will consume less gas. gas_used_per_storage = ( - gas_costs.G_STORAGE_SET - + gas_costs.G_COLD_SLOAD - + (gas_costs.G_VERY_LOW * 2) + gas_costs.GAS_STORAGE_SET + + gas_costs.GAS_COLD_SLOAD + + (gas_costs.GAS_VERY_LOW * 2) ) modified_system_contract_code += sum( Op.SSTORE(i, 1) @@ -358,8 +358,8 @@ def wrapper( # If the gas limit is not divisible by the gas used per # storage, we need to add some NO-OP (JUMPDEST) to the code # that each consume 1 gas. - assert gas_costs.G_JUMPDEST == 1, ( - f"JUMPDEST gas cost should be 1, but got {gas_costs.G_JUMPDEST}. " + assert gas_costs.GAS_JUMPDEST == 1, ( + f"JUMPDEST gas cost should be 1, but got {gas_costs.GAS_JUMPDEST}. " "Generator `generate_system_contract_error_test` needs to be updated." ) modified_system_contract_code += sum( diff --git a/src/ethereum/forks/osaka/vm/gas.py b/src/ethereum/forks/osaka/vm/gas.py index 62118f4c6a..2387e88614 100644 --- a/src/ethereum/forks/osaka/vm/gas.py +++ b/src/ethereum/forks/osaka/vm/gas.py @@ -84,6 +84,22 @@ GAS_BLS_G2_MUL = Uint(22500) GAS_BLS_G2_MAP = Uint(23800) +# EEST Specific Variables +G_TX_DATA_ZERO = 4 +G_TX_DATA_NON_ZERO = 68 + +# Transaction costs (from transactions.py) +TX_BASE_COST = Uint(21_000) +TX_CREATE_COST = Uint(32_000) +TX_ACCESS_LIST_ADDRESS_COST = Uint(2_400) +TX_ACCESS_LIST_STORAGE_KEY_COST = Uint(1_900) +STANDARD_CALLDATA_TOKEN_COST = Uint(4) +FLOOR_CALLDATA_COST = Uint(10) + +# Authorization costs (from eoa_delegation.py) +PER_EMPTY_ACCOUNT_COST = 25_000 +PER_AUTH_BASE_COST = 12_500 + @dataclass class ExtendMemory: diff --git a/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index 4f51fd946b..01eaae889a 100644 --- a/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -1227,10 +1227,10 @@ def test_bal_noop_storage_write( gas_limit = ( intrinsic_gas_calculator() # Sufficient gas for write - + fork.gas_costs().G_COLD_SLOAD - + fork.gas_costs().G_COLD_ACCOUNT_ACCESS - + fork.gas_costs().G_STORAGE_SET - + fork.gas_costs().G_BASE * 10 # Buffer for push + + fork.gas_costs().GAS_COLD_SLOAD + + fork.gas_costs().GAS_COLD_ACCOUNT_ACCESS + + fork.gas_costs().GAS_STORAGE_SET + + fork.gas_costs().GAS_BASE * 10 # Buffer for push ) tx = Transaction( diff --git a/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py index 5e5ebaefe3..4a21bbd81f 100644 --- a/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py +++ b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py @@ -87,13 +87,13 @@ def test_bal_sstore_and_oog( intrinsic_gas_cost = intrinsic_gas_calculator() # Costs: - # - PUSH1 (value and slot) = G_VERY_LOW * 2 - # - SSTORE cold (to zero slot) = G_STORAGE_SET + G_COLD_SLOAD - sload_cost = gas_costs.G_COLD_SLOAD - sstore_cost = gas_costs.G_STORAGE_SET + # - PUSH1 (value and slot) = GAS_VERY_LOW * 2 + # - SSTORE cold (to zero slot) = GAS_STORAGE_SET + GAS_COLD_SLOAD + sload_cost = gas_costs.GAS_COLD_SLOAD + sstore_cost = gas_costs.GAS_STORAGE_SET sstore_cold_cost = sstore_cost + sload_cost - push_cost = gas_costs.G_VERY_LOW * 2 - stipend = gas_costs.G_CALL_STIPEND + push_cost = gas_costs.GAS_VERY_LOW * 2 + stipend = gas_costs.GAS_CALL_STIPEND if out_of_gas_at == OutOfGasAt.EIP_2200_STIPEND: # 2300 after PUSHes (fails stipend check: 2300 <= 2300) @@ -185,10 +185,10 @@ def test_bal_sload_and_oog( intrinsic_gas_cost = intrinsic_gas_calculator() # Costs: - # - PUSH1 (slot) = G_VERY_LOW - # - SLOAD cold = G_COLD_SLOAD - push_cost = gas_costs.G_VERY_LOW - sload_cold_cost = gas_costs.G_COLD_SLOAD + # - PUSH1 (slot) = GAS_VERY_LOW + # - SLOAD cold = GAS_COLD_SLOAD + push_cost = gas_costs.GAS_VERY_LOW + sload_cold_cost = gas_costs.GAS_COLD_SLOAD tx_gas_limit = intrinsic_gas_cost + push_cost + sload_cold_cost if fails_at_sload: @@ -251,10 +251,10 @@ def test_bal_balance_and_oog( intrinsic_gas_cost = intrinsic_gas_calculator() # Costs: - # - PUSH20 = G_VERY_LOW - # - BALANCE cold = G_COLD_ACCOUNT_ACCESS - push_cost = gas_costs.G_VERY_LOW - balance_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + # - PUSH20 = GAS_VERY_LOW + # - BALANCE cold = GAS_COLD_ACCOUNT_ACCESS + push_cost = gas_costs.GAS_VERY_LOW + balance_cold_cost = gas_costs.GAS_COLD_ACCOUNT_ACCESS tx_gas_limit = intrinsic_gas_cost + push_cost + balance_cold_cost if fails_at_balance: @@ -326,10 +326,10 @@ def test_bal_extcodesize_and_oog( intrinsic_gas_cost = intrinsic_gas_calculator() # Costs: - # - PUSH20 = G_VERY_LOW - # - EXTCODESIZE cold = G_COLD_ACCOUNT_ACCESS - push_cost = gas_costs.G_VERY_LOW - extcodesize_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + # - PUSH20 = GAS_VERY_LOW + # - EXTCODESIZE cold = GAS_COLD_ACCOUNT_ACCESS + push_cost = gas_costs.GAS_VERY_LOW + extcodesize_cold_cost = gas_costs.GAS_COLD_ACCOUNT_ACCESS tx_gas_limit = intrinsic_gas_cost + push_cost + extcodesize_cold_cost if fails_at_extcodesize: @@ -401,10 +401,10 @@ def test_bal_call_and_oog( intrinsic_gas_cost = intrinsic_gas_calculator() # Costs: - # - 7 PUSH operations = G_VERY_LOW * 7 - # - CALL cold = G_COLD_ACCOUNT_ACCESS (minimum for account access) - push_cost = gas_costs.G_VERY_LOW * 7 - call_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + # - 7 PUSH operations = GAS_VERY_LOW * 7 + # - CALL cold = GAS_COLD_ACCOUNT_ACCESS (minimum for account access) + push_cost = gas_costs.GAS_VERY_LOW * 7 + call_cold_cost = gas_costs.GAS_COLD_ACCOUNT_ACCESS tx_gas_limit = intrinsic_gas_cost + push_cost + call_cold_cost if fails_at_call: @@ -483,10 +483,10 @@ def test_bal_delegatecall_and_oog( intrinsic_gas_cost = intrinsic_gas_calculator() # Costs: - # - 6 PUSH operations = G_VERY_LOW * 6 - # - DELEGATECALL cold = G_COLD_ACCOUNT_ACCESS - push_cost = gas_costs.G_VERY_LOW * 6 - delegatecall_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + # - 6 PUSH operations = GAS_VERY_LOW * 6 + # - DELEGATECALL cold = GAS_COLD_ACCOUNT_ACCESS + push_cost = gas_costs.GAS_VERY_LOW * 6 + delegatecall_cold_cost = gas_costs.GAS_COLD_ACCOUNT_ACCESS tx_gas_limit = intrinsic_gas_cost + push_cost + delegatecall_cold_cost if fails_at_delegatecall: @@ -563,13 +563,13 @@ def test_bal_extcodecopy_and_oog( intrinsic_gas_cost = intrinsic_gas_calculator() # Costs: - # - 4 PUSH operations = G_VERY_LOW * 4 - # - EXTCODECOPY cold = G_COLD_ACCOUNT_ACCESS + (G_COPY * words) + # - 4 PUSH operations = GAS_VERY_LOW * 4 + # - EXTCODECOPY cold = GAS_COLD_ACCOUNT_ACCESS + (GAS_COPY * words) # where words = ceil32(size) // 32 = ceil32(0) // 32 = 0 - push_cost = gas_costs.G_VERY_LOW * 4 + push_cost = gas_costs.GAS_VERY_LOW * 4 extcodecopy_cold_cost = ( - gas_costs.G_COLD_ACCOUNT_ACCESS - ) # + (G_COPY * 0) = 0 + gas_costs.GAS_COLD_ACCOUNT_ACCESS + ) # + (GAS_COPY * 0) = 0 tx_gas_limit = intrinsic_gas_cost + push_cost + extcodecopy_cold_cost if fails_at_extcodecopy: diff --git a/tests/benchmark/compute/helpers.py b/tests/benchmark/compute/helpers.py index 0343ff3cf6..c3f67b2e35 100644 --- a/tests/benchmark/compute/helpers.py +++ b/tests/benchmark/compute/helpers.py @@ -186,19 +186,19 @@ def calculate_optimal_input_length( for input_length in range(1, 1_000_000, 32): parameters_gas = ( - gsc.G_BASE # PUSH0 = arg offset - + gsc.G_BASE # PUSH0 = arg size - + gsc.G_BASE # PUSH0 = arg size - + gsc.G_VERY_LOW # PUSH0 = arg offset - + gsc.G_VERY_LOW # PUSHN = address - + gsc.G_BASE # GAS + gsc.GAS_BASE # PUSH0 = arg offset + + gsc.GAS_BASE # PUSH0 = arg size + + gsc.GAS_BASE # PUSH0 = arg size + + gsc.GAS_VERY_LOW # PUSH0 = arg offset + + gsc.GAS_VERY_LOW # PUSHN = address + + gsc.GAS_BASE # GAS ) iteration_gas_cost = ( parameters_gas + static_cost # Precompile static cost + math.ceil(input_length / 32) * per_word_dynamic_cost # Precompile dynamic cost - + gsc.G_BASE # POP + + gsc.GAS_BASE # POP ) # From the available gas, subtract the memory expansion costs diff --git a/tests/benchmark/compute/instruction/test_account_query.py b/tests/benchmark/compute/instruction/test_account_query.py index 1190194f77..3a93baeb8e 100644 --- a/tests/benchmark/compute/instruction/test_account_query.py +++ b/tests/benchmark/compute/instruction/test_account_query.py @@ -144,24 +144,26 @@ def test_extcode_ops( new_bytes=len(bytes(max_contract_size)) ) code_deposit_gas_minimum = ( - fork.gas_costs().G_CODE_DEPOSIT_BYTE * max_contract_size + fork.gas_costs().GAS_CODE_DEPOSIT * max_contract_size + memory_gas_minimum ) intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() # Calculate the loop cost of the attacker to query one address loop_cost = ( - gas_costs.G_KECCAK_256 # KECCAK static cost - + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic + gas_costs.GAS_KECCAK256 # KECCAK static cost + + math.ceil(85 / 32) * gas_costs.GAS_KECCAK256_WORD # KECCAK dynamic # cost for CREATE2 - + gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs - + gas_costs.G_COLD_ACCOUNT_ACCESS # Opcode cost + + gas_costs.GAS_VERY_LOW * 3 # ~MSTOREs+ADDs + + gas_costs.GAS_COLD_ACCOUNT_ACCESS # Opcode cost + 30 # ~Gluing opcodes ) # Calculate the number of contracts to be targeted num_contracts = ( # Base available gas = GAS_LIMIT - intrinsic - (out of loop MSTOREs) - attack_gas_limit - intrinsic_gas_cost_calc() - gas_costs.G_VERY_LOW * 4 + attack_gas_limit + - intrinsic_gas_cost_calc() + - gas_costs.GAS_VERY_LOW * 4 ) // loop_cost # Set the block gas limit to a relative high value to ensure the code @@ -431,7 +433,7 @@ def test_ext_account_query_cold( # transaction runs out of gas. num_target_accounts = ( attack_gas_limit - intrinsic_gas_cost_calc() - ) // gas_costs.G_COLD_ACCOUNT_ACCESS + ) // gas_costs.GAS_COLD_ACCOUNT_ACCESS blocks = [] post = {} diff --git a/tests/benchmark/compute/instruction/test_keccak.py b/tests/benchmark/compute/instruction/test_keccak.py index 28edd306bd..9f0963427b 100644 --- a/tests/benchmark/compute/instruction/test_keccak.py +++ b/tests/benchmark/compute/instruction/test_keccak.py @@ -36,11 +36,11 @@ def test_keccak( optimal_input_length = 0 for i in range(1, 1_000_000, 32): iteration_gas_cost = ( - 2 * gsc.G_VERY_LOW # PUSHN + PUSH1 - + gsc.G_KECCAK_256 # KECCAK256 static cost - + math.ceil(i / 32) * gsc.G_KECCAK_256_WORD # KECCAK256 dynamic + 2 * gsc.GAS_VERY_LOW # PUSHN + PUSH1 + + gsc.GAS_KECCAK256 # KECCAK256 static cost + + math.ceil(i / 32) * gsc.GAS_KECCAK256_WORD # KECCAK256 dynamic # cost - + gsc.G_BASE # POP + + gsc.GAS_BASE # POP ) # From the available gas, we subtract the mem expansion costs # considering we know the current input size length i. diff --git a/tests/benchmark/compute/instruction/test_storage.py b/tests/benchmark/compute/instruction/test_storage.py index a07673c35f..2d95d4f0c6 100644 --- a/tests/benchmark/compute/instruction/test_storage.py +++ b/tests/benchmark/compute/instruction/test_storage.py @@ -157,19 +157,19 @@ def test_storage_access_cold( gas_costs = fork.gas_costs() intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() - loop_cost = gas_costs.G_COLD_SLOAD # All accesses are always cold + loop_cost = gas_costs.GAS_COLD_SLOAD # All accesses are always cold if storage_action == StorageAction.WRITE_NEW_VALUE: if not absent_slots: - loop_cost += gas_costs.G_STORAGE_RESET + loop_cost += gas_costs.GAS_STORAGE_UPDATE else: - loop_cost += gas_costs.G_STORAGE_SET + loop_cost += gas_costs.GAS_STORAGE_SET elif storage_action == StorageAction.WRITE_SAME_VALUE: if absent_slots: - loop_cost += gas_costs.G_STORAGE_SET + loop_cost += gas_costs.GAS_STORAGE_SET else: - loop_cost += gas_costs.G_WARM_SLOAD + loop_cost += gas_costs.GAS_WARM_ACCESS elif storage_action == StorageAction.READ: - loop_cost += 0 # Only G_COLD_SLOAD is charged + loop_cost += 0 # Only GAS_COLD_SLOAD is charged # Contract code execution_code_body = Bytecode() @@ -177,31 +177,31 @@ def test_storage_access_cold( # All the storage slots in the contract are initialized to their index. # That is, storage slot `i` is initialized to `i`. execution_code_body = Op.SSTORE(Op.DUP1, Op.DUP1) - loop_cost += gas_costs.G_VERY_LOW * 2 + loop_cost += gas_costs.GAS_VERY_LOW * 2 elif storage_action == StorageAction.WRITE_NEW_VALUE: # The new value 2^256-1 is guaranteed to be different from the initial # value. execution_code_body = Op.SSTORE(Op.DUP2, Op.NOT(0)) - loop_cost += gas_costs.G_VERY_LOW * 3 + loop_cost += gas_costs.GAS_VERY_LOW * 3 elif storage_action == StorageAction.READ: execution_code_body = Op.POP(Op.SLOAD(Op.DUP1)) - loop_cost += gas_costs.G_VERY_LOW + gas_costs.G_BASE + loop_cost += gas_costs.GAS_VERY_LOW + gas_costs.GAS_BASE # Add costs jump-logic costs loop_cost += ( - gas_costs.G_JUMPDEST # Prefix Jumpdest - + gas_costs.G_VERY_LOW * 7 # ISZEROs, PUSHs, SWAPs, SUB, DUP - + gas_costs.G_HIGH # JUMPI + gas_costs.GAS_JUMPDEST # Prefix Jumpdest + + gas_costs.GAS_VERY_LOW * 7 # ISZEROs, PUSHs, SWAPs, SUB, DUP + + gas_costs.GAS_HIGH # JUMPI ) prefix_cost = ( - gas_costs.G_VERY_LOW # Target slots push + gas_costs.GAS_VERY_LOW # Target slots push ) suffix_cost = 0 if tx_result == TransactionResult.REVERT: suffix_cost = ( - gas_costs.G_VERY_LOW * 2 # Revert PUSHs + gas_costs.GAS_VERY_LOW * 2 # Revert PUSHs ) num_target_slots = ( diff --git a/tests/benchmark/compute/instruction/test_system.py b/tests/benchmark/compute/instruction/test_system.py index 80933bc979..7eb6afcc32 100644 --- a/tests/benchmark/compute/instruction/test_system.py +++ b/tests/benchmark/compute/instruction/test_system.py @@ -66,24 +66,26 @@ def test_xcall( new_bytes=len(bytes(max_contract_size)) ) code_deposit_gas_minimum = ( - fork.gas_costs().G_CODE_DEPOSIT_BYTE * max_contract_size + fork.gas_costs().GAS_CODE_DEPOSIT * max_contract_size + memory_gas_minimum ) intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() # Calculate the loop cost of the attacker to query one address loop_cost = ( - gas_costs.G_KECCAK_256 # KECCAK static cost - + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic + gas_costs.GAS_KECCAK256 # KECCAK static cost + + math.ceil(85 / 32) * gas_costs.GAS_KECCAK256_WORD # KECCAK dynamic # cost for CREATE2 - + gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs - + gas_costs.G_COLD_ACCOUNT_ACCESS # Opcode cost + + gas_costs.GAS_VERY_LOW * 3 # ~MSTOREs+ADDs + + gas_costs.GAS_COLD_ACCOUNT_ACCESS # Opcode cost + 30 # ~Gluing opcodes ) # Calculate the number of contracts to be targeted num_contracts = ( # Base available gas = GAS_LIMIT - intrinsic - (out of loop MSTOREs) - attack_gas_limit - intrinsic_gas_cost_calc() - gas_costs.G_VERY_LOW * 4 + attack_gas_limit + - intrinsic_gas_cost_calc() + - gas_costs.GAS_VERY_LOW * 4 ) // loop_cost # Set the block gas limit to a relative high value to ensure the code @@ -392,7 +394,7 @@ def test_creates_collisions( gas_costs = fork.gas_costs() # The CALL to the proxy contract needs at a minimum gas corresponding to # the CREATE(2) plus extra required PUSH0s for arguments. - min_gas_required = gas_costs.G_CREATE + gas_costs.G_BASE * ( + min_gas_required = gas_costs.GAS_CREATE + gas_costs.GAS_BASE * ( 3 if opcode == Op.CREATE else 4 ) setup = Op.PUSH20(proxy_contract) + Op.PUSH3(min_gas_required) @@ -411,7 +413,7 @@ def test_creates_collisions( pre.deploy_contract(address=addr, code=Op.INVALID) else: # Heuristic to have an upper bound. - max_contract_count = 2 * gas_benchmark_value // gas_costs.G_CREATE + max_contract_count = 2 * gas_benchmark_value // gas_costs.GAS_CREATE for nonce in range(max_contract_count): addr = compute_create_address(address=proxy_contract, nonce=nonce) pre.deploy_contract(address=addr, code=Op.INVALID) @@ -508,25 +510,26 @@ def test_selfdestruct_existing( gas_costs = fork.gas_costs() intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() loop_cost = ( - gas_costs.G_KECCAK_256 # KECCAK static cost - + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic + gas_costs.GAS_KECCAK256 # KECCAK static cost + + math.ceil(85 / 32) * gas_costs.GAS_KECCAK256_WORD # KECCAK dynamic # cost for CREATE2 - + gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs - + gas_costs.G_COLD_ACCOUNT_ACCESS # CALL to self-destructing contract - + gas_costs.G_SELF_DESTRUCT + + gas_costs.GAS_VERY_LOW * 3 # ~MSTOREs+ADDs + + gas_costs.GAS_COLD_ACCOUNT_ACCESS + # CALL to self-destructing contract + + gas_costs.GAS_SELF_DESTRUCT + 63 # ~Gluing opcodes ) final_storage_gas = ( - gas_costs.G_STORAGE_RESET - + gas_costs.G_COLD_SLOAD - + (gas_costs.G_VERY_LOW * 2) + gas_costs.GAS_STORAGE_UPDATE + + gas_costs.GAS_COLD_SLOAD + + (gas_costs.GAS_VERY_LOW * 2) ) memory_expansion_cost = fork().memory_expansion_gas_calculator()( new_bytes=96 ) base_costs = ( intrinsic_gas_cost_calc() - + (gas_costs.G_VERY_LOW * 12) # 8 PUSHs + 4 MSTOREs + + (gas_costs.GAS_VERY_LOW * 12) # 8 PUSHs + 4 MSTOREs + final_storage_gas + memory_expansion_cost ) @@ -657,40 +660,40 @@ def test_selfdestruct_created( intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() initcode_costs = ( - gas_costs.G_VERY_LOW * 8 # MSTOREs, PUSHs + gas_costs.GAS_VERY_LOW * 8 # MSTOREs, PUSHs + memory_expansion_calc(new_bytes=2) # return into memory ) create_costs = ( initcode_costs - + gas_costs.G_CREATE - + gas_costs.G_VERY_LOW * 3 # Create Parameter PUSHs - + gas_costs.G_CODE_DEPOSIT_BYTE * 2 - + gas_costs.G_INITCODE_WORD + + gas_costs.GAS_CREATE + + gas_costs.GAS_VERY_LOW * 3 # Create Parameter PUSHs + + gas_costs.GAS_CODE_DEPOSIT * 2 + + gas_costs.GAS_INIT_CODE_WORD_COST ) call_costs = ( - gas_costs.G_WARM_ACCOUNT_ACCESS - + gas_costs.G_BASE # COINBASE - + gas_costs.G_SELF_DESTRUCT - + gas_costs.G_VERY_LOW * 5 # CALL Parameter PUSHs - + gas_costs.G_BASE # Parameter GAS + gas_costs.GAS_WARM_ACCESS + + gas_costs.GAS_BASE # COINBASE + + gas_costs.GAS_SELF_DESTRUCT + + gas_costs.GAS_VERY_LOW * 5 # CALL Parameter PUSHs + + gas_costs.GAS_BASE # Parameter GAS ) extra_costs = ( - gas_costs.G_BASE # POP - + gas_costs.G_VERY_LOW * 6 # PUSHs, ADD, DUP, GT - + gas_costs.G_HIGH # JUMPI - + gas_costs.G_JUMPDEST + gas_costs.GAS_BASE # POP + + gas_costs.GAS_VERY_LOW * 6 # PUSHs, ADD, DUP, GT + + gas_costs.GAS_HIGH # JUMPI + + gas_costs.GAS_JUMPDEST ) loop_cost = create_costs + call_costs + extra_costs prefix_cost = ( - gas_costs.G_VERY_LOW * 3 - + gas_costs.G_BASE + gas_costs.GAS_VERY_LOW * 3 + + gas_costs.GAS_BASE + memory_expansion_calc(new_bytes=32) ) suffix_cost = ( - gas_costs.G_COLD_SLOAD - + gas_costs.G_STORAGE_RESET - + (gas_costs.G_VERY_LOW * 2) + gas_costs.GAS_COLD_SLOAD + + gas_costs.GAS_STORAGE_UPDATE + + (gas_costs.GAS_VERY_LOW * 2) ) base_costs = prefix_cost + suffix_cost + intrinsic_gas_cost_calc() @@ -757,32 +760,32 @@ def test_selfdestruct_initcode( intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() initcode_costs = ( - gas_costs.G_BASE # COINBASE - + gas_costs.G_SELF_DESTRUCT + gas_costs.GAS_BASE # COINBASE + + gas_costs.GAS_SELF_DESTRUCT ) create_costs = ( initcode_costs - + gas_costs.G_CREATE - + gas_costs.G_VERY_LOW * 3 # Create Parameter PUSHs - + gas_costs.G_INITCODE_WORD + + gas_costs.GAS_CREATE + + gas_costs.GAS_VERY_LOW * 3 # Create Parameter PUSHs + + gas_costs.GAS_INIT_CODE_WORD_COST ) extra_costs = ( - gas_costs.G_BASE # POP - + gas_costs.G_VERY_LOW * 6 # PUSHs, ADD, DUP, GT - + gas_costs.G_HIGH # JUMPI - + gas_costs.G_JUMPDEST + gas_costs.GAS_BASE # POP + + gas_costs.GAS_VERY_LOW * 6 # PUSHs, ADD, DUP, GT + + gas_costs.GAS_HIGH # JUMPI + + gas_costs.GAS_JUMPDEST ) loop_cost = create_costs + extra_costs prefix_cost = ( - gas_costs.G_VERY_LOW * 3 - + gas_costs.G_BASE + gas_costs.GAS_VERY_LOW * 3 + + gas_costs.GAS_BASE + memory_expansion_calc(new_bytes=32) ) suffix_cost = ( - gas_costs.G_COLD_SLOAD - + gas_costs.G_STORAGE_RESET - + (gas_costs.G_VERY_LOW * 2) + gas_costs.GAS_COLD_SLOAD + + gas_costs.GAS_STORAGE_UPDATE + + (gas_costs.GAS_VERY_LOW * 2) ) base_costs = prefix_cost + suffix_cost + intrinsic_gas_cost_calc() diff --git a/tests/benchmark/compute/precompile/test_alt_bn128.py b/tests/benchmark/compute/precompile/test_alt_bn128.py index 55026a44eb..627fe74aa8 100644 --- a/tests/benchmark/compute/precompile/test_alt_bn128.py +++ b/tests/benchmark/compute/precompile/test_alt_bn128.py @@ -461,7 +461,7 @@ def test_bn128_pairings_amortized( # This is ignoring "glue" opcodes, but helps to have a rough idea of # the right cutting point. approx_gas_cost_per_call = ( - gsc.G_WARM_ACCOUNT_ACCESS + base_cost + i * pairing_cost + gsc.GAS_WARM_ACCESS + base_cost + i * pairing_cost ) num_precompile_calls = ( diff --git a/tests/benchmark/compute/scenario/test_transaction_types.py b/tests/benchmark/compute/scenario/test_transaction_types.py index cb0a4f4b64..415ab0f7e1 100644 --- a/tests/benchmark/compute/scenario/test_transaction_types.py +++ b/tests/benchmark/compute/scenario/test_transaction_types.py @@ -306,8 +306,8 @@ def test_block_full_access_list_and_data( # Access list gas costs from fork's gas_costs gas_costs = fork.gas_costs() - gas_per_address = gas_costs.G_ACCESS_LIST_ADDRESS - gas_per_storage_key = gas_costs.G_ACCESS_LIST_STORAGE + gas_per_address = gas_costs.TX_ACCESS_LIST_ADDRESS_COST + gas_per_storage_key = gas_costs.TX_ACCESS_LIST_STORAGE_KEY_COST # Calculate number of storage keys we can fit gas_after_address = gas_for_access_list - gas_per_address @@ -407,7 +407,7 @@ def test_worst_case_auth_block( iteration_count = ( gas_benchmark_value - intrinsic_cost - ) // gas_costs.G_AUTHORIZATION + ) // gas_costs.PER_EMPTY_ACCOUNT_COST code = Op.STOP * fork.max_code_size() auth_target = ( @@ -441,10 +441,7 @@ def test_worst_case_auth_block( if not empty_authority: refund = min( gas_used // 5, - ( - gas_costs.G_AUTHORIZATION - - gas_costs.R_AUTHORIZATION_EXISTING_AUTHORITY - ) + (gas_costs.PER_EMPTY_ACCOUNT_COST - gas_costs.PER_AUTH_BASE_COST) * iteration_count, ) diff --git a/tests/benchmark/stateful/bloatnet/test_multi_opcode.py b/tests/benchmark/stateful/bloatnet/test_multi_opcode.py index 300322bc2f..d80f9dd8db 100755 --- a/tests/benchmark/stateful/bloatnet/test_multi_opcode.py +++ b/tests/benchmark/stateful/bloatnet/test_multi_opcode.py @@ -81,18 +81,18 @@ def test_bloatnet_balance_extcodesize( # Cost per contract access with CREATE2 address generation cost_per_contract = ( - gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) - + gas_costs.G_KECCAK_256_WORD + gas_costs.GAS_KECCAK256 # SHA3 static cost for address generation (30) + + gas_costs.GAS_KECCAK256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) - + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600) - + gas_costs.G_BASE # POP first result (2) - + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access (100) - + gas_costs.G_BASE # POP second result (2) - + gas_costs.G_BASE # DUP1 before first op (3) - + gas_costs.G_VERY_LOW * 4 # PUSH1 operations (4 * 3) - + gas_costs.G_LOW # MLOAD for salt (3) - + gas_costs.G_VERY_LOW # ADD for increment (3) - + gas_costs.G_LOW # MSTORE salt back (3) + + gas_costs.GAS_COLD_ACCOUNT_ACCESS # Cold access (2600) + + gas_costs.GAS_BASE # POP first result (2) + + gas_costs.GAS_WARM_ACCESS # Warm access (100) + + gas_costs.GAS_BASE # POP second result (2) + + gas_costs.GAS_BASE # DUP1 before first op (3) + + gas_costs.GAS_VERY_LOW * 4 # PUSH1 operations (4 * 3) + + gas_costs.GAS_LOW # MLOAD for salt (3) + + gas_costs.GAS_VERY_LOW # ADD for increment (3) + + gas_costs.GAS_LOW # MSTORE salt back (3) + 10 # While loop overhead ) @@ -237,19 +237,19 @@ def test_bloatnet_balance_extcodecopy( # Cost per contract with EXTCODECOPY and CREATE2 address generation cost_per_contract = ( - gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) - + gas_costs.G_KECCAK_256_WORD + gas_costs.GAS_KECCAK256 # SHA3 static cost for address generation (30) + + gas_costs.GAS_KECCAK256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) - + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600) - + gas_costs.G_BASE # POP first result (2) - + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access base (100) - + gas_costs.G_COPY * 1 # Copy cost for 1 byte (3) - + gas_costs.G_BASE * 2 # DUP1 before first op, DUP4 for address (6) - + gas_costs.G_VERY_LOW * 8 # PUSH operations (8 * 3 = 24) - + gas_costs.G_LOW * 2 # MLOAD for salt twice (6) - + gas_costs.G_VERY_LOW * 2 # ADD operations (6) - + gas_costs.G_LOW # MSTORE salt back (3) - + gas_costs.G_BASE # POP after second op (2) + + gas_costs.GAS_COLD_ACCOUNT_ACCESS # Cold access (2600) + + gas_costs.GAS_BASE # POP first result (2) + + gas_costs.GAS_WARM_ACCESS # Warm access base (100) + + gas_costs.GAS_COPY * 1 # Copy cost for 1 byte (3) + + gas_costs.GAS_BASE * 2 # DUP1 before first op, DUP4 for address (6) + + gas_costs.GAS_VERY_LOW * 8 # PUSH operations (8 * 3 = 24) + + gas_costs.GAS_LOW * 2 # MLOAD for salt twice (6) + + gas_costs.GAS_VERY_LOW * 2 # ADD operations (6) + + gas_costs.GAS_LOW # MSTORE salt back (3) + + gas_costs.GAS_BASE # POP after second op (2) + 10 # While loop overhead ) @@ -398,18 +398,18 @@ def test_bloatnet_balance_extcodehash( # Cost per contract access with CREATE2 address generation cost_per_contract = ( - gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) - + gas_costs.G_KECCAK_256_WORD + gas_costs.GAS_KECCAK256 # SHA3 static cost for address generation (30) + + gas_costs.GAS_KECCAK256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) - + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600) - + gas_costs.G_BASE # POP first result (2) - + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access (100) - + gas_costs.G_BASE # POP second result (2) - + gas_costs.G_BASE # DUP1 before first op (3) - + gas_costs.G_VERY_LOW * 4 # PUSH1 operations (4 * 3) - + gas_costs.G_LOW # MLOAD for salt (3) - + gas_costs.G_VERY_LOW # ADD for increment (3) - + gas_costs.G_LOW # MSTORE salt back (3) + + gas_costs.GAS_COLD_ACCOUNT_ACCESS # Cold access (2600) + + gas_costs.GAS_BASE # POP first result (2) + + gas_costs.GAS_WARM_ACCESS # Warm access (100) + + gas_costs.GAS_BASE # POP second result (2) + + gas_costs.GAS_BASE # DUP1 before first op (3) + + gas_costs.GAS_VERY_LOW * 4 # PUSH1 operations (4 * 3) + + gas_costs.GAS_LOW # MLOAD for salt (3) + + gas_costs.GAS_VERY_LOW # ADD for increment (3) + + gas_costs.GAS_LOW # MSTORE salt back (3) + 10 # While loop overhead ) @@ -579,65 +579,65 @@ def test_mixed_sload_sstore( # Fixed overhead for SLOAD loop sload_loop_overhead = ( # Attack contract loop overhead - gas_costs.G_VERY_LOW * 2 # MLOAD counter (3*2) - + gas_costs.G_VERY_LOW * 2 # MSTORE selector (3*2) - + gas_costs.G_VERY_LOW * 3 # MLOAD + MSTORE address (3*3) - + gas_costs.G_BASE # POP (2) - + gas_costs.G_BASE * 3 # SUB + MLOAD + MSTORE counter decrement - + gas_costs.G_BASE * 2 # ISZERO * 2 for loop condition (2*2) - + gas_costs.G_MID # JUMPI (8) + gas_costs.GAS_VERY_LOW * 2 # MLOAD counter (3*2) + + gas_costs.GAS_VERY_LOW * 2 # MSTORE selector (3*2) + + gas_costs.GAS_VERY_LOW * 3 # MLOAD + MSTORE address (3*3) + + gas_costs.GAS_BASE # POP (2) + + gas_costs.GAS_BASE * 3 # SUB + MLOAD + MSTORE counter decrement + + gas_costs.GAS_BASE * 2 # ISZERO * 2 for loop condition (2*2) + + gas_costs.GAS_MID # JUMPI (8) ) # ERC20 balanceOf internal gas sload_erc20_internal = ( - gas_costs.G_VERY_LOW # PUSH4 selector (3) - + gas_costs.G_BASE # EQ selector match (2) - + gas_costs.G_MID # JUMPI to function (8) - + gas_costs.G_JUMPDEST # JUMPDEST at function start (1) - + gas_costs.G_VERY_LOW * 2 # CALLDATALOAD arg (3*2) - + gas_costs.G_KECCAK_256 # keccak256 static (30) - + gas_costs.G_KECCAK_256_WORD * 2 # keccak256 dynamic 64 bytes - + gas_costs.G_COLD_SLOAD # Cold SLOAD - always cold - + gas_costs.G_VERY_LOW * 3 # MSTORE result + RETURN setup (3*3) + gas_costs.GAS_VERY_LOW # PUSH4 selector (3) + + gas_costs.GAS_BASE # EQ selector match (2) + + gas_costs.GAS_MID # JUMPI to function (8) + + gas_costs.GAS_JUMPDEST # JUMPDEST at function start (1) + + gas_costs.GAS_VERY_LOW * 2 # CALLDATALOAD arg (3*2) + + gas_costs.GAS_KECCAK256 # keccak256 static (30) + + gas_costs.GAS_KECCAK256_WORD * 2 # keccak256 dynamic 64 bytes + + gas_costs.GAS_COLD_SLOAD # Cold SLOAD - always cold + + gas_costs.GAS_VERY_LOW * 3 # MSTORE result + RETURN setup (3*3) ) # Fixed overhead for SSTORE loop sstore_loop_overhead = ( # Attack contract loop body operations - gas_costs.G_VERY_LOW # MSTORE selector at memory[32] (3) - + gas_costs.G_LOW # MLOAD counter (5) - + gas_costs.G_VERY_LOW # MSTORE spender at memory[64] (3) - + gas_costs.G_BASE # POP call result (2) + gas_costs.GAS_VERY_LOW # MSTORE selector at memory[32] (3) + + gas_costs.GAS_LOW # MLOAD counter (5) + + gas_costs.GAS_VERY_LOW # MSTORE spender at memory[64] (3) + + gas_costs.GAS_BASE # POP call result (2) # Counter decrement - + gas_costs.G_LOW # MLOAD counter (5) - + gas_costs.G_VERY_LOW # PUSH1 1 (3) - + gas_costs.G_VERY_LOW # SUB (3) - + gas_costs.G_VERY_LOW # MSTORE counter back (3) + + gas_costs.GAS_LOW # MLOAD counter (5) + + gas_costs.GAS_VERY_LOW # PUSH1 1 (3) + + gas_costs.GAS_VERY_LOW # SUB (3) + + gas_costs.GAS_VERY_LOW # MSTORE counter back (3) # While loop condition check - + gas_costs.G_LOW # MLOAD counter (5) - + gas_costs.G_BASE # ISZERO (2) - + gas_costs.G_BASE # ISZERO (2) - + gas_costs.G_MID # JUMPI back to loop start (8) + + gas_costs.GAS_LOW # MLOAD counter (5) + + gas_costs.GAS_BASE # ISZERO (2) + + gas_costs.GAS_BASE # ISZERO (2) + + gas_costs.GAS_MID # JUMPI back to loop start (8) ) # ERC20 approve internal gas # Cold SSTORE: 22100 = 20000 base + 2100 cold access sstore_erc20_internal = ( - gas_costs.G_VERY_LOW # PUSH4 selector (3) - + gas_costs.G_BASE # EQ selector match (2) - + gas_costs.G_MID # JUMPI to function (8) - + gas_costs.G_JUMPDEST # JUMPDEST at function start (1) - + gas_costs.G_VERY_LOW # CALLDATALOAD spender (3) - + gas_costs.G_VERY_LOW # CALLDATALOAD amount (3) - + gas_costs.G_KECCAK_256 # keccak256 static (30) - + gas_costs.G_KECCAK_256_WORD * 2 # keccak256 dynamic 64 bytes - + gas_costs.G_COLD_SLOAD # Cold SLOAD for allowance check (2100) - + gas_costs.G_STORAGE_SET # SSTORE base cost (20000) - + gas_costs.G_COLD_SLOAD # Additional cold storage access (2100) - + gas_costs.G_VERY_LOW # PUSH1 1 for return value (3) - + gas_costs.G_VERY_LOW # MSTORE return value (3) - + gas_costs.G_VERY_LOW # PUSH1 32 for return size (3) - + gas_costs.G_VERY_LOW # PUSH1 0 for return offset (3) + gas_costs.GAS_VERY_LOW # PUSH4 selector (3) + + gas_costs.GAS_BASE # EQ selector match (2) + + gas_costs.GAS_MID # JUMPI to function (8) + + gas_costs.GAS_JUMPDEST # JUMPDEST at function start (1) + + gas_costs.GAS_VERY_LOW # CALLDATALOAD spender (3) + + gas_costs.GAS_VERY_LOW # CALLDATALOAD amount (3) + + gas_costs.GAS_KECCAK256 # keccak256 static (30) + + gas_costs.GAS_KECCAK256_WORD * 2 # keccak256 dynamic 64 bytes + + gas_costs.GAS_COLD_SLOAD # Cold SLOAD for allowance check (2100) + + gas_costs.GAS_STORAGE_SET # SSTORE base cost (20000) + + gas_costs.GAS_COLD_SLOAD # Additional cold storage access (2100) + + gas_costs.GAS_VERY_LOW # PUSH1 1 for return value (3) + + gas_costs.GAS_VERY_LOW # MSTORE return value (3) + + gas_costs.GAS_VERY_LOW # PUSH1 32 for return size (3) + + gas_costs.GAS_VERY_LOW # PUSH1 0 for return offset (3) ) # Calculate gas budget per contract @@ -651,12 +651,10 @@ def test_mixed_sload_sstore( # Account for cold/warm transitions in CALL costs # First SLOAD call is COLD (2600), rest are WARM (100) sload_warm_cost = ( - sload_loop_overhead - + gas_costs.G_WARM_ACCOUNT_ACCESS - + sload_erc20_internal + sload_loop_overhead + gas_costs.GAS_WARM_ACCESS + sload_erc20_internal ) cold_warm_diff = ( - gas_costs.G_COLD_ACCOUNT_ACCESS - gas_costs.G_WARM_ACCOUNT_ACCESS + gas_costs.GAS_COLD_ACCOUNT_ACCESS - gas_costs.GAS_WARM_ACCESS ) sload_calls_per_contract = int( (sload_gas_per_contract - cold_warm_diff) // sload_warm_cost @@ -665,7 +663,7 @@ def test_mixed_sload_sstore( # First SSTORE call is COLD (2600), rest are WARM (100) sstore_warm_cost = ( sstore_loop_overhead - + gas_costs.G_WARM_ACCOUNT_ACCESS + + gas_costs.GAS_WARM_ACCESS + sstore_erc20_internal ) sstore_calls_per_contract = int( diff --git a/tests/benchmark/stateful/bloatnet/test_single_opcode.py b/tests/benchmark/stateful/bloatnet/test_single_opcode.py index 34e2c46434..d426c7af3e 100644 --- a/tests/benchmark/stateful/bloatnet/test_single_opcode.py +++ b/tests/benchmark/stateful/bloatnet/test_single_opcode.py @@ -131,26 +131,26 @@ def test_sload_empty_erc20_balanceof( # Fixed overhead per iteration (loop mechanics, independent of warm/cold) loop_overhead = ( # Attack contract loop overhead - gas_costs.G_VERY_LOW * 2 # MLOAD counter (3*2) - + gas_costs.G_VERY_LOW * 2 # MSTORE selector (3*2) - + gas_costs.G_VERY_LOW * 3 # MLOAD + MSTORE address (3*3) - + gas_costs.G_BASE # POP (2) - + gas_costs.G_BASE * 3 # SUB + MLOAD + MSTORE counter decrement - + gas_costs.G_BASE * 2 # ISZERO * 2 for loop condition (2*2) - + gas_costs.G_MID # JUMPI (8) + gas_costs.GAS_VERY_LOW * 2 # MLOAD counter (3*2) + + gas_costs.GAS_VERY_LOW * 2 # MSTORE selector (3*2) + + gas_costs.GAS_VERY_LOW * 3 # MLOAD + MSTORE address (3*3) + + gas_costs.GAS_BASE # POP (2) + + gas_costs.GAS_BASE * 3 # SUB + MLOAD + MSTORE counter decrement + + gas_costs.GAS_BASE * 2 # ISZERO * 2 for loop condition (2*2) + + gas_costs.GAS_MID # JUMPI (8) ) # ERC20 internal gas (same for all calls) erc20_internal_gas = ( - gas_costs.G_VERY_LOW # PUSH4 selector (3) - + gas_costs.G_BASE # EQ selector match (2) - + gas_costs.G_MID # JUMPI to function (8) - + gas_costs.G_JUMPDEST # JUMPDEST at function start (1) - + gas_costs.G_VERY_LOW * 2 # CALLDATALOAD arg (3*2) - + gas_costs.G_KECCAK_256 # keccak256 static (30) - + gas_costs.G_KECCAK_256_WORD * 2 # keccak256 dynamic 64 bytes - + gas_costs.G_COLD_SLOAD # Cold SLOAD - always cold - + gas_costs.G_VERY_LOW * 3 # MSTORE result + RETURN setup (3*3) + gas_costs.GAS_VERY_LOW # PUSH4 selector (3) + + gas_costs.GAS_BASE # EQ selector match (2) + + gas_costs.GAS_MID # JUMPI to function (8) + + gas_costs.GAS_JUMPDEST # JUMPDEST at function start (1) + + gas_costs.GAS_VERY_LOW * 2 # CALLDATALOAD arg (3*2) + + gas_costs.GAS_KECCAK256 # keccak256 static (30) + + gas_costs.GAS_KECCAK256_WORD * 2 # keccak256 dynamic 64 bytes + + gas_costs.GAS_COLD_SLOAD # Cold SLOAD - always cold + + gas_costs.GAS_VERY_LOW * 3 # MSTORE result + RETURN setup (3*3) # RETURN costs 0 gas ) @@ -163,10 +163,10 @@ def test_sload_empty_erc20_balanceof( # gas_per_contract = cold_call + (calls-1) * warm_call # Simplifies to: gas = cold_warm_diff + calls * warm_call_cost warm_call_cost = ( - loop_overhead + gas_costs.G_WARM_ACCOUNT_ACCESS + erc20_internal_gas + loop_overhead + gas_costs.GAS_WARM_ACCESS + erc20_internal_gas ) cold_warm_diff = ( - gas_costs.G_COLD_ACCOUNT_ACCESS - gas_costs.G_WARM_ACCOUNT_ACCESS + gas_costs.GAS_COLD_ACCOUNT_ACCESS - gas_costs.GAS_WARM_ACCESS ) calls_per_contract = int( @@ -302,54 +302,54 @@ def test_sstore_erc20_approve( # Per-contract fixed overhead (setup + teardown) memory_expansion_cost = 15 # Memory expansion to 160 bytes (5 words) overhead_per_contract = ( - gas_costs.G_VERY_LOW # MSTORE to initialize counter (3) + gas_costs.GAS_VERY_LOW # MSTORE to initialize counter (3) + memory_expansion_cost # Memory expansion (15) - + gas_costs.G_JUMPDEST # JUMPDEST at loop start (1) - + gas_costs.G_LOW # MLOAD for While condition check (5) - + gas_costs.G_BASE # ISZERO (2) - + gas_costs.G_BASE # ISZERO (2) - + gas_costs.G_MID # JUMPI (8) - + gas_costs.G_BASE # POP to clean up counter at end (2) + + gas_costs.GAS_JUMPDEST # JUMPDEST at loop start (1) + + gas_costs.GAS_LOW # MLOAD for While condition check (5) + + gas_costs.GAS_BASE # ISZERO (2) + + gas_costs.GAS_BASE # ISZERO (2) + + gas_costs.GAS_MID # JUMPI (8) + + gas_costs.GAS_BASE # POP to clean up counter at end (2) ) # = 38 # Fixed overhead per iteration (loop mechanics, independent of warm/cold) loop_overhead = ( # Attack contract loop body operations - gas_costs.G_VERY_LOW # MSTORE selector at memory[32] (3) - + gas_costs.G_LOW # MLOAD counter (5) - + gas_costs.G_VERY_LOW # MSTORE spender at memory[64] (3) - + gas_costs.G_BASE # POP call result (2) + gas_costs.GAS_VERY_LOW # MSTORE selector at memory[32] (3) + + gas_costs.GAS_LOW # MLOAD counter (5) + + gas_costs.GAS_VERY_LOW # MSTORE spender at memory[64] (3) + + gas_costs.GAS_BASE # POP call result (2) # Counter decrement: MSTORE(0, SUB(MLOAD(0), 1)) - + gas_costs.G_LOW # MLOAD counter (5) - + gas_costs.G_VERY_LOW # PUSH1 1 (3) - + gas_costs.G_VERY_LOW # SUB (3) - + gas_costs.G_VERY_LOW # MSTORE counter back (3) + + gas_costs.GAS_LOW # MLOAD counter (5) + + gas_costs.GAS_VERY_LOW # PUSH1 1 (3) + + gas_costs.GAS_VERY_LOW # SUB (3) + + gas_costs.GAS_VERY_LOW # MSTORE counter back (3) # While loop condition check - + gas_costs.G_LOW # MLOAD counter (5) - + gas_costs.G_BASE # ISZERO (2) - + gas_costs.G_BASE # ISZERO (2) - + gas_costs.G_MID # JUMPI back to loop start (8) + + gas_costs.GAS_LOW # MLOAD counter (5) + + gas_costs.GAS_BASE # ISZERO (2) + + gas_costs.GAS_BASE # ISZERO (2) + + gas_costs.GAS_MID # JUMPI back to loop start (8) ) # ERC20 internal gas (same for all calls) # Note: SSTORE cost is 22100 for cold slot, zero-to-non-zero # (20000 base + 2100 cold access) erc20_internal_gas = ( - gas_costs.G_VERY_LOW # PUSH4 selector (3) - + gas_costs.G_BASE # EQ selector match (2) - + gas_costs.G_MID # JUMPI to function (8) - + gas_costs.G_JUMPDEST # JUMPDEST at function start (1) - + gas_costs.G_VERY_LOW # CALLDATALOAD spender (3) - + gas_costs.G_VERY_LOW # CALLDATALOAD amount (3) - + gas_costs.G_KECCAK_256 # keccak256 static (30) - + gas_costs.G_KECCAK_256_WORD * 2 # keccak256 dynamic 64 bytes - + gas_costs.G_COLD_SLOAD # Cold SLOAD for allowance check (2100) - + gas_costs.G_STORAGE_SET # SSTORE base cost (20000) - + gas_costs.G_COLD_SLOAD # Additional cold storage access (2100) - + gas_costs.G_VERY_LOW # PUSH1 1 for return value (3) - + gas_costs.G_VERY_LOW # MSTORE return value (3) - + gas_costs.G_VERY_LOW # PUSH1 32 for return size (3) - + gas_costs.G_VERY_LOW # PUSH1 0 for return offset (3) + gas_costs.GAS_VERY_LOW # PUSH4 selector (3) + + gas_costs.GAS_BASE # EQ selector match (2) + + gas_costs.GAS_MID # JUMPI to function (8) + + gas_costs.GAS_JUMPDEST # JUMPDEST at function start (1) + + gas_costs.GAS_VERY_LOW # CALLDATALOAD spender (3) + + gas_costs.GAS_VERY_LOW # CALLDATALOAD amount (3) + + gas_costs.GAS_KECCAK256 # keccak256 static (30) + + gas_costs.GAS_KECCAK256_WORD * 2 # keccak256 dynamic 64 bytes + + gas_costs.GAS_COLD_SLOAD # Cold SLOAD for allowance check (2100) + + gas_costs.GAS_STORAGE_SET # SSTORE base cost (20000) + + gas_costs.GAS_COLD_SLOAD # Additional cold storage access (2100) + + gas_costs.GAS_VERY_LOW # PUSH1 1 for return value (3) + + gas_costs.GAS_VERY_LOW # MSTORE return value (3) + + gas_costs.GAS_VERY_LOW # PUSH1 32 for return size (3) + + gas_costs.GAS_VERY_LOW # PUSH1 0 for return offset (3) # RETURN costs 0 gas ) @@ -360,10 +360,10 @@ def test_sstore_erc20_approve( # For each contract: first call is COLD (2600), subsequent are WARM (100) # Solve for calls per contract accounting for cold/warm transition warm_call_cost = ( - loop_overhead + gas_costs.G_WARM_ACCOUNT_ACCESS + erc20_internal_gas + loop_overhead + gas_costs.GAS_WARM_ACCESS + erc20_internal_gas ) cold_warm_diff = ( - gas_costs.G_COLD_ACCOUNT_ACCESS - gas_costs.G_WARM_ACCOUNT_ACCESS + gas_costs.GAS_COLD_ACCOUNT_ACCESS - gas_costs.GAS_WARM_ACCESS ) # Per contract: gas_available = cold_warm_diff + calls * warm_call_cost diff --git a/tests/berlin/eip2929_gas_cost_increases/test_call.py b/tests/berlin/eip2929_gas_cost_increases/test_call.py index a1b6238085..8761f649f4 100644 --- a/tests/berlin/eip2929_gas_cost_increases/test_call.py +++ b/tests/berlin/eip2929_gas_cost_increases/test_call.py @@ -43,7 +43,7 @@ def test_call_insufficient_balance( # Measure the gas cost for BALANCE operation + CodeGasMeasure( code=Op.BALANCE(destination), - overhead_cost=gas_costs.G_VERY_LOW, # PUSH20 costs 3 gas + overhead_cost=gas_costs.GAS_VERY_LOW, # PUSH20 costs 3 gas extra_stack_items=1, # BALANCE puts balance on stack sstore_key=1, ), @@ -63,7 +63,7 @@ def test_call_insufficient_balance( contract_address: Account( storage={ 0: 0, # The CALL is aborted - 1: gas_costs.G_WARM_ACCOUNT_ACCESS, # Warm access cost + 1: gas_costs.GAS_WARM_ACCESS, # Warm access cost }, ), } diff --git a/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py b/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py index ebc05614fa..dc00661c1a 100644 --- a/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py +++ b/tests/berlin/eip2929_gas_cost_increases/test_precompile_warming.py @@ -162,9 +162,9 @@ def test_precompile_warming( def get_expected_gas(precompile_present: bool, fork: Fork) -> int: gas_costs = fork.gas_costs() - warm_access_cost = gas_costs.G_WARM_ACCOUNT_ACCESS - cold_access_cost = gas_costs.G_COLD_ACCOUNT_ACCESS - extra_cost = gas_costs.G_BASE * 2 + gas_costs.G_VERY_LOW + warm_access_cost = gas_costs.GAS_WARM_ACCESS + cold_access_cost = gas_costs.GAS_COLD_ACCOUNT_ACCESS + extra_cost = gas_costs.GAS_BASE * 2 + gas_costs.GAS_VERY_LOW if precompile_present: return warm_access_cost + extra_cost else: diff --git a/tests/berlin/eip2930_access_list/test_acl.py b/tests/berlin/eip2930_access_list/test_acl.py index d96c520537..186b02a1fb 100644 --- a/tests/berlin/eip2930_access_list/test_acl.py +++ b/tests/berlin/eip2930_access_list/test_acl.py @@ -46,10 +46,10 @@ def test_account_storage_warm_cold_state( storage_reader_contract = pre.deploy_contract(Op.SLOAD(1) + Op.STOP) overhead_cost = ( - gas_costs.G_VERY_LOW + gas_costs.GAS_VERY_LOW * (Op.CALL.popped_stack_items - 1) # Call stack items - + gas_costs.G_BASE # Call gas - + gas_costs.G_VERY_LOW # SLOAD Push + + gas_costs.GAS_BASE # Call gas + + gas_costs.GAS_VERY_LOW # SLOAD Push ) contract_address = pre.deploy_contract( CodeGasMeasure( @@ -63,15 +63,15 @@ def test_account_storage_warm_cold_state( access_list_address = Address(0) access_list_storage_key = Hash(0) if account_warm: - expected_gas_cost += gas_costs.G_WARM_ACCOUNT_ACCESS + expected_gas_cost += gas_costs.GAS_WARM_ACCESS access_list_address = storage_reader_contract else: - expected_gas_cost += gas_costs.G_COLD_ACCOUNT_ACCESS + expected_gas_cost += gas_costs.GAS_COLD_ACCOUNT_ACCESS if storage_key_warm: - expected_gas_cost += gas_costs.G_WARM_SLOAD + expected_gas_cost += gas_costs.GAS_WARM_ACCESS access_list_storage_key = Hash(1) else: - expected_gas_cost += gas_costs.G_COLD_SLOAD + expected_gas_cost += gas_costs.GAS_COLD_SLOAD access_lists: List[AccessList] = [ AccessList( @@ -293,7 +293,7 @@ def test_repeated_address_acl( sload0_measure = CodeGasMeasure( code=Op.SLOAD(0), - overhead_cost=gsc.G_VERY_LOW + overhead_cost=gsc.GAS_VERY_LOW * len(Op.SLOAD.kwargs), # Cost of pushing SLOAD args extra_stack_items=1, # SLOAD pushes 1 item to the stack sstore_key=0, @@ -302,7 +302,7 @@ def test_repeated_address_acl( sload1_measure = CodeGasMeasure( code=Op.SLOAD(1), - overhead_cost=gsc.G_VERY_LOW + overhead_cost=gsc.GAS_VERY_LOW * len(Op.SLOAD.kwargs), # Cost of pushing SLOAD args extra_stack_items=1, # SLOAD pushes 1 item to the stack sstore_key=1, @@ -327,7 +327,7 @@ def test_repeated_address_acl( ], ) - sload_cost = gsc.G_WARM_ACCOUNT_ACCESS + sload_cost = gsc.GAS_WARM_ACCESS state_test( env=Environment(), diff --git a/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py b/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py index 9b12efb34d..6221ecb0c8 100644 --- a/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py +++ b/tests/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py @@ -98,8 +98,8 @@ def call_exact_cost( calldatacopy_cost += 3 * ((len(initial_memory) + 31) // 32) calldatacopy_cost += cost_memory_bytes(new_bytes=len(initial_memory)) - pushes_cost = gas_costs.G_VERY_LOW * 9 - calldatasize_cost = gas_costs.G_BASE + pushes_cost = gas_costs.GAS_VERY_LOW * 9 + calldatasize_cost = gas_costs.GAS_BASE sstore_cost = 22100 return ( diff --git a/tests/frontier/opcodes/test_call.py b/tests/frontier/opcodes/test_call.py index 688e206b8f..6a5b773ae5 100644 --- a/tests/frontier/opcodes/test_call.py +++ b/tests/frontier/opcodes/test_call.py @@ -37,7 +37,7 @@ def test_call_large_offset_mstore( call_measure = CodeGasMeasure( code=Op.CALL(gas=0, ret_offset=mem_offset, ret_size=0), # Cost of pushing CALL args - overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), + overhead_cost=gsc.GAS_VERY_LOW * len(Op.CALL.kwargs), extra_stack_items=1, # Because CALL pushes 1 item to the stack sstore_key=0, stop=False, # Because it's the first CodeGasMeasure @@ -45,7 +45,7 @@ def test_call_large_offset_mstore( mstore_measure = CodeGasMeasure( code=Op.MSTORE(offset=mem_offset, value=1), # Cost of pushing MSTORE args - overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), + overhead_cost=gsc.GAS_VERY_LOW * len(Op.MSTORE.kwargs), extra_stack_items=0, sstore_key=1, ) @@ -60,11 +60,11 @@ def test_call_large_offset_mstore( ) # this call cost is just the address_access_cost - call_cost = gsc.G_COLD_ACCOUNT_ACCESS + call_cost = gsc.GAS_COLD_ACCOUNT_ACCESS memory_expansion_gas_calc = fork.memory_expansion_gas_calculator() # mstore cost: base cost + expansion cost - mstore_cost = gsc.G_MEMORY + memory_expansion_gas_calc( + mstore_cost = gsc.GAS_MEMORY + memory_expansion_gas_calc( new_bytes=mem_offset + 1 ) state_test( @@ -108,7 +108,7 @@ def test_call_memory_expands_on_early_revert( # CALL with value code=Op.CALL(gas=0, value=100, ret_size=ret_size), # Cost of pushing CALL args - overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), + overhead_cost=gsc.GAS_VERY_LOW * len(Op.CALL.kwargs), # Because CALL pushes 1 item to the stack extra_stack_items=1, sstore_key=0, @@ -119,7 +119,7 @@ def test_call_memory_expands_on_early_revert( # Low offset for not expanding memory code=Op.MSTORE(offset=ret_size // 2, value=1), # Cost of pushing MSTORE args - overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), + overhead_cost=gsc.GAS_VERY_LOW * len(Op.MSTORE.kwargs), extra_stack_items=0, sstore_key=1, ) @@ -140,16 +140,16 @@ def test_call_memory_expands_on_early_revert( # call cost: # address_access_cost+new_acc_cost+memory_expansion_cost+value-stipend call_cost = ( - gsc.G_COLD_ACCOUNT_ACCESS - + gsc.G_NEW_ACCOUNT + gsc.GAS_COLD_ACCOUNT_ACCESS + + gsc.GAS_NEW_ACCOUNT + memory_expansion_gas_calc(new_bytes=ret_size) - + gsc.G_CALL_VALUE - - gsc.G_CALL_STIPEND + + gsc.GAS_CALL_VALUE + - gsc.GAS_CALL_STIPEND ) # mstore cost: base cost. No memory expansion cost needed, it was expanded # on CALL. - mstore_cost = gsc.G_MEMORY + mstore_cost = gsc.GAS_MEMORY state_test( env=Environment(), pre=pre, @@ -188,7 +188,7 @@ def test_call_large_args_offset_size_zero( call_measure = CodeGasMeasure( code=call_opcode(gas=0, args_offset=very_large_offset, args_size=0), # Cost of pushing xCALL args - overhead_cost=gsc.G_VERY_LOW * len(call_opcode.kwargs), + overhead_cost=gsc.GAS_VERY_LOW * len(call_opcode.kwargs), extra_stack_items=1, # Because xCALL pushes 1 item to the stack sstore_key=0, ) @@ -203,7 +203,7 @@ def test_call_large_args_offset_size_zero( ) # this call cost is just the address_access_cost - call_cost = gsc.G_COLD_ACCOUNT_ACCESS + call_cost = gsc.GAS_COLD_ACCOUNT_ACCESS state_test( env=Environment(), diff --git a/tests/osaka/eip7823_modexp_upper_bounds/conftest.py b/tests/osaka/eip7823_modexp_upper_bounds/conftest.py index 314421a074..249e7b47e2 100644 --- a/tests/osaka/eip7823_modexp_upper_bounds/conftest.py +++ b/tests/osaka/eip7823_modexp_upper_bounds/conftest.py @@ -89,10 +89,10 @@ def gas_measure_contract( gas_costs = fork.gas_costs() extra_gas = ( - gas_costs.G_WARM_ACCOUNT_ACCESS - + (gas_costs.G_VERY_LOW * (len(Op.CALL.kwargs) - 1)) - + gas_costs.G_BASE # CALLDATASIZE - + gas_costs.G_BASE # GAS + gas_costs.GAS_WARM_ACCESS + + (gas_costs.GAS_VERY_LOW * (len(Op.CALL.kwargs) - 1)) + + gas_costs.GAS_BASE # CALLDATASIZE + + gas_costs.GAS_BASE # GAS ) # Build the gas measurement contract code diff --git a/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py b/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py index 8e8f8d01ce..afebc9d2af 100644 --- a/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py +++ b/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py @@ -254,9 +254,11 @@ def test_maximum_gas_refund( # Base Operation: SSTORE(slot, 0) iteration_cost = ( - gas_costs.G_STORAGE_RESET + gas_costs.G_BASE + gas_costs.G_VERY_LOW + gas_costs.GAS_STORAGE_UPDATE + + gas_costs.GAS_BASE + + gas_costs.GAS_VERY_LOW ) - gas_refund = gas_costs.R_STORAGE_CLEAR + gas_refund = gas_costs.GAS_STORAGE_CLEAR_REFUND # EIP-3529: Reduction in refunds storage_count = tx_gas_limit_cap // iteration_cost @@ -305,7 +307,7 @@ def test_maximum_gas_refund( def total_cost_floor_per_token(fork: Fork) -> int: """Total cost floor per token.""" gas_costs = fork.gas_costs() - return gas_costs.G_TX_DATA_FLOOR_TOKEN_COST + return gas_costs.FLOOR_CALLDATA_COST @pytest.mark.xdist_group(name="bigmem") @@ -484,8 +486,8 @@ def test_tx_gas_limit_cap_access_list_with_diff_keys( gas_available = tx_gas_limit_cap - intrinsic_cost() gas_costs = fork.gas_costs() - gas_per_address = gas_costs.G_ACCESS_LIST_ADDRESS - gas_per_storage_key = gas_costs.G_ACCESS_LIST_STORAGE + gas_per_address = gas_costs.TX_ACCESS_LIST_ADDRESS_COST + gas_per_storage_key = gas_costs.TX_ACCESS_LIST_STORAGE_KEY_COST gas_after_address = gas_available - gas_per_address num_storage_keys = gas_after_address // gas_per_storage_key + int( @@ -569,8 +571,8 @@ def test_tx_gas_limit_cap_access_list_with_diff_addr( gas_available = tx_gas_limit_cap - intrinsic_cost() gas_costs = fork.gas_costs() - gas_per_address = gas_costs.G_ACCESS_LIST_ADDRESS - gas_per_storage_key = gas_costs.G_ACCESS_LIST_STORAGE + gas_per_address = gas_costs.TX_ACCESS_LIST_ADDRESS_COST + gas_per_storage_key = gas_costs.TX_ACCESS_LIST_STORAGE_KEY_COST account_num = gas_available // ( gas_per_address + gas_per_storage_key @@ -646,7 +648,7 @@ def test_tx_gas_limit_cap_authorized_tx( gas_available = tx_gas_limit_cap - intrinsic_cost() gas_costs = fork.gas_costs() - gas_per_address = gas_costs.G_ACCESS_LIST_ADDRESS + gas_per_address = gas_costs.TX_ACCESS_LIST_ADDRESS_COST per_empty_account_cost = 25_000 auth_list_length = gas_available // ( diff --git a/tests/osaka/eip7883_modexp_gas_increase/conftest.py b/tests/osaka/eip7883_modexp_gas_increase/conftest.py index 319c234c23..6854784b50 100644 --- a/tests/osaka/eip7883_modexp_gas_increase/conftest.py +++ b/tests/osaka/eip7883_modexp_gas_increase/conftest.py @@ -60,7 +60,9 @@ def total_tx_gas_needed( fork.transaction_intrinsic_cost_calculator() ) memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() - sstore_gas = fork.gas_costs().G_STORAGE_SET * (len(modexp_expected) // 32) + sstore_gas = fork.gas_costs().GAS_STORAGE_SET * ( + len(modexp_expected) // 32 + ) extra_gas = 100_000 return ( @@ -154,10 +156,10 @@ def gas_measure_contract( gas_costs = fork.gas_costs() extra_gas = ( - gas_costs.G_WARM_ACCOUNT_ACCESS - + (gas_costs.G_VERY_LOW * (len(call_opcode.kwargs) - 1)) - + gas_costs.G_BASE # CALLDATASIZE - + gas_costs.G_BASE # GAS + gas_costs.GAS_WARM_ACCESS + + (gas_costs.GAS_VERY_LOW * (len(call_opcode.kwargs) - 1)) + + gas_costs.GAS_BASE # CALLDATASIZE + + gas_costs.GAS_BASE # GAS ) # Build the gas measurement contract code diff --git a/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py b/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py index be711225a2..e23b50e652 100644 --- a/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py +++ b/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py @@ -57,9 +57,9 @@ def test_modexp_fork_transition( gas_costs = fork.gas_costs() extra_gas = ( - gas_costs.G_WARM_ACCOUNT_ACCESS - + (gas_costs.G_VERY_LOW * (len(Op.CALL.kwargs) - 2)) - + (gas_costs.G_BASE * 3) + gas_costs.GAS_WARM_ACCESS + + (gas_costs.GAS_VERY_LOW * (len(Op.CALL.kwargs) - 2)) + + (gas_costs.GAS_BASE * 3) ) code = ( Op.CALLDATACOPY(dest_offset=0, offset=0, size=Op.CALLDATASIZE) diff --git a/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py b/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py index ff1da2f5ee..cb07d56ec0 100644 --- a/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py +++ b/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py @@ -136,7 +136,7 @@ def test_clz_gas_cost( CodeGasMeasure( code=Op.CLZ(Op.PUSH1(1)), extra_stack_items=1, - overhead_cost=fork.gas_costs().G_VERY_LOW, + overhead_cost=fork.gas_costs().GAS_VERY_LOW, ), ), storage={"0x00": "0xdeadbeef"}, @@ -145,7 +145,7 @@ def test_clz_gas_cost( tx = Transaction(to=contract_address, sender=sender, gas_limit=200_000) post = { contract_address: Account( # Cost measured is CLZ + PUSH1 - storage={"0x00": fork.gas_costs().G_LOW} + storage={"0x00": fork.gas_costs().GAS_LOW} ), } state_test(pre=pre, post=post, tx=tx) @@ -172,7 +172,7 @@ def test_clz_gas_cost_boundary( call_code = Op.SSTORE( 0, Op.CALL( - gas=fork.gas_costs().G_VERY_LOW + gas=fork.gas_costs().GAS_VERY_LOW + Spec.CLZ_GAS_COST + gas_cost_delta, address=contract_address, diff --git a/tests/prague/eip7623_increase_calldata_cost/test_refunds.py b/tests/prague/eip7623_increase_calldata_cost/test_refunds.py index 7e61fa058b..dadd7ec6b1 100644 --- a/tests/prague/eip7623_increase_calldata_cost/test_refunds.py +++ b/tests/prague/eip7623_increase_calldata_cost/test_refunds.py @@ -94,12 +94,12 @@ def max_refund(fork: Fork, refund_type: RefundType) -> int: """Return the max refund gas of the transaction.""" gas_costs = fork.gas_costs() max_refund = ( - gas_costs.R_STORAGE_CLEAR + gas_costs.GAS_STORAGE_CLEAR_REFUND if RefundType.STORAGE_CLEAR in refund_type else 0 ) max_refund += ( - gas_costs.R_AUTHORIZATION_EXISTING_AUTHORITY + gas_costs.PER_AUTH_BASE_COST if RefundType.AUTHORIZATION_EXISTING_AUTHORITY in refund_type else 0 ) @@ -113,9 +113,9 @@ def prefix_code_gas(fork: Fork, refund_type: RefundType) -> int: # Minimum code to generate a storage clear is Op.SSTORE(0, 0). gas_costs = fork.gas_costs() return ( - gas_costs.G_COLD_SLOAD - + gas_costs.G_STORAGE_RESET - + (gas_costs.G_VERY_LOW * 2) + gas_costs.GAS_COLD_SLOAD + + gas_costs.GAS_STORAGE_UPDATE + + (gas_costs.GAS_VERY_LOW * 2) ) return 0 diff --git a/tests/prague/eip7702_set_code_tx/test_eip_mainnet.py b/tests/prague/eip7702_set_code_tx/test_eip_mainnet.py index 6470700815..3215d37311 100644 --- a/tests/prague/eip7702_set_code_tx/test_eip_mainnet.py +++ b/tests/prague/eip7702_set_code_tx/test_eip_mainnet.py @@ -57,9 +57,9 @@ def test_eip_7702( authorization_list_or_count=authorization_list, ) execution_cost = ( - (gas_costs.G_COLD_SLOAD + gas_costs.G_STORAGE_SET) * 3 - + (gas_costs.G_VERY_LOW * 3) - + (gas_costs.G_BASE * 3) + (gas_costs.GAS_COLD_SLOAD + gas_costs.GAS_STORAGE_SET) * 3 + + (gas_costs.GAS_VERY_LOW * 3) + + (gas_costs.GAS_BASE * 3) ) tx = Transaction( diff --git a/tests/prague/eip7702_set_code_tx/test_gas.py b/tests/prague/eip7702_set_code_tx/test_gas.py index 048a84c44b..06e8b35cc1 100644 --- a/tests/prague/eip7702_set_code_tx/test_gas.py +++ b/tests/prague/eip7702_set_code_tx/test_gas.py @@ -885,12 +885,12 @@ def test_gas_cost( # fifth (EIP-3529) of the total gas used, so we can see the full discount # being reflected in most of the tests. gas_costs = fork.gas_costs() - gas_opcode_cost = gas_costs.G_BASE + gas_opcode_cost = gas_costs.GAS_BASE sstore_opcode_count = 10 push_opcode_count = (2 * (sstore_opcode_count)) - 1 - push_opcode_cost = gas_costs.G_VERY_LOW * push_opcode_count - sstore_opcode_cost = gas_costs.G_STORAGE_SET * sstore_opcode_count - cold_storage_cost = gas_costs.G_COLD_SLOAD * sstore_opcode_count + push_opcode_cost = gas_costs.GAS_VERY_LOW * push_opcode_count + sstore_opcode_cost = gas_costs.GAS_STORAGE_SET * sstore_opcode_count + cold_storage_cost = gas_costs.GAS_COLD_SLOAD * sstore_opcode_count execution_gas = ( gas_opcode_cost @@ -1259,8 +1259,8 @@ def test_call_to_pre_authorized_oog( ) tx_gas_limit = ( intrinsic_gas_cost_calculator() - + len(call_opcode.kwargs) * gas_costs.G_VERY_LOW - + (gas_costs.G_COLD_ACCOUNT_ACCESS * 2) + + len(call_opcode.kwargs) * gas_costs.GAS_VERY_LOW + + (gas_costs.GAS_COLD_ACCOUNT_ACCESS * 2) - 1 ) tx = Transaction( diff --git a/tests/prague/eip7702_set_code_tx/test_set_code_txs_2.py b/tests/prague/eip7702_set_code_tx/test_set_code_txs_2.py index 3c2db4b0f8..5401d8b912 100644 --- a/tests/prague/eip7702_set_code_tx/test_set_code_txs_2.py +++ b/tests/prague/eip7702_set_code_tx/test_set_code_txs_2.py @@ -593,14 +593,14 @@ def test_gas_diff_pointer_vs_direct_call( opcodes_price = 37 direct_call_gas: int = ( # 20_000 + 2_600 + 2_100 + 37 = 24737 - gas_costs.G_STORAGE_SET + gas_costs.GAS_STORAGE_SET + ( # access account price # If storage and account is declared in access list then discount - gas_costs.G_WARM_ACCOUNT_ACCESS + gas_costs.G_WARM_SLOAD + gas_costs.GAS_WARM_ACCESS + gas_costs.GAS_WARM_ACCESS if access_list_rule in [AccessListCall.IN_NORMAL_TX_ONLY, AccessListCall.IN_BOTH_TX] - else gas_costs.G_COLD_ACCOUNT_ACCESS + gas_costs.G_COLD_SLOAD + else gas_costs.GAS_COLD_ACCOUNT_ACCESS + gas_costs.GAS_COLD_SLOAD ) + opcodes_price ) @@ -622,10 +622,10 @@ def test_gas_diff_pointer_vs_direct_call( # contract call is hot, pointer call is call because pointer is set # only sload is hot because access list is for contract # 20_000 + 100 + 100 + 2100 + 37 = 22_337 - gas_costs.G_STORAGE_SET + gas_costs.GAS_STORAGE_SET # pointer address access + ( - gas_costs.G_WARM_ACCOUNT_ACCESS + gas_costs.GAS_WARM_ACCESS if ( pointer_definition in [ @@ -639,11 +639,11 @@ def test_gas_diff_pointer_vs_direct_call( ] and access_list_to == AccessListTo.POINTER_ADDRESS ) - else gas_costs.G_COLD_ACCOUNT_ACCESS + else gas_costs.GAS_COLD_ACCOUNT_ACCESS ) # storage access + ( - gas_costs.G_WARM_SLOAD + gas_costs.GAS_WARM_ACCESS if ( access_list_rule in [ @@ -652,11 +652,11 @@ def test_gas_diff_pointer_vs_direct_call( ] and access_list_to == AccessListTo.POINTER_ADDRESS ) - else gas_costs.G_COLD_SLOAD + else gas_costs.GAS_COLD_SLOAD ) # contract address access + ( - gas_costs.G_WARM_ACCOUNT_ACCESS + gas_costs.GAS_WARM_ACCESS if ( access_list_rule in [ @@ -665,7 +665,7 @@ def test_gas_diff_pointer_vs_direct_call( ] and access_list_to == AccessListTo.CONTRACT_ADDRESS ) - else gas_costs.G_COLD_ACCOUNT_ACCESS + else gas_costs.GAS_COLD_ACCOUNT_ACCESS ) + opcodes_price ) @@ -813,17 +813,17 @@ def test_pointer_call_followed_by_direct_call( call_worked = 1 opcodes_price: int = 37 pointer_call_gas = ( - gas_costs.G_STORAGE_SET - + gas_costs.G_WARM_ACCOUNT_ACCESS # pointer is warm - + gas_costs.G_COLD_ACCOUNT_ACCESS # contract is cold - + gas_costs.G_COLD_SLOAD # storage access under pointer call is cold + gas_costs.GAS_STORAGE_SET + + gas_costs.GAS_WARM_ACCESS # pointer is warm + + gas_costs.GAS_COLD_ACCOUNT_ACCESS # contract is cold + + gas_costs.GAS_COLD_SLOAD # storage access under pointer call is cold + opcodes_price ) direct_call_gas = ( - gas_costs.G_STORAGE_SET - + gas_costs.G_WARM_ACCOUNT_ACCESS # since previous pointer call, + gas_costs.GAS_STORAGE_SET + + gas_costs.GAS_WARM_ACCESS # since previous pointer call, # contract is now warm - + gas_costs.G_COLD_SLOAD # but storage is cold, because it's + + gas_costs.GAS_COLD_SLOAD # but storage is cold, because it's # contract's direct + opcodes_price ) @@ -1970,7 +1970,7 @@ def test_delegation_replacement_call_previous_contract( sender = pre.fund_eoa() gsc = fork.gas_costs() - overhead_cost = gsc.G_VERY_LOW * len(Op.CALL.kwargs) + overhead_cost = gsc.GAS_VERY_LOW * len(Op.CALL.kwargs) set_code = CodeGasMeasure( code=Op.CALL(gas=0, address=pre_set_delegation_address), overhead_cost=overhead_cost, @@ -2001,7 +2001,7 @@ def test_delegation_replacement_call_previous_contract( tx=tx, post={ auth_signer: Account( - storage={0: gsc.G_COLD_ACCOUNT_ACCESS}, + storage={0: gsc.GAS_COLD_ACCOUNT_ACCESS}, ) }, ) diff --git a/tests/shanghai/eip3860_initcode/test_initcode.py b/tests/shanghai/eip3860_initcode/test_initcode.py index bc645c494d..06ec8934e4 100644 --- a/tests/shanghai/eip3860_initcode/test_initcode.py +++ b/tests/shanghai/eip3860_initcode/test_initcode.py @@ -512,10 +512,10 @@ def contract_creation_gas_cost(self, fork: Fork, opcode: Op) -> int: """Calculate gas cost of the contract creation operation.""" gas_costs = fork.gas_costs() - create_contract_base_gas = gas_costs.G_CREATE - gas_opcode_gas = gas_costs.G_BASE - push_dup_opcode_gas = gas_costs.G_VERY_LOW - calldatasize_opcode_gas = gas_costs.G_BASE + create_contract_base_gas = gas_costs.GAS_CREATE + gas_opcode_gas = gas_costs.GAS_BASE + push_dup_opcode_gas = gas_costs.GAS_VERY_LOW + calldatasize_opcode_gas = gas_costs.GAS_BASE contract_creation_gas_usage = ( create_contract_base_gas + gas_opcode_gas @@ -530,7 +530,10 @@ def contract_creation_gas_cost(self, fork: Fork, opcode: Op) -> int: def initcode_word_cost(self, fork: Fork, initcode: Initcode) -> int: """Calculate gas cost charged for the initcode length.""" gas_costs = fork.gas_costs() - return ceiling_division(len(initcode), 32) * gas_costs.G_INITCODE_WORD + return ( + ceiling_division(len(initcode), 32) + * gas_costs.GAS_INIT_CODE_WORD_COST + ) @pytest.fixture def create2_word_cost( @@ -542,7 +545,7 @@ def create2_word_cost( gas_costs = fork.gas_costs() return ( - ceiling_division(len(initcode), 32) * gas_costs.G_KECCAK_256_WORD + ceiling_division(len(initcode), 32) * gas_costs.GAS_KECCAK256_WORD ) @pytest.mark.xdist_group(name="bigmem") diff --git a/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py b/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py index d9b05d4249..6423b51f24 100644 --- a/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py +++ b/tests/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py @@ -993,12 +993,12 @@ def test_invalid_container_deployment( ) elif reason == "out_of_gas_when_returning_contract": factory_gas_cost = ( - 7 * fork_gas_costs.G_VERY_LOW - + fork_gas_costs.G_STORAGE_SET - + fork_gas_costs.G_COLD_SLOAD - + fork_gas_costs.G_CREATE + 7 * fork_gas_costs.GAS_VERY_LOW + + fork_gas_costs.GAS_STORAGE_SET + + fork_gas_costs.GAS_COLD_SLOAD + + fork_gas_costs.GAS_CREATE ) - initcode_gas_cost = 2 * fork_gas_costs.G_VERY_LOW + initcode_gas_cost = 2 * fork_gas_costs.GAS_VERY_LOW tx_gas_limit = ( fork_intrinsic_gas_calculator(calldata=initcontainer) + factory_gas_cost @@ -1008,16 +1008,16 @@ def test_invalid_container_deployment( reason == "out_of_gas_when_returning_contract_due_to_memory_expansion" ): factory_gas_cost = ( - 7 * fork_gas_costs.G_VERY_LOW - + fork_gas_costs.G_STORAGE_SET - + fork_gas_costs.G_COLD_SLOAD - + fork_gas_costs.G_CREATE + 7 * fork_gas_costs.GAS_VERY_LOW + + fork_gas_costs.GAS_STORAGE_SET + + fork_gas_costs.GAS_COLD_SLOAD + + fork_gas_costs.GAS_CREATE ) initcode_gas_cost = ( # Code deposit gas cost - len(deployed_container) * fork_gas_costs.G_CODE_DEPOSIT_BYTE + len(deployed_container) * fork_gas_costs.GAS_CODE_DEPOSIT # Two push opcodes - + 2 * fork_gas_costs.G_VERY_LOW + + 2 * fork_gas_costs.GAS_VERY_LOW ) tx_gas_limit = ( fork_intrinsic_gas_calculator(calldata=initcontainer) From 68b1733e6c57640ac299d4d8ea795bd502f296ca Mon Sep 17 00:00:00 2001 From: LouisTsai Date: Mon, 3 Nov 2025 12:42:40 +0800 Subject: [PATCH 2/4] refactor: update opcode gas constant source --- src/ethereum/forks/osaka/vm/gas.py | 89 ++++++++++++++++++- .../forks/osaka/vm/instructions/arithmetic.py | 39 ++++---- .../forks/osaka/vm/instructions/bitwise.py | 31 ++++--- .../forks/osaka/vm/instructions/block.py | 25 ++++-- .../forks/osaka/vm/instructions/comparison.py | 22 +++-- .../osaka/vm/instructions/control_flow.py | 12 +-- .../osaka/vm/instructions/environment.py | 52 ++++++----- .../forks/osaka/vm/instructions/keccak.py | 4 +- .../forks/osaka/vm/instructions/log.py | 4 +- .../forks/osaka/vm/instructions/memory.py | 17 ++-- .../forks/osaka/vm/instructions/stack.py | 12 +-- .../forks/osaka/vm/instructions/storage.py | 6 +- .../forks/osaka/vm/instructions/system.py | 14 +-- 13 files changed, 232 insertions(+), 95 deletions(-) diff --git a/src/ethereum/forks/osaka/vm/gas.py b/src/ethereum/forks/osaka/vm/gas.py index 2387e88614..b13324b32d 100644 --- a/src/ethereum/forks/osaka/vm/gas.py +++ b/src/ethereum/forks/osaka/vm/gas.py @@ -86,7 +86,7 @@ # EEST Specific Variables G_TX_DATA_ZERO = 4 -G_TX_DATA_NON_ZERO = 68 +G_TX_DATA_NON_ZERO = 16 # Transaction costs (from transactions.py) TX_BASE_COST = Uint(21_000) @@ -100,6 +100,93 @@ PER_EMPTY_ACCOUNT_COST = 25_000 PER_AUTH_BASE_COST = 12_500 +# Opcode Costs +G_STOP = GAS_ZERO +G_ADD = GAS_VERY_LOW +G_MUL = GAS_LOW +G_SUB = GAS_VERY_LOW +G_DIV = GAS_LOW +G_SDIV = GAS_LOW +G_MOD = GAS_LOW +G_SMOD = GAS_LOW +G_ADDMOD = GAS_MID +G_MULMOD = GAS_MID +G_EXP = GAS_EXPONENTIATION +G_SIGNEXTEND = GAS_LOW +G_LT = GAS_VERY_LOW +G_GT = GAS_VERY_LOW +G_SLT = GAS_VERY_LOW +G_SGT = GAS_VERY_LOW +G_EQ = GAS_VERY_LOW +G_ISZERO = GAS_VERY_LOW +G_AND = GAS_VERY_LOW +G_OR = GAS_VERY_LOW +G_XOR = GAS_VERY_LOW +G_NOT = GAS_VERY_LOW +G_BYTE = GAS_VERY_LOW +G_SHL = GAS_VERY_LOW +G_SHR = GAS_VERY_LOW +G_SAR = GAS_VERY_LOW +G_CLZ = GAS_LOW +G_KECCAK256 = GAS_KECCAK256 +G_ADDRESS = GAS_BASE +G_BALANCE = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_ORIGIN = GAS_BASE +G_CALLER = GAS_BASE +G_CALLVALUE = GAS_BASE +G_CALLDATALOAD = GAS_VERY_LOW +G_CALLDATASIZE = GAS_BASE +G_CALLDATACOPY = GAS_VERY_LOW +G_CODESIZE = GAS_BASE +G_CODECOPY = GAS_VERY_LOW +G_GASPRICE = GAS_BASE +G_EXTCODESIZE = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_EXTCODECOPY = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_RETURNDATASIZE = GAS_BASE +G_RETURNDATACOPY = GAS_VERY_LOW +G_EXTCODEHASH = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_BLOCKHASH = GAS_BLOCK_HASH +G_COINBASE = GAS_BASE +G_TIMESTAMP = GAS_BASE +G_NUMBER = GAS_BASE +G_PREVRANDAO = GAS_BASE +G_GASLIMIT = GAS_BASE +G_CHAINID = GAS_BASE +G_SELFBALANCE = GAS_LOW +G_BASEFEE = GAS_BASE +G_BLOBHASH = GAS_BLOBHASH_OPCODE +G_BLOBBASEFEE = GAS_BASE +G_POP = GAS_BASE +G_MLOAD = GAS_VERY_LOW +G_MSTORE = GAS_VERY_LOW +G_MSTORE8 = GAS_VERY_LOW +G_SLOAD = GAS_WARM_ACCESS # or GAS_COLD_SLOAD if cold +G_SSTORE = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_JUMP = GAS_MID +G_JUMPI = GAS_HIGH +G_PC = GAS_BASE +G_MSIZE = GAS_BASE +G_GAS = GAS_BASE +G_JUMPDEST = GAS_JUMPDEST +G_TLOAD = GAS_WARM_ACCESS +G_TSTORE = GAS_WARM_ACCESS +G_MCOPY = GAS_VERY_LOW +G_PUSH0 = GAS_BASE +G_PUSHx = GAS_VERY_LOW +G_DUPx = GAS_VERY_LOW +G_SWAPx = GAS_VERY_LOW +G_LOGx = GAS_LOG +G_CREATE = GAS_CREATE +G_CALL = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_CALLCODE = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_RETURN = GAS_ZERO +G_DELEGATECALL = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_CREATE2 = GAS_CREATE +G_STATICCALL = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_REVERT = GAS_ZERO +G_INVALID = GAS_ZERO +G_SELFDESTRUCT = GAS_SELF_DESTRUCT + @dataclass class ExtendMemory: diff --git a/src/ethereum/forks/osaka/vm/instructions/arithmetic.py b/src/ethereum/forks/osaka/vm/instructions/arithmetic.py index de5d6ab43d..7a696cb338 100644 --- a/src/ethereum/forks/osaka/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/osaka/vm/instructions/arithmetic.py @@ -18,11 +18,18 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, + G_ADD, + G_ADDMOD, + G_DIV, + G_EXP, + G_MOD, + G_MUL, + G_MULMOD, + G_SDIV, + G_SIGNEXTEND, + G_SMOD, + G_SUB, GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, charge_gas, ) from ..stack import pop, push @@ -44,7 +51,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +78,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +105,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +132,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_DIV) # OPERATION if divisor == 0: @@ -158,7 +165,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_SDIV) # OPERATION if divisor == 0: @@ -191,7 +198,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_MOD) # OPERATION if y == 0: @@ -221,7 +228,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_SMOD) # OPERATION if y == 0: @@ -252,7 +259,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, G_ADDMOD) # OPERATION if z == 0: @@ -283,7 +290,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, G_MULMOD) # OPERATION if z == 0: @@ -317,9 +324,7 @@ def exp(evm: Evm) -> None: # function is inaccurate leading to wrong results. exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) - charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes - ) + charge_gas(evm, G_EXP + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes) # OPERATION result = U256(pow(base, exponent, Uint(U256.MAX_VALUE) + Uint(1))) @@ -346,7 +351,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/osaka/vm/instructions/bitwise.py b/src/ethereum/forks/osaka/vm/instructions/bitwise.py index cc6fa2fbb2..36d7aba3b6 100644 --- a/src/ethereum/forks/osaka/vm/instructions/bitwise.py +++ b/src/ethereum/forks/osaka/vm/instructions/bitwise.py @@ -14,7 +14,18 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import ( + G_AND, + G_BYTE, + G_CLZ, + G_NOT, + G_OR, + G_SAR, + G_SHL, + G_SHR, + G_XOR, + charge_gas, +) from ..stack import pop, push @@ -34,7 +45,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +70,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +95,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +119,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +145,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +180,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +210,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SHR) # OPERATION if shift < U256(256): @@ -229,7 +240,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SAR) # OPERATION if shift < 256: @@ -262,7 +273,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_CLZ) # OPERATION bit_length = U256(x.bit_length()) diff --git a/src/ethereum/forks/osaka/vm/instructions/block.py b/src/ethereum/forks/osaka/vm/instructions/block.py index e33f26aea4..86f2370a08 100644 --- a/src/ethereum/forks/osaka/vm/instructions/block.py +++ b/src/ethereum/forks/osaka/vm/instructions/block.py @@ -14,7 +14,16 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import ( + G_BLOCKHASH, + G_CHAINID, + G_COINBASE, + G_GASLIMIT, + G_NUMBER, + G_PREVRANDAO, + G_TIMESTAMP, + charge_gas, +) from ..stack import pop, push @@ -40,7 +49,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, G_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +98,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +132,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +165,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +198,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +231,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +261,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/osaka/vm/instructions/comparison.py b/src/ethereum/forks/osaka/vm/instructions/comparison.py index a6a3d99bc8..f6c32607b1 100644 --- a/src/ethereum/forks/osaka/vm/instructions/comparison.py +++ b/src/ethereum/forks/osaka/vm/instructions/comparison.py @@ -14,7 +14,15 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + G_EQ, + G_GT, + G_ISZERO, + G_LT, + G_SGT, + G_SLT, + charge_gas, +) from ..stack import pop, push @@ -34,7 +42,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_LT) # OPERATION result = U256(left < right) @@ -60,7 +68,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SLT) # OPERATION result = U256(left < right) @@ -87,7 +95,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_GT) # OPERATION result = U256(left > right) @@ -113,7 +121,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SGT) # OPERATION result = U256(left > right) @@ -140,7 +148,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_EQ) # OPERATION result = U256(left == right) @@ -166,7 +174,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/osaka/vm/instructions/control_flow.py b/src/ethereum/forks/osaka/vm/instructions/control_flow.py index b3b1f2316a..5ec05ea4bf 100644 --- a/src/ethereum/forks/osaka/vm/instructions/control_flow.py +++ b/src/ethereum/forks/osaka/vm/instructions/control_flow.py @@ -13,7 +13,7 @@ from ethereum_types.numeric import U256, Uint -from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from ...vm.gas import G_GAS, G_JUMP, G_JUMPDEST, G_JUMPI, G_PC, charge_gas from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +57,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, G_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +84,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, G_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +113,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +137,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +162,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, G_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/osaka/vm/instructions/environment.py b/src/ethereum/forks/osaka/vm/instructions/environment.py index 8369043465..a97625a1eb 100644 --- a/src/ethereum/forks/osaka/vm/instructions/environment.py +++ b/src/ethereum/forks/osaka/vm/instructions/environment.py @@ -24,13 +24,25 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, + G_ADDRESS, + G_BASEFEE, + G_BLOBBASEFEE, + G_BLOBHASH, + G_CALLDATACOPY, + G_CALLDATALOAD, + G_CALLDATASIZE, + G_CALLER, + G_CALLVALUE, + G_CODECOPY, + G_CODESIZE, + G_GASPRICE, + G_ORIGIN, + G_RETURNDATACOPY, + G_RETURNDATASIZE, + G_SELFBALANCE, GAS_COLD_ACCOUNT_ACCESS, GAS_COPY, - GAS_FAST_STEP, GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, GAS_WARM_ACCESS, calculate_blob_gas_price, calculate_gas_extend_memory, @@ -53,7 +65,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -107,7 +119,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -130,7 +142,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -153,7 +165,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -177,7 +189,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -202,7 +214,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -235,7 +247,7 @@ def calldatacopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_CALLDATACOPY + copy_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -260,7 +272,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -293,7 +305,7 @@ def codecopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_CODECOPY + copy_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -318,7 +330,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -415,7 +427,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -445,7 +457,7 @@ def returndatacopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_RETURNDATACOPY + copy_gas_cost + extend_memory.cost) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -510,7 +522,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, G_SELFBALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +550,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +573,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, G_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +600,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/osaka/vm/instructions/keccak.py b/src/ethereum/forks/osaka/vm/instructions/keccak.py index 44ba2eb40b..375d50024f 100644 --- a/src/ethereum/forks/osaka/vm/instructions/keccak.py +++ b/src/ethereum/forks/osaka/vm/instructions/keccak.py @@ -18,7 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, + G_KECCAK256, GAS_KECCAK256_WORD, calculate_gas_extend_memory, charge_gas, @@ -50,7 +50,7 @@ def keccak(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + charge_gas(evm, G_KECCAK256 + word_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/osaka/vm/instructions/log.py b/src/ethereum/forks/osaka/vm/instructions/log.py index a6e95b3170..dd68dfaa66 100644 --- a/src/ethereum/forks/osaka/vm/instructions/log.py +++ b/src/ethereum/forks/osaka/vm/instructions/log.py @@ -19,9 +19,9 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, GAS_LOG_DATA, GAS_LOG_TOPIC, + G_LOGx, calculate_gas_extend_memory, charge_gas, ) @@ -59,7 +59,7 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG + G_LOGx + GAS_LOG_DATA * Uint(size) + GAS_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, diff --git a/src/ethereum/forks/osaka/vm/instructions/memory.py b/src/ethereum/forks/osaka/vm/instructions/memory.py index 631d33a7fd..bf9e809449 100644 --- a/src/ethereum/forks/osaka/vm/instructions/memory.py +++ b/src/ethereum/forks/osaka/vm/instructions/memory.py @@ -18,9 +18,12 @@ from .. import Evm from ..gas import ( - GAS_BASE, + G_MCOPY, + G_MLOAD, + G_MSIZE, + G_MSTORE, + G_MSTORE8, GAS_COPY, - GAS_VERY_LOW, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +52,7 @@ def mstore(evm: Evm) -> None: evm.memory, [(start_position, U256(len(value)))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, G_MSTORE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +83,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, G_MSTORE8 + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +111,7 @@ def mload(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(start_position, U256(32))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, G_MLOAD + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +138,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -166,7 +169,7 @@ def mcopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(source, length), (destination, length)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_MCOPY + copy_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/osaka/vm/instructions/stack.py b/src/ethereum/forks/osaka/vm/instructions/stack.py index e381b52c37..e96c19d3f4 100644 --- a/src/ethereum/forks/osaka/vm/instructions/stack.py +++ b/src/ethereum/forks/osaka/vm/instructions/stack.py @@ -17,7 +17,7 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import G_POP, G_PUSH0, G_DUPx, G_PUSHx, G_SWAPx, charge_gas from ..memory import buffer_read @@ -35,7 +35,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_POP) # OPERATION pass @@ -63,9 +63,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_PUSHx) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_DUPx) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SWAPx) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/osaka/vm/instructions/storage.py b/src/ethereum/forks/osaka/vm/instructions/storage.py index e6777c30a0..1ed0c37e16 100644 --- a/src/ethereum/forks/osaka/vm/instructions/storage.py +++ b/src/ethereum/forks/osaka/vm/instructions/storage.py @@ -23,6 +23,8 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( + G_TLOAD, + G_TSTORE, GAS_CALL_STIPEND, GAS_COLD_SLOAD, GAS_STORAGE_CLEAR_REFUND, @@ -147,7 +149,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, G_TLOAD) # OPERATION value = get_transient_storage( @@ -174,7 +176,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, G_TSTORE) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/osaka/vm/instructions/system.py b/src/ethereum/forks/osaka/vm/instructions/system.py index fea7a0c1b9..f7e20c7a5a 100644 --- a/src/ethereum/forks/osaka/vm/instructions/system.py +++ b/src/ethereum/forks/osaka/vm/instructions/system.py @@ -40,15 +40,15 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( + G_CREATE, + G_RETURN, + G_SELFDESTRUCT, GAS_CALL_VALUE, GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, GAS_KECCAK256_WORD, GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, GAS_SELF_DESTRUCT_NEW_ACCOUNT, GAS_WARM_ACCESS, - GAS_ZERO, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +166,7 @@ def create(evm: Evm) -> None: ) init_code_gas = init_code_cost(Uint(memory_size)) - charge_gas(evm, GAS_CREATE + extend_memory.cost + init_code_gas) + charge_gas(evm, G_CREATE + extend_memory.cost + init_code_gas) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,7 +216,7 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE + G_CREATE + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost + init_code_gas, @@ -261,7 +261,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, G_RETURN + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -531,7 +531,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = G_SELFDESTRUCT if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) gas_cost += GAS_COLD_ACCOUNT_ACCESS From d7d2fe1e6dc98677ac97acd0da1bca104fc8664a Mon Sep 17 00:00:00 2001 From: LouisTsai Date: Mon, 3 Nov 2025 13:23:06 +0800 Subject: [PATCH 3/4] refactor: update prague opcode gas constant source --- .../execution_testing/forks/forks/forks.py | 18 ++-- src/ethereum/forks/prague/vm/gas.py | 102 ++++++++++++++++++ .../prague/vm/instructions/arithmetic.py | 39 ++++--- .../forks/prague/vm/instructions/bitwise.py | 28 +++-- .../forks/prague/vm/instructions/block.py | 25 +++-- .../prague/vm/instructions/comparison.py | 14 +-- .../prague/vm/instructions/control_flow.py | 19 ++-- .../prague/vm/instructions/environment.py | 52 +++++---- .../forks/prague/vm/instructions/keccak.py | 4 +- .../forks/prague/vm/instructions/log.py | 4 +- .../forks/prague/vm/instructions/memory.py | 17 +-- .../forks/prague/vm/instructions/stack.py | 12 +-- .../forks/prague/vm/instructions/storage.py | 6 +- .../forks/prague/vm/instructions/system.py | 15 +-- .../create/test_create_deposit_oog.py | 2 +- 15 files changed, 254 insertions(+), 103 deletions(-) diff --git a/packages/testing/src/execution_testing/forks/forks/forks.py b/packages/testing/src/execution_testing/forks/forks/forks.py index 4a7ae5f087..63c8f3d1db 100644 --- a/packages/testing/src/execution_testing/forks/forks/forks.py +++ b/packages/testing/src/execution_testing/forks/forks/forks.py @@ -1851,15 +1851,15 @@ def gas_costs( On Prague, the standard token cost and the floor token costs are introduced due to EIP-7623. """ - return replace( - super(Prague, cls).gas_costs( - block_number=block_number, timestamp=timestamp - ), - STANDARD_CALLDATA_TOKEN_COST=4, # https://eips.ethereum.org/EIPS/eip-7623 - FLOOR_CALLDATA_COST=10, - PER_EMPTY_ACCOUNT_COST=25_000, - PER_AUTH_BASE_COST=12_500, - ) + from ethereum.forks.prague.vm import gas as g + from dataclasses import fields + + kwargs = {} + for field in fields(GasCosts): + if hasattr(g, field.name): + kwargs[field.name] = int(getattr(g, field.name)) + + return GasCosts(**kwargs) @classmethod def system_contracts( diff --git a/src/ethereum/forks/prague/vm/gas.py b/src/ethereum/forks/prague/vm/gas.py index 8bb3c042cb..7ef0ce7d2a 100644 --- a/src/ethereum/forks/prague/vm/gas.py +++ b/src/ethereum/forks/prague/vm/gas.py @@ -80,6 +80,108 @@ GAS_BLS_G2_MUL = Uint(22500) GAS_BLS_G2_MAP = Uint(23800) +# EEST Specific Variables +G_TX_DATA_ZERO = 4 +G_TX_DATA_NON_ZERO = 16 + +# Transaction costs (from transactions.py) +TX_BASE_COST = Uint(21_000) +TX_CREATE_COST = Uint(32_000) +TX_ACCESS_LIST_ADDRESS_COST = Uint(2_400) +TX_ACCESS_LIST_STORAGE_KEY_COST = Uint(1_900) +STANDARD_CALLDATA_TOKEN_COST = Uint(4) +FLOOR_CALLDATA_COST = Uint(10) + +# Authorization costs (from eoa_delegation.py) +PER_EMPTY_ACCOUNT_COST = 25_000 +PER_AUTH_BASE_COST = 12_500 + +# Opcode Costs +G_STOP = GAS_ZERO +G_ADD = GAS_VERY_LOW +G_MUL = GAS_LOW +G_SUB = GAS_VERY_LOW +G_DIV = GAS_LOW +G_SDIV = GAS_LOW +G_MOD = GAS_LOW +G_SMOD = GAS_LOW +G_ADDMOD = GAS_MID +G_MULMOD = GAS_MID +G_EXP = GAS_EXPONENTIATION +G_SIGNEXTEND = GAS_LOW +G_LT = GAS_VERY_LOW +G_GT = GAS_VERY_LOW +G_SLT = GAS_VERY_LOW +G_SGT = GAS_VERY_LOW +G_EQ = GAS_VERY_LOW +G_ISZERO = GAS_VERY_LOW +G_AND = GAS_VERY_LOW +G_OR = GAS_VERY_LOW +G_XOR = GAS_VERY_LOW +G_NOT = GAS_VERY_LOW +G_BYTE = GAS_VERY_LOW +G_SHL = GAS_VERY_LOW +G_SHR = GAS_VERY_LOW +G_SAR = GAS_VERY_LOW +G_KECCAK256 = GAS_KECCAK256 +G_ADDRESS = GAS_BASE +G_BALANCE = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_ORIGIN = GAS_BASE +G_CALLER = GAS_BASE +G_CALLVALUE = GAS_BASE +G_CALLDATALOAD = GAS_VERY_LOW +G_CALLDATASIZE = GAS_BASE +G_CALLDATACOPY = GAS_VERY_LOW +G_CODESIZE = GAS_BASE +G_CODECOPY = GAS_VERY_LOW +G_GASPRICE = GAS_BASE +G_EXTCODESIZE = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_EXTCODECOPY = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_RETURNDATASIZE = GAS_BASE +G_RETURNDATACOPY = GAS_VERY_LOW +G_EXTCODEHASH = GAS_WARM_ACCESS # or GAS_COLD_ACCOUNT_ACCESS if cold +G_BLOCKHASH = GAS_BLOCK_HASH +G_COINBASE = GAS_BASE +G_TIMESTAMP = GAS_BASE +G_NUMBER = GAS_BASE +G_PREVRANDAO = GAS_BASE +G_GASLIMIT = GAS_BASE +G_CHAINID = GAS_BASE +G_SELFBALANCE = GAS_LOW +G_BASEFEE = GAS_BASE +G_BLOBHASH = GAS_BLOBHASH_OPCODE +G_BLOBBASEFEE = GAS_BASE +G_POP = GAS_BASE +G_MLOAD = GAS_VERY_LOW +G_MSTORE = GAS_VERY_LOW +G_MSTORE8 = GAS_VERY_LOW +G_SLOAD = GAS_WARM_ACCESS # or GAS_COLD_SLOAD if cold +G_SSTORE = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_JUMP = GAS_MID +G_JUMPI = GAS_HIGH +G_PC = GAS_BASE +G_MSIZE = GAS_BASE +G_GAS = GAS_BASE +G_JUMPDEST = GAS_JUMPDEST +G_TLOAD = GAS_WARM_ACCESS +G_TSTORE = GAS_WARM_ACCESS +G_MCOPY = GAS_VERY_LOW +G_PUSH0 = GAS_BASE +G_PUSHx = GAS_VERY_LOW +G_DUPx = GAS_VERY_LOW +G_SWAPx = GAS_VERY_LOW +G_LOGx = GAS_LOG +G_CREATE = GAS_CREATE +G_CALL = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_CALLCODE = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_RETURN = GAS_ZERO +G_DELEGATECALL = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_CREATE2 = GAS_CREATE +G_STATICCALL = GAS_WARM_ACCESS # base cost, actual cost is more complex +G_REVERT = GAS_ZERO +G_INVALID = GAS_ZERO +G_SELFDESTRUCT = GAS_SELF_DESTRUCT + @dataclass class ExtendMemory: diff --git a/src/ethereum/forks/prague/vm/instructions/arithmetic.py b/src/ethereum/forks/prague/vm/instructions/arithmetic.py index de5d6ab43d..7a696cb338 100644 --- a/src/ethereum/forks/prague/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/prague/vm/instructions/arithmetic.py @@ -18,11 +18,18 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, + G_ADD, + G_ADDMOD, + G_DIV, + G_EXP, + G_MOD, + G_MUL, + G_MULMOD, + G_SDIV, + G_SIGNEXTEND, + G_SMOD, + G_SUB, GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, charge_gas, ) from ..stack import pop, push @@ -44,7 +51,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +78,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +105,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +132,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_DIV) # OPERATION if divisor == 0: @@ -158,7 +165,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_SDIV) # OPERATION if divisor == 0: @@ -191,7 +198,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_MOD) # OPERATION if y == 0: @@ -221,7 +228,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_SMOD) # OPERATION if y == 0: @@ -252,7 +259,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, G_ADDMOD) # OPERATION if z == 0: @@ -283,7 +290,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, G_MULMOD) # OPERATION if z == 0: @@ -317,9 +324,7 @@ def exp(evm: Evm) -> None: # function is inaccurate leading to wrong results. exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) - charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes - ) + charge_gas(evm, G_EXP + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes) # OPERATION result = U256(pow(base, exponent, Uint(U256.MAX_VALUE) + Uint(1))) @@ -346,7 +351,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, G_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/prague/vm/instructions/bitwise.py b/src/ethereum/forks/prague/vm/instructions/bitwise.py index 41dabe8185..be82c0662e 100644 --- a/src/ethereum/forks/prague/vm/instructions/bitwise.py +++ b/src/ethereum/forks/prague/vm/instructions/bitwise.py @@ -14,7 +14,17 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + G_AND, + G_BYTE, + G_NOT, + G_OR, + G_SAR, + G_SHL, + G_SHR, + G_XOR, + charge_gas, +) from ..stack import pop, push @@ -34,7 +44,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +69,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +94,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +118,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +144,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +179,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +209,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SHR) # OPERATION if shift < U256(256): @@ -229,7 +239,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/prague/vm/instructions/block.py b/src/ethereum/forks/prague/vm/instructions/block.py index ddaa221bfc..24bbe2323a 100644 --- a/src/ethereum/forks/prague/vm/instructions/block.py +++ b/src/ethereum/forks/prague/vm/instructions/block.py @@ -14,7 +14,16 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import ( + G_BLOCKHASH, + G_CHAINID, + G_COINBASE, + G_GASLIMIT, + G_NUMBER, + G_PREVRANDAO, + G_TIMESTAMP, + charge_gas, +) from ..stack import pop, push @@ -40,7 +49,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, G_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +98,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +132,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +165,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +198,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +231,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +261,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/prague/vm/instructions/comparison.py b/src/ethereum/forks/prague/vm/instructions/comparison.py index a6a3d99bc8..278216dd46 100644 --- a/src/ethereum/forks/prague/vm/instructions/comparison.py +++ b/src/ethereum/forks/prague/vm/instructions/comparison.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import G_EQ, G_GT, G_ISZERO, G_LT, G_SGT, G_SLT, charge_gas from ..stack import pop, push @@ -34,7 +34,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_LT) # OPERATION result = U256(left < right) @@ -60,7 +60,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SLT) # OPERATION result = U256(left < right) @@ -87,7 +87,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_GT) # OPERATION result = U256(left > right) @@ -113,7 +113,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SGT) # OPERATION result = U256(left > right) @@ -140,7 +140,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_EQ) # OPERATION result = U256(left == right) @@ -166,7 +166,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/prague/vm/instructions/control_flow.py b/src/ethereum/forks/prague/vm/instructions/control_flow.py index b3b1f2316a..faab4e81d6 100644 --- a/src/ethereum/forks/prague/vm/instructions/control_flow.py +++ b/src/ethereum/forks/prague/vm/instructions/control_flow.py @@ -13,7 +13,14 @@ from ethereum_types.numeric import U256, Uint -from ...vm.gas import GAS_BASE, GAS_HIGH, GAS_JUMPDEST, GAS_MID, charge_gas +from ...vm.gas import ( + G_GAS, + G_JUMP, + G_JUMPDEST, + G_JUMPI, + G_PC, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +64,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, G_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +91,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, G_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +120,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +144,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +169,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, G_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/prague/vm/instructions/environment.py b/src/ethereum/forks/prague/vm/instructions/environment.py index 8369043465..a97625a1eb 100644 --- a/src/ethereum/forks/prague/vm/instructions/environment.py +++ b/src/ethereum/forks/prague/vm/instructions/environment.py @@ -24,13 +24,25 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, + G_ADDRESS, + G_BASEFEE, + G_BLOBBASEFEE, + G_BLOBHASH, + G_CALLDATACOPY, + G_CALLDATALOAD, + G_CALLDATASIZE, + G_CALLER, + G_CALLVALUE, + G_CODECOPY, + G_CODESIZE, + G_GASPRICE, + G_ORIGIN, + G_RETURNDATACOPY, + G_RETURNDATASIZE, + G_SELFBALANCE, GAS_COLD_ACCOUNT_ACCESS, GAS_COPY, - GAS_FAST_STEP, GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, GAS_WARM_ACCESS, calculate_blob_gas_price, calculate_gas_extend_memory, @@ -53,7 +65,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -107,7 +119,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -130,7 +142,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -153,7 +165,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -177,7 +189,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -202,7 +214,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -235,7 +247,7 @@ def calldatacopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_CALLDATACOPY + copy_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -260,7 +272,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -293,7 +305,7 @@ def codecopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_CODECOPY + copy_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -318,7 +330,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -415,7 +427,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -445,7 +457,7 @@ def returndatacopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_RETURNDATACOPY + copy_gas_cost + extend_memory.cost) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -510,7 +522,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, G_SELFBALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +550,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +573,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, G_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +600,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/prague/vm/instructions/keccak.py b/src/ethereum/forks/prague/vm/instructions/keccak.py index 44ba2eb40b..375d50024f 100644 --- a/src/ethereum/forks/prague/vm/instructions/keccak.py +++ b/src/ethereum/forks/prague/vm/instructions/keccak.py @@ -18,7 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, + G_KECCAK256, GAS_KECCAK256_WORD, calculate_gas_extend_memory, charge_gas, @@ -50,7 +50,7 @@ def keccak(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_KECCAK256 + word_gas_cost + extend_memory.cost) + charge_gas(evm, G_KECCAK256 + word_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/prague/vm/instructions/log.py b/src/ethereum/forks/prague/vm/instructions/log.py index a6e95b3170..dd68dfaa66 100644 --- a/src/ethereum/forks/prague/vm/instructions/log.py +++ b/src/ethereum/forks/prague/vm/instructions/log.py @@ -19,9 +19,9 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, GAS_LOG_DATA, GAS_LOG_TOPIC, + G_LOGx, calculate_gas_extend_memory, charge_gas, ) @@ -59,7 +59,7 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG + G_LOGx + GAS_LOG_DATA * Uint(size) + GAS_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, diff --git a/src/ethereum/forks/prague/vm/instructions/memory.py b/src/ethereum/forks/prague/vm/instructions/memory.py index 631d33a7fd..bf9e809449 100644 --- a/src/ethereum/forks/prague/vm/instructions/memory.py +++ b/src/ethereum/forks/prague/vm/instructions/memory.py @@ -18,9 +18,12 @@ from .. import Evm from ..gas import ( - GAS_BASE, + G_MCOPY, + G_MLOAD, + G_MSIZE, + G_MSTORE, + G_MSTORE8, GAS_COPY, - GAS_VERY_LOW, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +52,7 @@ def mstore(evm: Evm) -> None: evm.memory, [(start_position, U256(len(value)))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, G_MSTORE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +83,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, G_MSTORE8 + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +111,7 @@ def mload(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(start_position, U256(32))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, G_MLOAD + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +138,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -166,7 +169,7 @@ def mcopy(evm: Evm) -> None: extend_memory = calculate_gas_extend_memory( evm.memory, [(source, length), (destination, length)] ) - charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) + charge_gas(evm, G_MCOPY + copy_gas_cost + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/prague/vm/instructions/stack.py b/src/ethereum/forks/prague/vm/instructions/stack.py index e381b52c37..e96c19d3f4 100644 --- a/src/ethereum/forks/prague/vm/instructions/stack.py +++ b/src/ethereum/forks/prague/vm/instructions/stack.py @@ -17,7 +17,7 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import G_POP, G_PUSH0, G_DUPx, G_PUSHx, G_SWAPx, charge_gas from ..memory import buffer_read @@ -35,7 +35,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_POP) # OPERATION pass @@ -63,9 +63,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, G_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_PUSHx) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_DUPx) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, G_SWAPx) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/prague/vm/instructions/storage.py b/src/ethereum/forks/prague/vm/instructions/storage.py index e6777c30a0..1ed0c37e16 100644 --- a/src/ethereum/forks/prague/vm/instructions/storage.py +++ b/src/ethereum/forks/prague/vm/instructions/storage.py @@ -23,6 +23,8 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( + G_TLOAD, + G_TSTORE, GAS_CALL_STIPEND, GAS_COLD_SLOAD, GAS_STORAGE_CLEAR_REFUND, @@ -147,7 +149,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, G_TLOAD) # OPERATION value = get_transient_storage( @@ -174,7 +176,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, G_TSTORE) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/prague/vm/instructions/system.py b/src/ethereum/forks/prague/vm/instructions/system.py index fea7a0c1b9..c26773a886 100644 --- a/src/ethereum/forks/prague/vm/instructions/system.py +++ b/src/ethereum/forks/prague/vm/instructions/system.py @@ -40,15 +40,16 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( + G_CREATE, + G_CREATE2, + G_RETURN, + G_SELFDESTRUCT, GAS_CALL_VALUE, GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, GAS_KECCAK256_WORD, GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, GAS_SELF_DESTRUCT_NEW_ACCOUNT, GAS_WARM_ACCESS, - GAS_ZERO, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +167,7 @@ def create(evm: Evm) -> None: ) init_code_gas = init_code_cost(Uint(memory_size)) - charge_gas(evm, GAS_CREATE + extend_memory.cost + init_code_gas) + charge_gas(evm, G_CREATE + extend_memory.cost + init_code_gas) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,7 +217,7 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE + G_CREATE2 + GAS_KECCAK256_WORD * call_data_words + extend_memory.cost + init_code_gas, @@ -261,7 +262,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, G_RETURN + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -531,7 +532,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = G_SELFDESTRUCT if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) gas_cost += GAS_COLD_ACCOUNT_ACCESS diff --git a/tests/frontier/create/test_create_deposit_oog.py b/tests/frontier/create/test_create_deposit_oog.py index 5e0fee4d78..0ae34a3b7e 100644 --- a/tests/frontier/create/test_create_deposit_oog.py +++ b/tests/frontier/create/test_create_deposit_oog.py @@ -32,7 +32,7 @@ def test_create_deposit_oog( deposited_len = 10_000 initcode = Op.RETURN(0, deposited_len) tx_gas_limit = 1_000_000 - assert tx_gas_limit < deposited_len * fork.gas_costs().G_CODE_DEPOSIT_BYTE + assert tx_gas_limit < deposited_len * fork.gas_costs().GAS_CODE_DEPOSIT sender = pre.fund_eoa() expect_post = Storage() From 0f2fdd7ee36241e024cce54624c861d574d21a40 Mon Sep 17 00:00:00 2001 From: LouisTsai Date: Mon, 3 Nov 2025 15:35:04 +0800 Subject: [PATCH 4/4] feat: implement fork dependent cost calculator --- .../testing/src/execution_testing/__init__.py | 2 + .../execution_testing/forks/forks/forks.py | 64 +++ .../src/execution_testing/vm/__init__.py | 2 + .../vm/opcode_gas_calculator.py | 63 +++ .../src/execution_testing/vm/opcodes.py | 505 +++++++++++++----- .../vm/tests/test_opcode_gas_calculator.py | 208 ++++++++ 6 files changed, 696 insertions(+), 148 deletions(-) create mode 100644 packages/testing/src/execution_testing/vm/opcode_gas_calculator.py create mode 100644 packages/testing/src/execution_testing/vm/tests/test_opcode_gas_calculator.py diff --git a/packages/testing/src/execution_testing/__init__.py b/packages/testing/src/execution_testing/__init__.py index b391229897..2b9f8f618e 100644 --- a/packages/testing/src/execution_testing/__init__.py +++ b/packages/testing/src/execution_testing/__init__.py @@ -107,6 +107,7 @@ Op, Opcode, OpcodeCallArg, + OpcodeGasCalculator, Opcodes, UndefinedOpcodes, call_return_code, @@ -174,6 +175,7 @@ "Op", "Opcode", "OpcodeCallArg", + "OpcodeGasCalculator", "Opcodes", "ParameterSet", "ReferenceSpec", diff --git a/packages/testing/src/execution_testing/forks/forks/forks.py b/packages/testing/src/execution_testing/forks/forks/forks.py index 63c8f3d1db..32426b3822 100644 --- a/packages/testing/src/execution_testing/forks/forks/forks.py +++ b/packages/testing/src/execution_testing/forks/forks/forks.py @@ -2144,6 +2144,32 @@ def engine_forkchoice_updated_version( del block_number, timestamp return 3 + @classmethod + def op_cost( + cls, opcode: Opcodes, *, block_number: int = 0, timestamp: int = 0 + ) -> int: + """ + Return the base gas cost for a given opcode at Prague fork. + """ + from ethereum.forks.prague.vm import gas as g + + opcode_name = opcode.name + + if opcode_name.startswith("PUSH") and opcode_name != "PUSH0": + gas_const_name = "G_PUSHx" + elif opcode_name.startswith("DUP") and len(opcode_name) > 3: + gas_const_name = "G_DUPx" + elif opcode_name.startswith("SWAP") and len(opcode_name) > 4: + gas_const_name = "G_SWAPx" + elif opcode_name.startswith("LOG") and len(opcode_name) > 3: + gas_const_name = "G_LOGx" + else: + gas_const_name = f"G_{opcode_name}" + + if hasattr(g, gas_const_name): + return int(getattr(g, gas_const_name)) + return 0 + class Osaka(Prague, solc_name="cancun"): """Osaka fork.""" @@ -2343,6 +2369,44 @@ def gas_costs( return GasCosts(**kwargs) + @classmethod + def op_cost( + cls, opcode: Opcodes, *, block_number: int = 0, timestamp: int = 0 + ) -> int: + """ + Return the base gas cost for a given opcode at Osaka fork. + + Args: + opcode: The opcode enum value + block_number: Block number context + timestamp: Timestamp context + + Returns: + Base gas cost for the opcode + + Example: + >>> Osaka.op_cost(Opcodes.ADD) + 3 + """ + from ethereum.forks.osaka.vm import gas as g + + opcode_name = opcode.name + + if opcode_name.startswith("PUSH") and opcode_name != "PUSH0": + gas_const_name = "G_PUSHx" + elif opcode_name.startswith("DUP") and len(opcode_name) > 3: + gas_const_name = "G_DUPx" + elif opcode_name.startswith("SWAP") and len(opcode_name) > 4: + gas_const_name = "G_SWAPx" + elif opcode_name.startswith("LOG") and len(opcode_name) > 3: + gas_const_name = "G_LOGx" + else: + gas_const_name = f"G_{opcode_name}" + + if hasattr(g, gas_const_name): + return int(getattr(g, gas_const_name)) + return 0 + class BPO1(Osaka, bpo_fork=True): """Mainnet BPO1 fork - Blob Parameter Only fork 1.""" diff --git a/packages/testing/src/execution_testing/vm/__init__.py b/packages/testing/src/execution_testing/vm/__init__.py index 2305418904..bf66c56369 100644 --- a/packages/testing/src/execution_testing/vm/__init__.py +++ b/packages/testing/src/execution_testing/vm/__init__.py @@ -3,6 +3,7 @@ from .bytecode import Bytecode from .evm_types import EVMCodeType from .helpers import MemoryVariable, call_return_code +from .opcode_gas_calculator import OpcodeGasCalculator from .opcodes import ( Macro, Macros, @@ -24,6 +25,7 @@ "Op", "Opcode", "OpcodeCallArg", + "OpcodeGasCalculator", "Opcodes", "UndefinedOpcodes", "call_return_code", diff --git a/packages/testing/src/execution_testing/vm/opcode_gas_calculator.py b/packages/testing/src/execution_testing/vm/opcode_gas_calculator.py new file mode 100644 index 0000000000..0bdf07cc3b --- /dev/null +++ b/packages/testing/src/execution_testing/vm/opcode_gas_calculator.py @@ -0,0 +1,63 @@ +"""Simple opcode gas cost calculator for bytecode sequences.""" + +from typing import Any, Dict + +from .bytecode import Bytecode +from .opcodes import Opcodes + + +class OpcodeGasCalculator: + """ + Calculator for computing base gas costs of opcode sequences. + """ + + def __init__(self, fork: Any) -> None: + """ + Initialize the calculator with a specific fork. + + Args: + fork: Fork class (Prague or Osaka) + """ + self.fork = fork + self._byte_to_opcode: Dict[int, Opcodes] = {} + for opcode_member in Opcodes: + opcode_bytes = bytes(opcode_member._value_) + if len(opcode_bytes) > 0: + byte_value = opcode_bytes[0] + self._byte_to_opcode[byte_value] = opcode_member + + def calculate(self, opcodes: Bytecode) -> int: + """ + Calculate total base gas cost for an opcode sequence. + + Args: + opcodes: Bytecode object (result of Op.XXX + Op.YYY + ...) + + Returns: + Total base gas cost + """ + # Get bytecode bytes + bytecode = bytes(opcodes) + + total_gas = 0 + pc = 0 # Program counter + + while pc < len(bytecode): + opcode_byte = bytecode[pc] + + # Look up opcode from byte value + if opcode_byte in self._byte_to_opcode: + opcode = self._byte_to_opcode[opcode_byte] + + # Get gas cost from fork using opcode.name + gas_cost = self.fork.op_cost(opcode) + total_gas += gas_cost + + # Skip data portion for PUSH instructions + if 0x60 <= opcode_byte <= 0x7F: # PUSH1 to PUSH32 + push_size = opcode_byte - 0x5F + pc += push_size + + pc += 1 + + return total_gas diff --git a/packages/testing/src/execution_testing/vm/opcodes.py b/packages/testing/src/execution_testing/vm/opcodes.py index 6d3463f780..acd57df6d1 100644 --- a/packages/testing/src/execution_testing/vm/opcodes.py +++ b/packages/testing/src/execution_testing/vm/opcodes.py @@ -107,6 +107,7 @@ class Opcode(Bytecode): kwargs: List[str] kwargs_defaults: KW_ARGS_DEFAULTS_TYPE unchecked_stack: bool = False + name: str = "" def __new__( cls, @@ -123,6 +124,7 @@ def __new__( terminating: bool = False, kwargs: List[str] | None = None, kwargs_defaults: Optional[KW_ARGS_DEFAULTS_TYPE] = None, + name: str = "", ) -> "Opcode": """Create new opcode instance.""" if kwargs_defaults is None: @@ -159,6 +161,7 @@ def __new__( obj.data_portion_formatter = data_portion_formatter obj.stack_properties_modifier = stack_properties_modifier obj.unchecked_stack = unchecked_stack + obj.name = name if kwargs is None: obj.kwargs = [] else: @@ -501,7 +504,7 @@ class Opcodes(Opcode, Enum): Do !! NOT !! remove or modify existing opcodes from this list. """ - STOP = Opcode(0x00, terminating=True) + STOP = Opcode(0x00, terminating=True, name="STOP") """ STOP() ---- @@ -529,7 +532,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#00](https://www.evm.codes/#00) """ - ADD = Opcode(0x01, popped_stack_items=2, pushed_stack_items=1) + ADD = Opcode(0x01, popped_stack_items=2, pushed_stack_items=1, name="ADD") """ ADD(a, b) = c ---- @@ -558,7 +561,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#01](https://www.evm.codes/#01) """ - MUL = Opcode(0x02, popped_stack_items=2, pushed_stack_items=1) + MUL = Opcode(0x02, popped_stack_items=2, pushed_stack_items=1, name="MUL") """ MUL(a, b) = c ---- @@ -587,7 +590,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#02](https://www.evm.codes/#02) """ - SUB = Opcode(0x03, popped_stack_items=2, pushed_stack_items=1) + SUB = Opcode(0x03, popped_stack_items=2, pushed_stack_items=1, name="SUB") """ SUB(a, b) = c ---- @@ -616,7 +619,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#03](https://www.evm.codes/#03) """ - DIV = Opcode(0x04, popped_stack_items=2, pushed_stack_items=1) + DIV = Opcode(0x04, popped_stack_items=2, pushed_stack_items=1, name="DIV") """ DIV(a, b) = c ---- @@ -645,7 +648,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#04](https://www.evm.codes/#04) """ - SDIV = Opcode(0x05, popped_stack_items=2, pushed_stack_items=1) + SDIV = Opcode( + 0x05, popped_stack_items=2, pushed_stack_items=1, name="SDIV" + ) """ SDIV(a, b) = c ---- @@ -676,7 +681,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#05](https://www.evm.codes/#05) """ - MOD = Opcode(0x06, popped_stack_items=2, pushed_stack_items=1) + MOD = Opcode(0x06, popped_stack_items=2, pushed_stack_items=1, name="MOD") """ MOD(a, b) = c ---- @@ -706,7 +711,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#06](https://www.evm.codes/#06) """ - SMOD = Opcode(0x07, popped_stack_items=2, pushed_stack_items=1) + SMOD = Opcode( + 0x07, popped_stack_items=2, pushed_stack_items=1, name="SMOD" + ) """ SMOD(a, b) = c ---- @@ -736,7 +743,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#07](https://www.evm.codes/#07) """ - ADDMOD = Opcode(0x08, popped_stack_items=3, pushed_stack_items=1) + ADDMOD = Opcode( + 0x08, popped_stack_items=3, pushed_stack_items=1, name="ADDMOD" + ) """ ADDMOD(a, b, c) = d ---- @@ -767,7 +776,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#08](https://www.evm.codes/#08) """ - MULMOD = Opcode(0x09, popped_stack_items=3, pushed_stack_items=1) + MULMOD = Opcode( + 0x09, popped_stack_items=3, pushed_stack_items=1, name="MULMOD" + ) """ MULMOD(a, b, N) = d ---- @@ -798,7 +809,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#09](https://www.evm.codes/#09) """ - EXP = Opcode(0x0A, popped_stack_items=2, pushed_stack_items=1) + EXP = Opcode(0x0A, popped_stack_items=2, pushed_stack_items=1, name="EXP") """ EXP(a, exponent) = a ** exponent ---- @@ -828,7 +839,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#0A](https://www.evm.codes/#0A) """ - SIGNEXTEND = Opcode(0x0B, popped_stack_items=2, pushed_stack_items=1) + SIGNEXTEND = Opcode( + 0x0B, popped_stack_items=2, pushed_stack_items=1, name="SIGNEXTEND" + ) """ SIGNEXTEND(b, x) = y ---- @@ -857,7 +870,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#0B](https://www.evm.codes/#0B) """ - LT = Opcode(0x10, popped_stack_items=2, pushed_stack_items=1) + LT = Opcode(0x10, popped_stack_items=2, pushed_stack_items=1, name="LT") """ LT(a, b) = a < b ---- @@ -886,7 +899,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#10](https://www.evm.codes/#10) """ - GT = Opcode(0x11, popped_stack_items=2, pushed_stack_items=1) + GT = Opcode(0x11, popped_stack_items=2, pushed_stack_items=1, name="GT") """ GT(a, b) = a > b ---- @@ -915,7 +928,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#11](https://www.evm.codes/#11) """ - SLT = Opcode(0x12, popped_stack_items=2, pushed_stack_items=1) + SLT = Opcode(0x12, popped_stack_items=2, pushed_stack_items=1, name="SLT") """ SLT(a, b) = a < b ---- @@ -944,7 +957,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#12](https://www.evm.codes/#12) """ - SGT = Opcode(0x13, popped_stack_items=2, pushed_stack_items=1) + SGT = Opcode(0x13, popped_stack_items=2, pushed_stack_items=1, name="SGT") """ SGT(a, b) = a > b ---- @@ -973,7 +986,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#13](https://www.evm.codes/#13) """ - EQ = Opcode(0x14, popped_stack_items=2, pushed_stack_items=1) + EQ = Opcode(0x14, popped_stack_items=2, pushed_stack_items=1, name="EQ") """ EQ(a, b) = a == b ---- @@ -1002,7 +1015,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#14](https://www.evm.codes/#14) """ - ISZERO = Opcode(0x15, popped_stack_items=1, pushed_stack_items=1) + ISZERO = Opcode( + 0x15, popped_stack_items=1, pushed_stack_items=1, name="ISZERO" + ) """ ISZERO(a) = a == 0 ---- @@ -1030,7 +1045,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#15](https://www.evm.codes/#15) """ - AND = Opcode(0x16, popped_stack_items=2, pushed_stack_items=1) + AND = Opcode(0x16, popped_stack_items=2, pushed_stack_items=1, name="AND") """ AND(a, b) = a & b ---- @@ -1059,7 +1074,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#16](https://www.evm.codes/#16) """ - OR = Opcode(0x17, popped_stack_items=2, pushed_stack_items=1) + OR = Opcode(0x17, popped_stack_items=2, pushed_stack_items=1, name="OR") """ OR(a, b) = a | b ---- @@ -1088,7 +1103,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#17](https://www.evm.codes/#17) """ - XOR = Opcode(0x18, popped_stack_items=2, pushed_stack_items=1) + XOR = Opcode(0x18, popped_stack_items=2, pushed_stack_items=1, name="XOR") """ XOR(a, b) = a ^ b ---- @@ -1117,7 +1132,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#18](https://www.evm.codes/#18) """ - NOT = Opcode(0x19, popped_stack_items=1, pushed_stack_items=1) + NOT = Opcode(0x19, popped_stack_items=1, pushed_stack_items=1, name="NOT") """ NOT(a) = ~a ---- @@ -1145,7 +1160,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#19](https://www.evm.codes/#19) """ - BYTE = Opcode(0x1A, popped_stack_items=2, pushed_stack_items=1) + BYTE = Opcode( + 0x1A, popped_stack_items=2, pushed_stack_items=1, name="BYTE" + ) """ BYTE(i, x) = y ---- @@ -1175,7 +1192,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#1A](https://www.evm.codes/#1A) """ - SHL = Opcode(0x1B, popped_stack_items=2, pushed_stack_items=1) + SHL = Opcode(0x1B, popped_stack_items=2, pushed_stack_items=1, name="SHL") """ SHL(shift, value) = value << shift ---- @@ -1204,7 +1221,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#1B](https://www.evm.codes/#1B) """ - SHR = Opcode(0x1C, popped_stack_items=2, pushed_stack_items=1) + SHR = Opcode(0x1C, popped_stack_items=2, pushed_stack_items=1, name="SHR") """ SHR(shift, value) = value >> shift ---- @@ -1233,7 +1250,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#1C](https://www.evm.codes/#1C) """ - SAR = Opcode(0x1D, popped_stack_items=2, pushed_stack_items=1) + SAR = Opcode(0x1D, popped_stack_items=2, pushed_stack_items=1, name="SAR") """ SAR(shift, value) = value >> shift ---- @@ -1262,7 +1279,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#1D](https://www.evm.codes/#1D) """ - CLZ = Opcode(0x1E, popped_stack_items=1, pushed_stack_items=1) + CLZ = Opcode(0x1E, popped_stack_items=1, pushed_stack_items=1, name="CLZ") """ CLZ(value) = count_leading_zeros(value) ---- @@ -1295,6 +1312,7 @@ class Opcodes(Opcode, Enum): popped_stack_items=2, pushed_stack_items=1, kwargs=["offset", "size"], + name="KECCAK256", ) """ SHA3(offset, size) = hash @@ -1326,7 +1344,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#20](https://www.evm.codes/#20) """ - ADDRESS = Opcode(0x30, pushed_stack_items=1) + ADDRESS = Opcode(0x30, pushed_stack_items=1, name="ADDRESS") """ ADDRESS() = address ---- @@ -1355,7 +1373,11 @@ class Opcodes(Opcode, Enum): """ BALANCE = Opcode( - 0x31, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"] + 0x31, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["address"], + name="BALANCE", ) """ BALANCE(address) = balance @@ -1386,7 +1408,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#31](https://www.evm.codes/#31) """ - ORIGIN = Opcode(0x32, pushed_stack_items=1) + ORIGIN = Opcode(0x32, pushed_stack_items=1, name="ORIGIN") """ ORIGIN() = address ---- @@ -1415,7 +1437,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#32](https://www.evm.codes/#32) """ - CALLER = Opcode(0x33, pushed_stack_items=1) + CALLER = Opcode(0x33, pushed_stack_items=1, name="CALLER") """ CALLER() = address ---- @@ -1445,7 +1467,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#33](https://www.evm.codes/#33) """ - CALLVALUE = Opcode(0x34, pushed_stack_items=1) + CALLVALUE = Opcode(0x34, pushed_stack_items=1, name="CALLVALUE") """ CALLVALUE() = value ---- @@ -1475,7 +1497,11 @@ class Opcodes(Opcode, Enum): """ CALLDATALOAD = Opcode( - 0x35, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"] + 0x35, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["offset"], + name="CALLDATALOAD", ) """ CALLDATALOAD(offset) = data[offset] @@ -1506,7 +1532,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#35](https://www.evm.codes/#35) """ - CALLDATASIZE = Opcode(0x36, pushed_stack_items=1) + CALLDATASIZE = Opcode(0x36, pushed_stack_items=1, name="CALLDATASIZE") """ CALLDATASIZE() = size ---- @@ -1535,7 +1561,10 @@ class Opcodes(Opcode, Enum): """ CALLDATACOPY = Opcode( - 0x37, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"] + 0x37, + popped_stack_items=3, + kwargs=["dest_offset", "offset", "size"], + name="CALLDATACOPY", ) """ CALLDATACOPY(dest_offset, offset, size) @@ -1568,7 +1597,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#37](https://www.evm.codes/#37) """ - CODESIZE = Opcode(0x38, pushed_stack_items=1) + CODESIZE = Opcode(0x38, pushed_stack_items=1, name="CODESIZE") """ CODESIZE() = size ---- @@ -1597,7 +1626,10 @@ class Opcodes(Opcode, Enum): """ CODECOPY = Opcode( - 0x39, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"] + 0x39, + popped_stack_items=3, + kwargs=["dest_offset", "offset", "size"], + name="CODECOPY", ) """ CODECOPY(dest_offset, offset, size) @@ -1626,7 +1658,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#39](https://www.evm.codes/#39) """ - GASPRICE = Opcode(0x3A, pushed_stack_items=1) + GASPRICE = Opcode(0x3A, pushed_stack_items=1, name="GASPRICE") """ GASPRICE() = price ---- @@ -1651,7 +1683,11 @@ class Opcodes(Opcode, Enum): """ EXTCODESIZE = Opcode( - 0x3B, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"] + 0x3B, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["address"], + name="EXTCODESIZE", ) """ EXTCODESIZE(address) = size @@ -1685,6 +1721,7 @@ class Opcodes(Opcode, Enum): 0x3C, popped_stack_items=4, kwargs=["address", "dest_offset", "offset", "size"], + name="EXTCODECOPY", ) """ EXTCODECOPY(address, dest_offset, offset, size) @@ -1719,7 +1756,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#3C](https://www.evm.codes/#3C) """ - RETURNDATASIZE = Opcode(0x3D, pushed_stack_items=1) + RETURNDATASIZE = Opcode(0x3D, pushed_stack_items=1, name="RETURNDATASIZE") """ RETURNDATASIZE() = size ---- @@ -1744,7 +1781,10 @@ class Opcodes(Opcode, Enum): """ RETURNDATACOPY = Opcode( - 0x3E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"] + 0x3E, + popped_stack_items=3, + kwargs=["dest_offset", "offset", "size"], + name="RETURNDATACOPY", ) """ RETURNDATACOPY(dest_offset, offset, size) @@ -1775,7 +1815,11 @@ class Opcodes(Opcode, Enum): """ EXTCODEHASH = Opcode( - 0x3F, popped_stack_items=1, pushed_stack_items=1, kwargs=["address"] + 0x3F, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["address"], + name="EXTCODEHASH", ) """ EXTCODEHASH(address) = hash @@ -1812,6 +1856,7 @@ class Opcodes(Opcode, Enum): popped_stack_items=1, pushed_stack_items=1, kwargs=["block_number"], + name="BLOCKHASH", ) """ BLOCKHASH(block_number) = hash @@ -1843,7 +1888,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#40](https://www.evm.codes/#40) """ - COINBASE = Opcode(0x41, pushed_stack_items=1) + COINBASE = Opcode(0x41, pushed_stack_items=1, name="COINBASE") """ COINBASE() = address ---- @@ -1871,7 +1916,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#41](https://www.evm.codes/#41) """ - TIMESTAMP = Opcode(0x42, pushed_stack_items=1) + TIMESTAMP = Opcode(0x42, pushed_stack_items=1, name="TIMESTAMP") """ TIMESTAMP() = timestamp ---- @@ -1899,7 +1944,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#42](https://www.evm.codes/#42) """ - NUMBER = Opcode(0x43, pushed_stack_items=1) + NUMBER = Opcode(0x43, pushed_stack_items=1, name="NUMBER") """ NUMBER() = blockNumber ---- @@ -1927,7 +1972,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#43](https://www.evm.codes/#43) """ - PREVRANDAO = Opcode(0x44, pushed_stack_items=1) + PREVRANDAO = Opcode(0x44, pushed_stack_items=1, name="PREVRANDAO") """ PREVRANDAO() = prevRandao ---- @@ -1955,7 +2000,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#44](https://www.evm.codes/#44) """ - GASLIMIT = Opcode(0x45, pushed_stack_items=1) + GASLIMIT = Opcode(0x45, pushed_stack_items=1, name="GASLIMIT") """ GASLIMIT() = gasLimit ---- @@ -1983,7 +2028,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#45](https://www.evm.codes/#45) """ - CHAINID = Opcode(0x46, pushed_stack_items=1) + CHAINID = Opcode(0x46, pushed_stack_items=1, name="CHAINID") """ CHAINID() = chainId ---- @@ -2011,7 +2056,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#46](https://www.evm.codes/#46) """ - SELFBALANCE = Opcode(0x47, pushed_stack_items=1) + SELFBALANCE = Opcode(0x47, pushed_stack_items=1, name="SELFBALANCE") """ SELFBALANCE() = balance ---- @@ -2039,7 +2084,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#47](https://www.evm.codes/#47) """ - BASEFEE = Opcode(0x48, pushed_stack_items=1) + BASEFEE = Opcode(0x48, pushed_stack_items=1, name="BASEFEE") """ BASEFEE() = baseFee ---- @@ -2064,7 +2109,11 @@ class Opcodes(Opcode, Enum): """ BLOBHASH = Opcode( - 0x49, popped_stack_items=1, pushed_stack_items=1, kwargs=["index"] + 0x49, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["index"], + name="BLOBHASH", ) """ BLOBHASH(index) = versionedHash @@ -2095,7 +2144,9 @@ class Opcodes(Opcode, Enum): eip-4844](https://eips.ethereum.org/EIPS/eip-4844) """ - BLOBBASEFEE = Opcode(0x4A, popped_stack_items=0, pushed_stack_items=1) + BLOBBASEFEE = Opcode( + 0x4A, popped_stack_items=0, pushed_stack_items=1, name="BLOBBASEFEE" + ) """ BLOBBASEFEE() = fee ---- @@ -2124,7 +2175,7 @@ class Opcodes(Opcode, Enum): EIPS/eip-7516) """ - POP = Opcode(0x50, popped_stack_items=1) + POP = Opcode(0x50, popped_stack_items=1, name="POP") """ POP() ---- @@ -2153,7 +2204,11 @@ class Opcodes(Opcode, Enum): """ MLOAD = Opcode( - 0x51, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"] + 0x51, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["offset"], + name="MLOAD", ) """ MLOAD(offset) = value @@ -2184,7 +2239,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#51](https://www.evm.codes/#51) """ - MSTORE = Opcode(0x52, popped_stack_items=2, kwargs=["offset", "value"]) + MSTORE = Opcode( + 0x52, popped_stack_items=2, kwargs=["offset", "value"], name="MSTORE" + ) """ MSTORE(offset, value) ---- @@ -2214,7 +2271,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#52](https://www.evm.codes/#52) """ - MSTORE8 = Opcode(0x53, popped_stack_items=2, kwargs=["offset", "value"]) + MSTORE8 = Opcode( + 0x53, popped_stack_items=2, kwargs=["offset", "value"], name="MSTORE8" + ) """ MSTORE8(offset, value) ---- @@ -2242,7 +2301,11 @@ class Opcodes(Opcode, Enum): """ SLOAD = Opcode( - 0x54, popped_stack_items=1, pushed_stack_items=1, kwargs=["key"] + 0x54, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["key"], + name="SLOAD", ) """ SLOAD(key) = value @@ -2273,7 +2336,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#54](https://www.evm.codes/#54) """ - SSTORE = Opcode(0x55, popped_stack_items=2, kwargs=["key", "value"]) + SSTORE = Opcode( + 0x55, popped_stack_items=2, kwargs=["key", "value"], name="SSTORE" + ) """ SSTORE(key, value) ---- @@ -2320,7 +2385,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#55](https://www.evm.codes/#55) """ - JUMP = Opcode(0x56, popped_stack_items=1, kwargs=["pc"]) + JUMP = Opcode(0x56, popped_stack_items=1, kwargs=["pc"], name="JUMP") """ JUMP(pc) ---- @@ -2349,7 +2414,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#56](https://www.evm.codes/#56) """ - JUMPI = Opcode(0x57, popped_stack_items=2, kwargs=["pc", "condition"]) + JUMPI = Opcode( + 0x57, popped_stack_items=2, kwargs=["pc", "condition"], name="JUMPI" + ) """ JUMPI(pc, condition) ---- @@ -2378,7 +2445,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#57](https://www.evm.codes/#57) """ - PC = Opcode(0x58, pushed_stack_items=1) + PC = Opcode(0x58, pushed_stack_items=1, name="PC") """ PC() = counter ---- @@ -2407,7 +2474,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#58](https://www.evm.codes/#58) """ - MSIZE = Opcode(0x59, pushed_stack_items=1) + MSIZE = Opcode(0x59, pushed_stack_items=1, name="MSIZE") """ MSIZE() = size ---- @@ -2431,7 +2498,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#59](https://www.evm.codes/#59) """ - GAS = Opcode(0x5A, pushed_stack_items=1) + GAS = Opcode(0x5A, pushed_stack_items=1, name="GAS") """ GAS() = gas_remaining ---- @@ -2460,7 +2527,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#5A](https://www.evm.codes/#5A) """ - JUMPDEST = Opcode(0x5B) + JUMPDEST = Opcode(0x5B, name="JUMPDEST") """ JUMPDEST() ---- @@ -2517,7 +2584,11 @@ class Opcodes(Opcode, Enum): """ TLOAD = Opcode( - 0x5C, popped_stack_items=1, pushed_stack_items=1, kwargs=["key"] + 0x5C, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["key"], + name="TLOAD", ) """ TLOAD(key) = value @@ -2547,7 +2618,9 @@ class Opcodes(Opcode, Enum): Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/eip-1153) """ - TSTORE = Opcode(0x5D, popped_stack_items=2, kwargs=["key", "value"]) + TSTORE = Opcode( + 0x5D, popped_stack_items=2, kwargs=["key", "value"], name="TSTORE" + ) """ TSTORE(key, value) ---- @@ -2574,7 +2647,10 @@ class Opcodes(Opcode, Enum): """ MCOPY = Opcode( - 0x5E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"] + 0x5E, + popped_stack_items=3, + kwargs=["dest_offset", "offset", "size"], + name="MCOPY", ) """ MCOPY(dest_offset, offset, size) @@ -2608,7 +2684,7 @@ class Opcodes(Opcode, Enum): eip-5656) """ - PUSH0 = Opcode(0x5F, pushed_stack_items=1) + PUSH0 = Opcode(0x5F, pushed_stack_items=1, name="PUSH0") """ PUSH0() = value ---- @@ -2636,7 +2712,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#5F](https://www.evm.codes/#5F) """ - PUSH1 = Opcode(0x60, pushed_stack_items=1, data_portion_length=1) + PUSH1 = Opcode( + 0x60, pushed_stack_items=1, data_portion_length=1, name="PUSH1" + ) """ PUSH1() = value ---- @@ -2665,7 +2743,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#60](https://www.evm.codes/#60) """ - PUSH2 = Opcode(0x61, pushed_stack_items=1, data_portion_length=2) + PUSH2 = Opcode( + 0x61, pushed_stack_items=1, data_portion_length=2, name="PUSH2" + ) """ PUSH2() = value ---- @@ -2694,7 +2774,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#61](https://www.evm.codes/#61) """ - PUSH3 = Opcode(0x62, pushed_stack_items=1, data_portion_length=3) + PUSH3 = Opcode( + 0x62, pushed_stack_items=1, data_portion_length=3, name="PUSH3" + ) """ PUSH3() = value ---- @@ -2723,7 +2805,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#62](https://www.evm.codes/#62) """ - PUSH4 = Opcode(0x63, pushed_stack_items=1, data_portion_length=4) + PUSH4 = Opcode( + 0x63, pushed_stack_items=1, data_portion_length=4, name="PUSH4" + ) """ PUSH4() = value ---- @@ -2752,7 +2836,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#63](https://www.evm.codes/#63) """ - PUSH5 = Opcode(0x64, pushed_stack_items=1, data_portion_length=5) + PUSH5 = Opcode( + 0x64, pushed_stack_items=1, data_portion_length=5, name="PUSH5" + ) """ PUSH5() = value ---- @@ -2781,7 +2867,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#64](https://www.evm.codes/#64) """ - PUSH6 = Opcode(0x65, pushed_stack_items=1, data_portion_length=6) + PUSH6 = Opcode( + 0x65, pushed_stack_items=1, data_portion_length=6, name="PUSH6" + ) """ PUSH6() = value ---- @@ -2810,7 +2898,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#65](https://www.evm.codes/#65) """ - PUSH7 = Opcode(0x66, pushed_stack_items=1, data_portion_length=7) + PUSH7 = Opcode( + 0x66, pushed_stack_items=1, data_portion_length=7, name="PUSH7" + ) """ PUSH7() = value ---- @@ -2839,7 +2929,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#66](https://www.evm.codes/#66) """ - PUSH8 = Opcode(0x67, pushed_stack_items=1, data_portion_length=8) + PUSH8 = Opcode( + 0x67, pushed_stack_items=1, data_portion_length=8, name="PUSH8" + ) """ PUSH8() = value ---- @@ -2868,7 +2960,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#67](https://www.evm.codes/#67) """ - PUSH9 = Opcode(0x68, pushed_stack_items=1, data_portion_length=9) + PUSH9 = Opcode( + 0x68, pushed_stack_items=1, data_portion_length=9, name="PUSH9" + ) """ PUSH9() = value ---- @@ -2897,7 +2991,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#68](https://www.evm.codes/#68) """ - PUSH10 = Opcode(0x69, pushed_stack_items=1, data_portion_length=10) + PUSH10 = Opcode( + 0x69, pushed_stack_items=1, data_portion_length=10, name="PUSH10" + ) """ PUSH10() = value ---- @@ -2926,7 +3022,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#69](https://www.evm.codes/#69) """ - PUSH11 = Opcode(0x6A, pushed_stack_items=1, data_portion_length=11) + PUSH11 = Opcode( + 0x6A, pushed_stack_items=1, data_portion_length=11, name="PUSH11" + ) """ PUSH11() = value ---- @@ -2955,7 +3053,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#6A](https://www.evm.codes/#6A) """ - PUSH12 = Opcode(0x6B, pushed_stack_items=1, data_portion_length=12) + PUSH12 = Opcode( + 0x6B, pushed_stack_items=1, data_portion_length=12, name="PUSH12" + ) """ PUSH12() = value ---- @@ -2984,7 +3084,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#6B](https://www.evm.codes/#6B) """ - PUSH13 = Opcode(0x6C, pushed_stack_items=1, data_portion_length=13) + PUSH13 = Opcode( + 0x6C, pushed_stack_items=1, data_portion_length=13, name="PUSH13" + ) """ PUSH13() = value ---- @@ -3013,7 +3115,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#6C](https://www.evm.codes/#6C) """ - PUSH14 = Opcode(0x6D, pushed_stack_items=1, data_portion_length=14) + PUSH14 = Opcode( + 0x6D, pushed_stack_items=1, data_portion_length=14, name="PUSH14" + ) """ PUSH14() = value ---- @@ -3043,7 +3147,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#6D](https://www.evm.codes/#6D) """ - PUSH15 = Opcode(0x6E, pushed_stack_items=1, data_portion_length=15) + PUSH15 = Opcode( + 0x6E, pushed_stack_items=1, data_portion_length=15, name="PUSH15" + ) """ PUSH15() = value ---- @@ -3072,7 +3178,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#6E](https://www.evm.codes/#6E) """ - PUSH16 = Opcode(0x6F, pushed_stack_items=1, data_portion_length=16) + PUSH16 = Opcode( + 0x6F, pushed_stack_items=1, data_portion_length=16, name="PUSH16" + ) """ PUSH16() = value ---- @@ -3101,7 +3209,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#6F](https://www.evm.codes/#6F) """ - PUSH17 = Opcode(0x70, pushed_stack_items=1, data_portion_length=17) + PUSH17 = Opcode( + 0x70, pushed_stack_items=1, data_portion_length=17, name="PUSH17" + ) """ PUSH17() = value ---- @@ -3130,7 +3240,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#70](https://www.evm.codes/#70) """ - PUSH18 = Opcode(0x71, pushed_stack_items=1, data_portion_length=18) + PUSH18 = Opcode( + 0x71, pushed_stack_items=1, data_portion_length=18, name="PUSH18" + ) """ PUSH18() = value ---- @@ -3159,7 +3271,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#71](https://www.evm.codes/#71) """ - PUSH19 = Opcode(0x72, pushed_stack_items=1, data_portion_length=19) + PUSH19 = Opcode( + 0x72, pushed_stack_items=1, data_portion_length=19, name="PUSH19" + ) """ PUSH19() = value ---- @@ -3188,7 +3302,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#72](https://www.evm.codes/#72) """ - PUSH20 = Opcode(0x73, pushed_stack_items=1, data_portion_length=20) + PUSH20 = Opcode( + 0x73, pushed_stack_items=1, data_portion_length=20, name="PUSH20" + ) """ PUSH20() = value ---- @@ -3217,7 +3333,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#73](https://www.evm.codes/#73) """ - PUSH21 = Opcode(0x74, pushed_stack_items=1, data_portion_length=21) + PUSH21 = Opcode( + 0x74, pushed_stack_items=1, data_portion_length=21, name="PUSH21" + ) """ PUSH21() = value ---- @@ -3246,7 +3364,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#74](https://www.evm.codes/#74) """ - PUSH22 = Opcode(0x75, pushed_stack_items=1, data_portion_length=22) + PUSH22 = Opcode( + 0x75, pushed_stack_items=1, data_portion_length=22, name="PUSH22" + ) """ PUSH22() = value ---- @@ -3275,7 +3395,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#75](https://www.evm.codes/#75) """ - PUSH23 = Opcode(0x76, pushed_stack_items=1, data_portion_length=23) + PUSH23 = Opcode( + 0x76, pushed_stack_items=1, data_portion_length=23, name="PUSH23" + ) """ PUSH23() = value ---- @@ -3304,7 +3426,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#76](https://www.evm.codes/#76) """ - PUSH24 = Opcode(0x77, pushed_stack_items=1, data_portion_length=24) + PUSH24 = Opcode( + 0x77, pushed_stack_items=1, data_portion_length=24, name="PUSH24" + ) """ PUSH24() = value ---- @@ -3333,7 +3457,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#77](https://www.evm.codes/#77) """ - PUSH25 = Opcode(0x78, pushed_stack_items=1, data_portion_length=25) + PUSH25 = Opcode( + 0x78, pushed_stack_items=1, data_portion_length=25, name="PUSH25" + ) """ PUSH25() = value ---- @@ -3362,7 +3488,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#78](https://www.evm.codes/#78) """ - PUSH26 = Opcode(0x79, pushed_stack_items=1, data_portion_length=26) + PUSH26 = Opcode( + 0x79, pushed_stack_items=1, data_portion_length=26, name="PUSH26" + ) """ PUSH26() = value ---- @@ -3391,7 +3519,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#79](https://www.evm.codes/#79) """ - PUSH27 = Opcode(0x7A, pushed_stack_items=1, data_portion_length=27) + PUSH27 = Opcode( + 0x7A, pushed_stack_items=1, data_portion_length=27, name="PUSH27" + ) """ PUSH27() = value ---- @@ -3420,7 +3550,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#7A](https://www.evm.codes/#7A) """ - PUSH28 = Opcode(0x7B, pushed_stack_items=1, data_portion_length=28) + PUSH28 = Opcode( + 0x7B, pushed_stack_items=1, data_portion_length=28, name="PUSH28" + ) """ PUSH28() = value ---- @@ -3449,7 +3581,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#7B](https://www.evm.codes/#7B) """ - PUSH29 = Opcode(0x7C, pushed_stack_items=1, data_portion_length=29) + PUSH29 = Opcode( + 0x7C, pushed_stack_items=1, data_portion_length=29, name="PUSH29" + ) """ PUSH29() = value ---- @@ -3478,7 +3612,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#7C](https://www.evm.codes/#7C) """ - PUSH30 = Opcode(0x7D, pushed_stack_items=1, data_portion_length=30) + PUSH30 = Opcode( + 0x7D, pushed_stack_items=1, data_portion_length=30, name="PUSH30" + ) """ PUSH30() = value ---- @@ -3507,7 +3643,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#7D](https://www.evm.codes/#7D) """ - PUSH31 = Opcode(0x7E, pushed_stack_items=1, data_portion_length=31) + PUSH31 = Opcode( + 0x7E, pushed_stack_items=1, data_portion_length=31, name="PUSH31" + ) """ PUSH31() = value ---- @@ -3536,7 +3674,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#7E](https://www.evm.codes/#7E) """ - PUSH32 = Opcode(0x7F, pushed_stack_items=1, data_portion_length=32) + PUSH32 = Opcode( + 0x7F, pushed_stack_items=1, data_portion_length=32, name="PUSH32" + ) """ PUSH32() = value ---- @@ -3565,7 +3705,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#7F](https://www.evm.codes/#7F) """ - DUP1 = Opcode(0x80, pushed_stack_items=1, min_stack_height=1) + DUP1 = Opcode(0x80, pushed_stack_items=1, min_stack_height=1, name="DUP1") """ DUP1(value) = value, value ---- @@ -3594,7 +3734,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#80](https://www.evm.codes/#80) """ - DUP2 = Opcode(0x81, pushed_stack_items=1, min_stack_height=2) + DUP2 = Opcode(0x81, pushed_stack_items=1, min_stack_height=2, name="DUP2") """ DUP2(v1, v2) = v2, v1, v2 ---- @@ -3625,7 +3765,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#81](https://www.evm.codes/#81) """ - DUP3 = Opcode(0x82, pushed_stack_items=1, min_stack_height=3) + DUP3 = Opcode(0x82, pushed_stack_items=1, min_stack_height=3, name="DUP3") """ DUP3(v1, v2, v3) = v3, v1, v2, v3 ---- @@ -3658,7 +3798,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#82](https://www.evm.codes/#82) """ - DUP4 = Opcode(0x83, pushed_stack_items=1, min_stack_height=4) + DUP4 = Opcode(0x83, pushed_stack_items=1, min_stack_height=4, name="DUP4") """ DUP4(v1, v2, v3, v4) = v4, v1, v2, v3, v4 ---- @@ -3693,7 +3833,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#83](https://www.evm.codes/#83) """ - DUP5 = Opcode(0x84, pushed_stack_items=1, min_stack_height=5) + DUP5 = Opcode(0x84, pushed_stack_items=1, min_stack_height=5, name="DUP5") """ DUP5(v1, v2, v3, v4, v5) = v5, v1, v2, v3, v4, v5 ---- @@ -3730,7 +3870,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#84](https://www.evm.codes/#84) """ - DUP6 = Opcode(0x85, pushed_stack_items=1, min_stack_height=6) + DUP6 = Opcode(0x85, pushed_stack_items=1, min_stack_height=6, name="DUP6") """ DUP6(v1, v2, ..., v5, v6) = v6, v1, v2, ..., v5, v6 ---- @@ -3767,7 +3907,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#85](https://www.evm.codes/#85) """ - DUP7 = Opcode(0x86, pushed_stack_items=1, min_stack_height=7) + DUP7 = Opcode(0x86, pushed_stack_items=1, min_stack_height=7, name="DUP7") """ DUP7(v1, v2, ..., v6, v7) = v7, v1, v2, ..., v6, v7 ---- @@ -3804,7 +3944,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#86](https://www.evm.codes/#86) """ - DUP8 = Opcode(0x87, pushed_stack_items=1, min_stack_height=8) + DUP8 = Opcode(0x87, pushed_stack_items=1, min_stack_height=8, name="DUP8") """ DUP8(v1, v2, ..., v7, v8) = v8, v1, v2, ..., v7, v8 ---- @@ -3841,7 +3981,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#87](https://www.evm.codes/#87) """ - DUP9 = Opcode(0x88, pushed_stack_items=1, min_stack_height=9) + DUP9 = Opcode(0x88, pushed_stack_items=1, min_stack_height=9, name="DUP9") """ DUP9(v1, v2, ..., v8, v9) = v9, v1, v2, ..., v8, v9 ---- @@ -3877,7 +4017,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#88](https://www.evm.codes/#88) """ - DUP10 = Opcode(0x89, pushed_stack_items=1, min_stack_height=10) + DUP10 = Opcode( + 0x89, pushed_stack_items=1, min_stack_height=10, name="DUP10" + ) """ DUP10(v1, v2, ..., v9, v10) = v10, v1, v2, ..., v9, v10 ---- @@ -3914,7 +4056,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#89](https://www.evm.codes/#89) """ - DUP11 = Opcode(0x8A, pushed_stack_items=1, min_stack_height=11) + DUP11 = Opcode( + 0x8A, pushed_stack_items=1, min_stack_height=11, name="DUP11" + ) """ DUP11(v1, v2, ..., v10, v11) = v11, v1, v2, ..., v10, v11 ---- @@ -3951,7 +4095,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#8A](https://www.evm.codes/#8A) """ - DUP12 = Opcode(0x8B, pushed_stack_items=1, min_stack_height=12) + DUP12 = Opcode( + 0x8B, pushed_stack_items=1, min_stack_height=12, name="DUP12" + ) """ DUP12(v1, v2, ..., v11, v12) = v12, v1, v2, ..., v11, v12 ---- @@ -3988,7 +4134,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#8B](https://www.evm.codes/#8B) """ - DUP13 = Opcode(0x8C, pushed_stack_items=1, min_stack_height=13) + DUP13 = Opcode( + 0x8C, pushed_stack_items=1, min_stack_height=13, name="DUP13" + ) """ DUP13(v1, v2, ..., v12, v13) = v13, v1, v2, ..., v12, v13 ---- @@ -4025,7 +4173,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#8C](https://www.evm.codes/#8C) """ - DUP14 = Opcode(0x8D, pushed_stack_items=1, min_stack_height=14) + DUP14 = Opcode( + 0x8D, pushed_stack_items=1, min_stack_height=14, name="DUP14" + ) """ DUP14(v1, v2, ..., v13, v14) = v14, v1, v2, ..., v13, v14 ---- @@ -4062,7 +4212,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#8D](https://www.evm.codes/#8D) """ - DUP15 = Opcode(0x8E, pushed_stack_items=1, min_stack_height=15) + DUP15 = Opcode( + 0x8E, pushed_stack_items=1, min_stack_height=15, name="DUP15" + ) """ DUP15(v1, v2, ..., v14, v15) = v15, v1, v2, ..., v14, v15 ---- @@ -4099,7 +4251,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#8E](https://www.evm.codes/#8E) """ - DUP16 = Opcode(0x8F, pushed_stack_items=1, min_stack_height=16) + DUP16 = Opcode( + 0x8F, pushed_stack_items=1, min_stack_height=16, name="DUP16" + ) """ DUP16(v1, v2, ..., v15, v16) = v16, v1, v2, ..., v15, v16 ---- @@ -4136,7 +4290,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#8F](https://www.evm.codes/#8F) """ - SWAP1 = Opcode(0x90, min_stack_height=2) + SWAP1 = Opcode(0x90, min_stack_height=2, name="SWAP1") """ SWAP1(v1, v2) = v2, v1 ---- @@ -4166,7 +4320,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#90](https://www.evm.codes/#90) """ - SWAP2 = Opcode(0x91, min_stack_height=3) + SWAP2 = Opcode(0x91, min_stack_height=3, name="SWAP2") """ SWAP2(v1, v2, v3) = v3, v2, v1 ---- @@ -4198,7 +4352,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#91](https://www.evm.codes/#91) """ - SWAP3 = Opcode(0x92, min_stack_height=4) + SWAP3 = Opcode(0x92, min_stack_height=4, name="SWAP3") """ SWAP3(v1, v2, v3, v4) = v4, v2, v3, v1 ---- @@ -4232,7 +4386,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#92](https://www.evm.codes/#92) """ - SWAP4 = Opcode(0x93, min_stack_height=5) + SWAP4 = Opcode(0x93, min_stack_height=5, name="SWAP4") """ SWAP4(v1, v2, ..., v4, v5) = v5, v2, ..., v4, v1 ---- @@ -4268,7 +4422,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#93](https://www.evm.codes/#93) """ - SWAP5 = Opcode(0x94, min_stack_height=6) + SWAP5 = Opcode(0x94, min_stack_height=6, name="SWAP5") """ SWAP5(v1, v2, ..., v5, v6) = v6, v2, ..., v5, v1 ---- @@ -4304,7 +4458,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#94](https://www.evm.codes/#94) """ - SWAP6 = Opcode(0x95, min_stack_height=7) + SWAP6 = Opcode(0x95, min_stack_height=7, name="SWAP6") """ SWAP6(v1, v2, ..., v6, v7) = v7, v2, ..., v6, v1 ---- @@ -4340,7 +4494,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#95](https://www.evm.codes/#95) """ - SWAP7 = Opcode(0x96, min_stack_height=8) + SWAP7 = Opcode(0x96, min_stack_height=8, name="SWAP7") """ SWAP7(v1, v2, ..., v7, v8) = v8, v2, ..., v7, v1 ---- @@ -4376,7 +4530,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#96](https://www.evm.codes/#96) """ - SWAP8 = Opcode(0x97, min_stack_height=9) + SWAP8 = Opcode(0x97, min_stack_height=9, name="SWAP8") """ SWAP8(v1, v2, ..., v8, v9) = v9, v2, ..., v8, v1 ---- @@ -4412,7 +4566,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#97](https://www.evm.codes/#97) """ - SWAP9 = Opcode(0x98, min_stack_height=10) + SWAP9 = Opcode(0x98, min_stack_height=10, name="SWAP9") """ SWAP9(v1, v2, ..., v9, v10) = v10, v2, ..., v9, v1 ---- @@ -4448,7 +4602,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#98](https://www.evm.codes/#98) """ - SWAP10 = Opcode(0x99, min_stack_height=11) + SWAP10 = Opcode(0x99, min_stack_height=11, name="SWAP10") """ SWAP10(v1, v2, ..., v10, v11) = v11, v2, ..., v10, v1 ---- @@ -4484,7 +4638,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#99](https://www.evm.codes/#99) """ - SWAP11 = Opcode(0x9A, min_stack_height=12) + SWAP11 = Opcode(0x9A, min_stack_height=12, name="SWAP11") """ SWAP11(v1, v2, ..., v11, v12) = v12, v2, ..., v11, v1 ---- @@ -4520,7 +4674,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#9A](https://www.evm.codes/#9A) """ - SWAP12 = Opcode(0x9B, min_stack_height=13) + SWAP12 = Opcode(0x9B, min_stack_height=13, name="SWAP12") """ SWAP12(v1, v2, ..., v12, v13) = v13, v2, ..., v12, v1 ---- @@ -4556,7 +4710,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#9B](https://www.evm.codes/#9B) """ - SWAP13 = Opcode(0x9C, min_stack_height=14) + SWAP13 = Opcode(0x9C, min_stack_height=14, name="SWAP13") """ SWAP13(v1, v2, ..., v13, v14) = v14, v2, ..., v13, v1 ---- @@ -4592,7 +4746,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#9C](https://www.evm.codes/#9C) """ - SWAP14 = Opcode(0x9D, min_stack_height=15) + SWAP14 = Opcode(0x9D, min_stack_height=15, name="SWAP14") """ SWAP14(v1, v2, ..., v14, v15) = v15, v2, ..., v14, v1 ---- @@ -4628,7 +4782,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#9D](https://www.evm.codes/#9D) """ - SWAP15 = Opcode(0x9E, min_stack_height=16) + SWAP15 = Opcode(0x9E, min_stack_height=16, name="SWAP15") """ SWAP15(v1, v2, ..., v15, v16) = v16, v2, ..., v15, v1 ---- @@ -4664,7 +4818,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#9E](https://www.evm.codes/#9E) """ - SWAP16 = Opcode(0x9F, min_stack_height=17) + SWAP16 = Opcode(0x9F, min_stack_height=17, name="SWAP16") """ SWAP16(v1, v2, ..., v16, v17) = v17, v2, ..., v16, v1 ---- @@ -4700,7 +4854,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#9F](https://www.evm.codes/#9F) """ - LOG0 = Opcode(0xA0, popped_stack_items=2, kwargs=["offset", "size"]) + LOG0 = Opcode( + 0xA0, popped_stack_items=2, kwargs=["offset", "size"], name="LOG0" + ) """ LOG0(offset, size) ---- @@ -4731,7 +4887,10 @@ class Opcodes(Opcode, Enum): """ LOG1 = Opcode( - 0xA1, popped_stack_items=3, kwargs=["offset", "size", "topic_1"] + 0xA1, + popped_stack_items=3, + kwargs=["offset", "size", "topic_1"], + name="LOG1", ) """ LOG1(offset, size, topic_1) @@ -4767,6 +4926,7 @@ class Opcodes(Opcode, Enum): 0xA2, popped_stack_items=4, kwargs=["offset", "size", "topic_1", "topic_2"], + name="LOG2", ) """ LOG2(offset, size, topic_1, topic_2) @@ -4803,6 +4963,7 @@ class Opcodes(Opcode, Enum): 0xA3, popped_stack_items=5, kwargs=["offset", "size", "topic_1", "topic_2", "topic_3"], + name="LOG3", ) """ LOG3(offset, size, topic_1, topic_2, topic_3) @@ -4840,6 +5001,7 @@ class Opcodes(Opcode, Enum): 0xA4, popped_stack_items=6, kwargs=["offset", "size", "topic_1", "topic_2", "topic_3", "topic_4"], + name="LOG4", ) """ LOG4(offset, size, topic_1, topic_2, topic_3, topic_4) @@ -4874,7 +5036,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#A4](https://www.evm.codes/#A4) """ - RJUMP = Opcode(0xE0, data_portion_length=2) + RJUMP = Opcode(0xE0, data_portion_length=2, name="RJUMP") """ !!! Note: This opcode is under development @@ -4902,7 +5064,11 @@ class Opcodes(Opcode, Enum): """ DATALOAD = Opcode( - 0xD0, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"] + 0xD0, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["offset"], + name="DATALOAD", ) """ !!! Note: This opcode is under development @@ -4934,7 +5100,9 @@ class Opcodes(Opcode, Enum): eip-7480) """ - DATALOADN = Opcode(0xD1, pushed_stack_items=1, data_portion_length=2) + DATALOADN = Opcode( + 0xD1, pushed_stack_items=1, data_portion_length=2, name="DATALOADN" + ) """ !!! Note: This opcode is under development @@ -4969,7 +5137,7 @@ class Opcodes(Opcode, Enum): eip-7480) """ - DATASIZE = Opcode(0xD2, pushed_stack_items=1) + DATASIZE = Opcode(0xD2, pushed_stack_items=1, name="DATASIZE") """ !!! Note: This opcode is under development @@ -5000,7 +5168,10 @@ class Opcodes(Opcode, Enum): """ DATACOPY = Opcode( - 0xD3, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"] + 0xD3, + popped_stack_items=3, + kwargs=["dest_offset", "offset", "size"], + name="DATACOPY", ) """ !!! Note: This opcode is under development @@ -5036,7 +5207,9 @@ class Opcodes(Opcode, Enum): eip-7480) """ - RJUMPI = Opcode(0xE1, popped_stack_items=1, data_portion_length=2) + RJUMPI = Opcode( + 0xE1, popped_stack_items=1, data_portion_length=2, name="RJUMPI" + ) """ !!! Note: This opcode is under development @@ -5067,6 +5240,7 @@ class Opcodes(Opcode, Enum): 0xE2, popped_stack_items=1, data_portion_formatter=_rjumpv_encoder, + name="RJUMPV", ) """ !!! Note: This opcode is under development @@ -5103,7 +5277,9 @@ class Opcodes(Opcode, Enum): eip-4200) """ - CALLF = Opcode(0xE3, data_portion_length=2, unchecked_stack=True) + CALLF = Opcode( + 0xE3, data_portion_length=2, unchecked_stack=True, name="CALLF" + ) """ !!! Note: This opcode is under development @@ -5144,7 +5320,7 @@ class Opcodes(Opcode, Enum): main/spec/eof.md) """ - RETF = Opcode(0xE4, terminating=True) + RETF = Opcode(0xE4, terminating=True, name="RETF") """ !!! Note: This opcode is under development @@ -5170,7 +5346,11 @@ class Opcodes(Opcode, Enum): """ JUMPF = Opcode( - 0xE5, data_portion_length=2, terminating=True, unchecked_stack=True + 0xE5, + data_portion_length=2, + terminating=True, + unchecked_stack=True, + name="JUMPF", ) """ !!! Note: This opcode is under development @@ -5210,6 +5390,7 @@ class Opcodes(Opcode, Enum): pushed_stack_items=1, data_portion_length=1, stack_properties_modifier=_dupn_stack_properties_modifier, + name="DUPN", ) """ !!! Note: This opcode is under development @@ -5246,6 +5427,7 @@ class Opcodes(Opcode, Enum): 0xE7, data_portion_length=1, stack_properties_modifier=_swapn_stack_properties_modifier, + name="SWAPN", ) """ !!! Note: This opcode is under development @@ -5283,6 +5465,7 @@ class Opcodes(Opcode, Enum): data_portion_length=1, data_portion_formatter=_exchange_encoder, stack_properties_modifier=_exchange_stack_properties_modifier, + name="EXCHANGE", ) """ !!! Note: This opcode is under development @@ -5325,6 +5508,7 @@ class Opcodes(Opcode, Enum): pushed_stack_items=1, data_portion_length=1, kwargs=["salt", "input_offset", "input_size", "value"], + name="EOFCREATE", ) """ !!! Note: This opcode is under development @@ -5360,6 +5544,7 @@ class Opcodes(Opcode, Enum): "input_size", "value", ], + name="TXCREATE", ) """ !!! Note: This opcode is under development @@ -5390,6 +5575,7 @@ class Opcodes(Opcode, Enum): data_portion_length=1, terminating=True, kwargs=["auxdata_offset", "auxdata_size"], + name="RETURNCODE", ) """ !!! Note: This opcode is under development @@ -5419,6 +5605,7 @@ class Opcodes(Opcode, Enum): popped_stack_items=3, pushed_stack_items=1, kwargs=["value", "offset", "size"], + name="CREATE", ) """ CREATE(value, offset, size) = address @@ -5473,6 +5660,7 @@ class Opcodes(Opcode, Enum): "ret_size", ], kwargs_defaults={"gas": GAS}, + name="CALL", ) """ CALL(gas, address, value, args_offset, args_size, ret_offset, ret_size) @@ -5530,6 +5718,7 @@ class Opcodes(Opcode, Enum): "ret_size", ], kwargs_defaults={"gas": GAS}, + name="CALLCODE", ) """ CALLCODE(gas, address, value, args_offset, args_size, ret_offset, ret_size) @@ -5574,7 +5763,11 @@ class Opcodes(Opcode, Enum): """ RETURN = Opcode( - 0xF3, popped_stack_items=2, kwargs=["offset", "size"], terminating=True + 0xF3, + popped_stack_items=2, + kwargs=["offset", "size"], + terminating=True, + name="RETURN", ) """ RETURN(offset, size) @@ -5619,6 +5812,7 @@ class Opcodes(Opcode, Enum): "ret_size", ], kwargs_defaults={"gas": GAS}, + name="DELEGATECALL", ) """ DELEGATECALL(gas, address, args_offset, args_size, ret_offset, ret_size) @@ -5664,6 +5858,7 @@ class Opcodes(Opcode, Enum): popped_stack_items=4, pushed_stack_items=1, kwargs=["value", "offset", "size", "salt"], + name="CREATE2", ) """ CREATE2(value, offset, size, salt) = address @@ -5711,6 +5906,7 @@ class Opcodes(Opcode, Enum): popped_stack_items=4, pushed_stack_items=1, kwargs=["address", "args_offset", "args_size", "value"], + name="EXTCALL", ) """ EXTCALL(address, args_offset, args_size, value) = address @@ -5757,6 +5953,7 @@ class Opcodes(Opcode, Enum): popped_stack_items=3, pushed_stack_items=1, kwargs=["address", "args_offset", "args_size"], + name="EXTDELEGATECALL", ) """ EXTDELEGATECALL(address, args_offset, args_size) = address @@ -5808,6 +6005,7 @@ class Opcodes(Opcode, Enum): "ret_size", ], kwargs_defaults={"gas": GAS}, + name="STATICCALL", ) """ STATICCALL(gas, address, args_offset, args_size, ret_offset, ret_size) @@ -5852,6 +6050,7 @@ class Opcodes(Opcode, Enum): popped_stack_items=3, pushed_stack_items=1, kwargs=["address", "args_offset", "args_size"], + name="EXTSTATICCALL", ) """ EXTSTATICCALL(address, args_offset, args_size) = address @@ -5890,7 +6089,11 @@ class Opcodes(Opcode, Enum): """ RETURNDATALOAD = Opcode( - 0xF7, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"] + 0xF7, + popped_stack_items=1, + pushed_stack_items=1, + kwargs=["offset"], + name="RETURNDATALOAD", ) """ RETURNDATALOAD(offset) @@ -5915,7 +6118,11 @@ class Opcodes(Opcode, Enum): """ REVERT = Opcode( - 0xFD, popped_stack_items=2, kwargs=["offset", "size"], terminating=True + 0xFD, + popped_stack_items=2, + kwargs=["offset", "size"], + terminating=True, + name="REVERT", ) """ REVERT(offset, size) @@ -5943,7 +6150,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#FD](https://www.evm.codes/#FD) """ - INVALID = Opcode(0xFE, terminating=True) + INVALID = Opcode(0xFE, terminating=True, name="INVALID") """ INVALID() ---- @@ -5971,7 +6178,9 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#FE](https://www.evm.codes/#FE) """ - SELFDESTRUCT = Opcode(0xFF, popped_stack_items=1, kwargs=["address"]) + SELFDESTRUCT = Opcode( + 0xFF, popped_stack_items=1, kwargs=["address"], name="SELFDESTRUCT" + ) """ SELFDESTRUCT(address) ---- diff --git a/packages/testing/src/execution_testing/vm/tests/test_opcode_gas_calculator.py b/packages/testing/src/execution_testing/vm/tests/test_opcode_gas_calculator.py new file mode 100644 index 0000000000..21378083eb --- /dev/null +++ b/packages/testing/src/execution_testing/vm/tests/test_opcode_gas_calculator.py @@ -0,0 +1,208 @@ +"""Test suite for OpcodeGasCalculator.""" + +import pytest + +from execution_testing.forks.forks.forks import Osaka, Prague +from execution_testing import Bytecode, OpcodeGasCalculator, Op, Fork + + +@pytest.mark.parametrize( + "fork,bytecode,expected_gas", + [ + # Simple arithmetic + pytest.param( + Prague, + Op.PUSH0 + Op.PUSH0 + Op.ADD, + 7, # 2 + 2 + 3 + id="prague_simple_arithmetic", + ), + pytest.param( + Osaka, + Op.PUSH0 + Op.PUSH0 + Op.ADD, + 7, # 2 + 2 + 3 + id="osaka_simple_arithmetic", + ), + # PUSH1 operations + pytest.param( + Prague, + Op.PUSH1(42) + Op.PUSH1(43) + Op.MUL, + 11, # 3 + 3 + 5 + id="prague_push1_mul", + ), + pytest.param( + Osaka, + Op.PUSH1(42) + Op.PUSH1(43) + Op.MUL, + 11, # 3 + 3 + 5 + id="osaka_push1_mul", + ), + # Storage operations (base cost only) + pytest.param( + Prague, + Op.PUSH1(42) + Op.PUSH0 + Op.SSTORE, + 105, # 3 + 2 + 100 + id="prague_sstore", + ), + pytest.param( + Osaka, + Op.PUSH1(42) + Op.PUSH0 + Op.SSTORE, + 105, # 3 + 2 + 100 + id="osaka_sstore", + ), + # Complex sequence + pytest.param( + Osaka, + Op.PUSH1(42) + + Op.PUSH1(43) + + Op.ADD + + Op.PUSH0 + + Op.MSTORE + + Op.PUSH0 + + Op.PUSH0 + + Op.RETURN, + 18, # 3 + 3 + 3 + 2 + 3 + 2 + 2 + 0 + id="complex_sequence", + ), + # DUP opcodes + pytest.param( + Osaka, + Op.DUP1 + Op.DUP2 + Op.DUP16, + 9, # 3 + 3 + 3 + id="dup_opcodes", + ), + # SWAP opcodes + pytest.param( + Osaka, + Op.SWAP1 + Op.SWAP2 + Op.SWAP16, + 9, # 3 + 3 + 3 + id="swap_opcodes", + ), + # LOG opcodes + pytest.param( + Osaka, + Op.LOG0 + Op.LOG1 + Op.LOG4, + 1125, # 375 + 375 + 375 + id="log_opcodes", + ), + # Various PUSH sizes + pytest.param( + Osaka, + Op.PUSH0 + Op.PUSH1(0xFF) + Op.PUSH2(0xFFFF) + Op.PUSH32(0xFF), + 11, # 2 + 3 + 3 + 3 + id="push_variants", + ), + # Empty bytecode + pytest.param( + Osaka, + Bytecode(), + 0, + id="empty_bytecode", + ), + # Single opcode + pytest.param( + Osaka, + Op.STOP, + 0, + id="stop_opcode", + ), + # Memory operations + pytest.param( + Osaka, + Op.MLOAD + Op.MSTORE + Op.MSTORE8, + 9, # 3 + 3 + 3 + id="memory_ops", + ), + # Comparison and bitwise + pytest.param( + Osaka, + Op.LT + Op.GT + Op.EQ + Op.AND + Op.OR + Op.XOR + Op.NOT, + 21, # 3 * 7 + id="comparison_bitwise", + ), + # Arithmetic operations + pytest.param( + Prague, + Op.ADD + Op.SUB + Op.MUL + Op.DIV + Op.MOD, + 21, # 3 + 3 + 5 + 5 + 5 + id="arithmetic_ops", + ), + # EXP operation + pytest.param( + Osaka, + Op.EXP, + 10, + id="exp_op", + ), + # CALL-like operations + pytest.param( + Osaka, + Op.CALL + Op.DELEGATECALL + Op.STATICCALL, + 300, # 100 + 100 + 100 + id="call_ops", + ), + # CREATE operations + pytest.param( + Osaka, + Op.CREATE + Op.CREATE2, + 64000, # 32000 + 32000 + id="create_ops", + ), + # SHA3/KECCAK256 + pytest.param( + Osaka, + Op.SHA3, + 30, + id="sha3", + ), + # Block information opcodes + pytest.param( + Osaka, + Op.BLOCKHASH + Op.COINBASE + Op.TIMESTAMP + Op.NUMBER, + 26, # 20 + 2 + 2 + 2 + id="block_info", + ), + # Realistic constructor pattern + pytest.param( + Osaka, + Op.PUSH1(0x80) + + Op.PUSH1(0x40) + + Op.MSTORE + + Op.CALLVALUE + + Op.DUP1 + + Op.ISZERO + + Op.PUSH1(0x0F) + + Op.JUMPI + + Op.PUSH0 + + Op.DUP1 + + Op.REVERT, + 35, # 3+3+3+2+3+3+3+10+2+3+0 + id="constructor_pattern", + ), + ], +) +def test_opcode_gas_calculator( + fork: Fork, bytecode: Bytecode, expected_gas: int +) -> None: + """Test that OpcodeGasCalculator correctly calculates base gas costs.""" + calc = OpcodeGasCalculator(fork) + assert calc.calculate(bytecode) == expected_gas + + +def test_direct_op_cost() -> None: + """Test using fork's op_cost method directly.""" + assert Prague.op_cost(Op.ADD) == 3 + assert Osaka.op_cost(Op.ADD) == 3 + assert Prague.op_cost(Op.MUL) == 5 + assert Osaka.op_cost(Op.MUL) == 5 + + +def test_fork_consistency() -> None: + """Test that Prague and Osaka have same base costs for common opcodes.""" + code = Op.PUSH1(0x01) + Op.PUSH1(0x02) + Op.ADD + + prague_calc = OpcodeGasCalculator(Prague) + osaka_calc = OpcodeGasCalculator(Osaka) + + prague_gas = prague_calc.calculate(code) + osaka_gas = osaka_calc.calculate(code) + + assert prague_gas == osaka_gas == 9 # 3 + 3 + 3