diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/pre_alloc.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/pre_alloc.py index 65d9e100ca6..306b6c143fd 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/pre_alloc.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/execute/pre_alloc.py @@ -348,10 +348,8 @@ def _deterministic_deploy_contract( raise ValueError( f"initcode too large {len(initcode)} > {max_initcode_size}" ) - deploy_gas_limit = gas_costs.GAS_TX_BASE + gas_costs.GAS_TX_CREATE - deploy_gas_limit += ( - len(deploy_code) * gas_costs.GAS_CODE_DEPOSIT_PER_BYTE - ) + deploy_gas_limit = gas_costs.TX_BASE + gas_costs.TX_CREATE + deploy_gas_limit += len(deploy_code) * gas_costs.CODE_DEPOSIT_PER_BYTE deploy_gas_limit += memory_expansion_gas_calculator( new_bytes=len(initcode) ) @@ -445,7 +443,7 @@ def _deploy_contract( initcode_prefix = Bytecode() - deploy_gas_limit = gas_costs.GAS_TX_BASE + gas_costs.GAS_TX_CREATE + deploy_gas_limit = gas_costs.TX_BASE + gas_costs.TX_CREATE if len(storage.root) > 0: initcode_prefix += sum( @@ -462,7 +460,7 @@ def _deploy_contract( if len(code) > max_code_size: raise ValueError(f"code too large: {len(code)} > {max_code_size}") - deploy_gas_limit += len(code) * gas_costs.GAS_CODE_DEPOSIT_PER_BYTE + deploy_gas_limit += len(code) * gas_costs.CODE_DEPOSIT_PER_BYTE prepared_initcode = Initcode( deploy_code=code, initcode_prefix=initcode_prefix diff --git a/packages/testing/src/execution_testing/forks/forks/eips/amsterdam/eip_7928.py b/packages/testing/src/execution_testing/forks/forks/eips/amsterdam/eip_7928.py index 5e46e0ccb95..d4b1b9a6e17 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/amsterdam/eip_7928.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/amsterdam/eip_7928.py @@ -36,7 +36,7 @@ def gas_costs(cls) -> GasCosts: """ return replace( super(EIP7928, cls).gas_costs(), - GAS_BLOCK_ACCESS_LIST_ITEM=2000, + BLOCK_ACCESS_LIST_ITEM=2000, ) @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/eips/berlin/eip_2930.py b/packages/testing/src/execution_testing/forks/forks/eips/berlin/eip_2930.py index 7544ae1580a..7dede0ace15 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/berlin/eip_2930.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/berlin/eip_2930.py @@ -55,11 +55,9 @@ def fn( ) if access_list is not None: for access in access_list: - intrinsic_cost += gas_costs.GAS_TX_ACCESS_LIST_ADDRESS + intrinsic_cost += gas_costs.TX_ACCESS_LIST_ADDRESS for _ in access.storage_keys: - intrinsic_cost += ( - gas_costs.GAS_TX_ACCESS_LIST_STORAGE_KEY - ) + intrinsic_cost += gas_costs.TX_ACCESS_LIST_STORAGE_KEY return intrinsic_cost return fn diff --git a/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_196.py b/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_196.py index 2d7178efdca..343e8ba9947 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_196.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_196.py @@ -30,6 +30,6 @@ def gas_costs(cls) -> GasCosts: """Set gas costs for BN254 addition and multiplication.""" return replace( super(EIP196, cls).gas_costs(), - GAS_PRECOMPILE_ECADD=500, - GAS_PRECOMPILE_ECMUL=40_000, + PRECOMPILE_ECADD=500, + PRECOMPILE_ECMUL=40_000, ) diff --git a/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_197.py b/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_197.py index 55a4e60c34c..4d18dc85b3e 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_197.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_197.py @@ -29,6 +29,6 @@ def gas_costs(cls) -> GasCosts: """Set gas costs for BN254 pairing check.""" return replace( super(EIP197, cls).gas_costs(), - GAS_PRECOMPILE_ECPAIRING_BASE=100_000, - GAS_PRECOMPILE_ECPAIRING_PER_POINT=80_000, + PRECOMPILE_ECPAIRING_BASE=100_000, + PRECOMPILE_ECPAIRING_PER_POINT=80_000, ) diff --git a/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_211.py b/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_211.py index 51b958f741e..d8e053c26ef 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_211.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/byzantium/eip_211.py @@ -24,9 +24,9 @@ def opcode_gas_map( base_map = super(EIP211, cls).opcode_gas_map() return { **base_map, - Opcodes.RETURNDATASIZE: gas_costs.GAS_BASE, + Opcodes.RETURNDATASIZE: gas_costs.BASE, Opcodes.RETURNDATACOPY: cls._with_memory_expansion( - cls._with_data_copy(gas_costs.GAS_VERY_LOW, gas_costs), + cls._with_data_copy(gas_costs.VERY_LOW, gas_costs), memory_expansion_calculator, ), } diff --git a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_1153.py b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_1153.py index 0481a794842..c98a22bc3f4 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_1153.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_1153.py @@ -26,8 +26,8 @@ def opcode_gas_map( base_map = super(EIP1153, cls).opcode_gas_map() return { **base_map, - Opcodes.TLOAD: gas_costs.GAS_WARM_SLOAD, - Opcodes.TSTORE: gas_costs.GAS_WARM_SLOAD, + Opcodes.TLOAD: gas_costs.WARM_SLOAD, + Opcodes.TSTORE: gas_costs.WARM_SLOAD, } @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_4844.py b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_4844.py index ac6733817e6..9774befab96 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_4844.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_4844.py @@ -189,7 +189,7 @@ def gas_costs(cls) -> GasCosts: """On Cancun, the point evaluation precompile gas cost is set.""" return replace( super(EIP4844, cls).gas_costs(), - GAS_PRECOMPILE_POINT_EVALUATION=50_000, + PRECOMPILE_POINT_EVALUATION=50_000, ) @classmethod @@ -208,7 +208,7 @@ def opcode_gas_map( base_map = super(EIP4844, cls).opcode_gas_map() # Add Cancun-specific opcodes - return {**base_map, Opcodes.BLOBHASH: gas_costs.GAS_VERY_LOW} + return {**base_map, Opcodes.BLOBHASH: gas_costs.VERY_LOW} @classmethod def valid_opcodes(cls) -> List[Opcodes]: diff --git a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_5656.py b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_5656.py index a3d0190c6f3..3365f3c2296 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_5656.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_5656.py @@ -27,7 +27,7 @@ def opcode_gas_map( return { **base_map, Opcodes.MCOPY: cls._with_memory_expansion( - cls._with_data_copy(gas_costs.GAS_VERY_LOW, gas_costs), + cls._with_data_copy(gas_costs.VERY_LOW, gas_costs), memory_expansion_calculator, ), } diff --git a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_7516.py b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_7516.py index 87fde9fc426..194e3e27852 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_7516.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/cancun/eip_7516.py @@ -29,7 +29,7 @@ def opcode_gas_map( # Add Cancun-specific opcodes return { **base_map, - Opcodes.BLOBBASEFEE: gas_costs.GAS_BASE, + Opcodes.BLOBBASEFEE: gas_costs.BASE, } @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_1014.py b/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_1014.py index 5dacb5b54cd..01201e0559a 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_1014.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_1014.py @@ -26,9 +26,9 @@ def _calculate_create2_gas( init_code_size = metadata["init_code_size"] init_code_words = (init_code_size + 31) // 32 - hash_gas = gas_costs.GAS_KECCAK256_PER_WORD * init_code_words + hash_gas = gas_costs.OPCODE_KECCACK256_PER_WORD * init_code_words - return gas_costs.GAS_CREATE + hash_gas + return gas_costs.OPCODE_CREATE_BASE + hash_gas @classmethod def create_opcodes(cls) -> List[Opcodes]: diff --git a/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_145.py b/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_145.py index 2ca9ca345c6..6a1b1cd854a 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_145.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/constantinople/eip_145.py @@ -25,9 +25,9 @@ def opcode_gas_map( base_map = super(EIP145, cls).opcode_gas_map() return { **base_map, - Opcodes.SHL: gas_costs.GAS_VERY_LOW, - Opcodes.SHR: gas_costs.GAS_VERY_LOW, - Opcodes.SAR: gas_costs.GAS_VERY_LOW, + Opcodes.SHL: gas_costs.VERY_LOW, + Opcodes.SHR: gas_costs.VERY_LOW, + Opcodes.SAR: gas_costs.VERY_LOW, } @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/eips/homestead/eip_2.py b/packages/testing/src/execution_testing/forks/forks/eips/homestead/eip_2.py index 29007094e3d..811094f0a98 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/homestead/eip_2.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/homestead/eip_2.py @@ -43,7 +43,7 @@ def fn( authorization_list_or_count=authorization_list_or_count, ) if contract_creation: - intrinsic_cost += gas_costs.GAS_TX_CREATE + intrinsic_cost += gas_costs.TX_CREATE return intrinsic_cost return fn diff --git a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1108.py b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1108.py index 6d45947dc1f..512a2c2c44f 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1108.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1108.py @@ -18,8 +18,8 @@ def gas_costs(cls) -> GasCosts: """Reduce BN254 precompile gas costs.""" return replace( super(EIP1108, cls).gas_costs(), - GAS_PRECOMPILE_ECADD=150, - GAS_PRECOMPILE_ECMUL=6000, - GAS_PRECOMPILE_ECPAIRING_BASE=45_000, - GAS_PRECOMPILE_ECPAIRING_PER_POINT=34_000, + PRECOMPILE_ECADD=150, + PRECOMPILE_ECMUL=6000, + PRECOMPILE_ECPAIRING_BASE=45_000, + PRECOMPILE_ECPAIRING_PER_POINT=34_000, ) diff --git a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1344.py b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1344.py index 89a7272f497..207aae46994 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1344.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1344.py @@ -24,7 +24,7 @@ def opcode_gas_map( """Add CHAINID opcode gas cost.""" gas_costs = cls.gas_costs() base_map = super(EIP1344, cls).opcode_gas_map() - return {**base_map, Opcodes.CHAINID: gas_costs.GAS_BASE} + return {**base_map, Opcodes.CHAINID: gas_costs.BASE} @classmethod def valid_opcodes(cls) -> List[Opcodes]: diff --git a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_152.py b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_152.py index 9979cc4076d..e8451f88fdf 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_152.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_152.py @@ -28,5 +28,5 @@ def gas_costs(cls) -> GasCosts: """Set BLAKE2F per-round gas cost.""" return replace( super(EIP152, cls).gas_costs(), - GAS_PRECOMPILE_BLAKE2F_PER_ROUND=1, + PRECOMPILE_BLAKE2F_PER_ROUND=1, ) diff --git a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1884.py b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1884.py index f434b90a56e..b79a3c1e4fa 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1884.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_1884.py @@ -23,7 +23,7 @@ def opcode_gas_map( """Add SELFBALANCE opcode gas cost.""" gas_costs = cls.gas_costs() base_map = super(EIP1884, cls).opcode_gas_map() - return {**base_map, Opcodes.SELFBALANCE: gas_costs.GAS_LOW} + return {**base_map, Opcodes.SELFBALANCE: gas_costs.LOW} @classmethod def valid_opcodes(cls) -> List[Opcodes]: diff --git a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_2028.py b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_2028.py index 6dbb2446b43..ca6fed863ed 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_2028.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/istanbul/eip_2028.py @@ -20,5 +20,5 @@ def gas_costs(cls) -> GasCosts: """Reduce non-zero calldata byte gas cost to 16.""" return replace( super(EIP2028, cls).gas_costs(), - GAS_TX_DATA_PER_NON_ZERO=16, + TX_DATA_PER_NON_ZERO=16, ) diff --git a/packages/testing/src/execution_testing/forks/forks/eips/london/eip_3198.py b/packages/testing/src/execution_testing/forks/forks/eips/london/eip_3198.py index 5be886c92f5..df8e3f1373d 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/london/eip_3198.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/london/eip_3198.py @@ -24,7 +24,7 @@ def opcode_gas_map( """Add BASEFEE opcode gas cost.""" gas_costs = cls.gas_costs() base_map = super(EIP3198, cls).opcode_gas_map() - return {**base_map, Opcodes.BASEFEE: gas_costs.GAS_BASE} + return {**base_map, Opcodes.BASEFEE: gas_costs.BASE} @classmethod def valid_opcodes(cls) -> List[Opcodes]: diff --git a/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7939.py b/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7939.py index 88b5a23e783..c53935a4d4d 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7939.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7939.py @@ -25,7 +25,7 @@ def opcode_gas_map( base_map = super(EIP7939, cls).opcode_gas_map() return { **base_map, - Opcodes.CLZ: gas_costs.GAS_LOW, + Opcodes.CLZ: gas_costs.LOW, } @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7951.py b/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7951.py index 1729515f158..e80674d2725 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7951.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/osaka/eip_7951.py @@ -35,5 +35,5 @@ def gas_costs(cls) -> GasCosts: """Set the P256VERIFY precompile gas cost.""" return replace( super(EIP7951, cls).gas_costs(), - GAS_PRECOMPILE_P256VERIFY=6_900, + PRECOMPILE_P256VERIFY=6_900, ) diff --git a/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_2537.py b/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_2537.py index 92702858ed6..d0cb4edc70b 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_2537.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_2537.py @@ -47,12 +47,12 @@ def gas_costs(cls) -> GasCosts: """Add gas costs for BLS12-381 precompiles.""" return replace( super(EIP2537, cls).gas_costs(), - GAS_PRECOMPILE_BLS_G1ADD=375, - GAS_PRECOMPILE_BLS_G1MUL=12_000, - GAS_PRECOMPILE_BLS_G1MAP=5_500, - GAS_PRECOMPILE_BLS_G2ADD=600, - GAS_PRECOMPILE_BLS_G2MUL=22_500, - GAS_PRECOMPILE_BLS_G2MAP=23_800, - GAS_PRECOMPILE_BLS_PAIRING_BASE=37_700, - GAS_PRECOMPILE_BLS_PAIRING_PER_PAIR=32_600, + PRECOMPILE_BLS_G1ADD=375, + PRECOMPILE_BLS_G1MUL=12_000, + PRECOMPILE_BLS_G1MAP=5_500, + PRECOMPILE_BLS_G2ADD=600, + PRECOMPILE_BLS_G2MUL=22_500, + PRECOMPILE_BLS_G2MAP=23_800, + PRECOMPILE_BLS_PAIRING_BASE=37_700, + PRECOMPILE_BLS_PAIRING_PER_PAIR=32_600, ) diff --git a/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7623.py b/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7623.py index 894ac85b433..1a073f11a92 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7623.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7623.py @@ -29,8 +29,8 @@ def gas_costs(cls) -> GasCosts: """Add standard and floor token costs for calldata.""" return replace( super(EIP7623, cls).gas_costs(), - GAS_TX_DATA_TOKEN_STANDARD=4, - GAS_TX_DATA_TOKEN_FLOOR=10, + TX_DATA_TOKEN_STANDARD=4, + TX_DATA_TOKEN_FLOOR=10, ) @classmethod @@ -47,8 +47,8 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int: num_non_zeros = len(raw) - num_zeros tokens = num_zeros + num_non_zeros * 4 if floor: - return tokens * gas_costs.GAS_TX_DATA_TOKEN_FLOOR - return tokens * gas_costs.GAS_TX_DATA_TOKEN_STANDARD + return tokens * gas_costs.TX_DATA_TOKEN_FLOOR + return tokens * gas_costs.TX_DATA_TOKEN_STANDARD return fn @@ -65,7 +65,7 @@ def transaction_data_floor_cost_calculator( def fn(*, data: BytesConvertible) -> int: return ( calldata_gas_calculator(data=data, floor=True) - + gas_costs.GAS_TX_BASE + + gas_costs.TX_BASE ) return fn diff --git a/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7702.py b/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7702.py index 1904b135f6a..d19fd6009c1 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7702.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/prague/eip_7702.py @@ -33,7 +33,7 @@ def gas_costs(cls) -> GasCosts: """Add gas costs for authorization operations.""" return replace( super(EIP7702, cls).gas_costs(), - GAS_AUTH_PER_EMPTY_ACCOUNT=25_000, + AUTH_PER_EMPTY_ACCOUNT=25_000, REFUND_AUTH_PER_EXISTING_ACCOUNT=12_500, ) @@ -50,9 +50,9 @@ def _calculate_call_gas( if metadata["delegated_address"] or metadata["delegated_address_warm"]: if metadata["delegated_address_warm"]: - base_cost += gas_costs.GAS_WARM_ACCESS + base_cost += gas_costs.WARM_ACCESS else: - base_cost += gas_costs.GAS_COLD_ACCOUNT_ACCESS + base_cost += gas_costs.COLD_ACCOUNT_ACCESS return base_cost @@ -89,7 +89,7 @@ def fn( ) intrinsic_cost += ( authorization_list_or_count - * gas_costs.GAS_AUTH_PER_EMPTY_ACCOUNT + * gas_costs.AUTH_PER_EMPTY_ACCOUNT ) return intrinsic_cost diff --git a/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3855.py b/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3855.py index cf734cb3f3d..fd6586dfa71 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3855.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3855.py @@ -26,7 +26,7 @@ def opcode_gas_map( base_map = super(EIP3855, cls).opcode_gas_map() return { **base_map, - Opcodes.PUSH0: gas_costs.GAS_BASE, + Opcodes.PUSH0: gas_costs.BASE, } @classmethod diff --git a/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3860.py b/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3860.py index c5e52708bce..128c162cc9d 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3860.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/shanghai/eip_3860.py @@ -36,7 +36,7 @@ def _calculate_create_gas( init_code_size = metadata["init_code_size"] init_code_words = (init_code_size + 31) // 32 - init_code_gas = gas_costs.GAS_CODE_INIT_PER_WORD * init_code_words + init_code_gas = gas_costs.CODE_INIT_PER_WORD * init_code_words return base_cost + init_code_gas @@ -55,6 +55,6 @@ def _calculate_create2_gas( init_code_size = metadata["init_code_size"] init_code_words = (init_code_size + 31) // 32 - init_code_gas = gas_costs.GAS_CODE_INIT_PER_WORD * init_code_words + init_code_gas = gas_costs.CODE_INIT_PER_WORD * init_code_words return base_cost + init_code_gas diff --git a/packages/testing/src/execution_testing/forks/forks/eips/spurious_dragon/eip_161.py b/packages/testing/src/execution_testing/forks/forks/eips/spurious_dragon/eip_161.py index 6a5b61d919c..2806276fb3e 100644 --- a/packages/testing/src/execution_testing/forks/forks/eips/spurious_dragon/eip_161.py +++ b/packages/testing/src/execution_testing/forks/forks/eips/spurious_dragon/eip_161.py @@ -26,9 +26,9 @@ def _calculate_call_gas( metadata = opcode.metadata if "value_transfer" in metadata: if metadata["value_transfer"]: - base_cost += gas_costs.GAS_CALL_VALUE + base_cost += gas_costs.CALL_VALUE if metadata["account_new"]: - base_cost += gas_costs.GAS_NEW_ACCOUNT + base_cost += gas_costs.NEW_ACCOUNT elif metadata["account_new"]: raise ValueError("Account new requires value transfer") diff --git a/packages/testing/src/execution_testing/forks/forks/forks.py b/packages/testing/src/execution_testing/forks/forks/forks.py index 92eeb70a89a..49fcaf32cd9 100644 --- a/packages/testing/src/execution_testing/forks/forks/forks.py +++ b/packages/testing/src/execution_testing/forks/forks/forks.py @@ -32,7 +32,7 @@ TransactionDataFloorCostCalculator, TransactionIntrinsicCostCalculator, ) -from ..gas_costs import GasCosts +from ..gas_costs import BASE, HIGH, LOW, MID, VERY_LOW, GasCosts from . import eips from .helpers import ceiling_division @@ -97,73 +97,118 @@ def gas_costs(cls) -> GasCosts: Return dataclass with the defined gas costs constants for genesis. """ return GasCosts( - 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, - GAS_TX_ACCESS_LIST_ADDRESS=2_400, - GAS_TX_ACCESS_LIST_STORAGE_KEY=1_900, - GAS_WARM_SLOAD=100, - GAS_COLD_STORAGE_ACCESS=2_100, - GAS_STORAGE_SET=20_000, - GAS_COLD_STORAGE_WRITE=5_000, - GAS_STORAGE_RESET=2_900, + # Tiers + BASE=BASE, + VERY_LOW=VERY_LOW, + LOW=LOW, + MID=MID, + HIGH=HIGH, + # Access + WARM_ACCESS=100, + COLD_ACCOUNT_ACCESS=2_600, + WARM_SLOAD=100, + COLD_STORAGE_ACCESS=2_100, + # Storage + STORAGE_SET=20_000, + COLD_STORAGE_WRITE=5_000, + STORAGE_RESET=2_900, + # Call + CALL_VALUE=9_000, + CALL_STIPEND=2_300, + NEW_ACCOUNT=25_000, + # Contract Creation + CODE_DEPOSIT_PER_BYTE=200, + CODE_INIT_PER_WORD=2, + # Authorization + AUTH_PER_EMPTY_ACCOUNT=0, + # Utility + MEMORY_PER_WORD=3, + # Transactions + TX_BASE=21_000, + TX_ACCESS_LIST_ADDRESS=2_400, + TX_ACCESS_LIST_STORAGE_KEY=1_900, + TX_DATA_PER_ZERO=4, + TX_DATA_PER_NON_ZERO=68, + TX_CREATE=32_000, + # Refunds REFUND_STORAGE_CLEAR=4_800, - GAS_SELF_DESTRUCT=5_000, - GAS_CREATE=32_000, - GAS_CODE_DEPOSIT_PER_BYTE=200, - GAS_CODE_INIT_PER_WORD=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, - GAS_TX_DATA_PER_ZERO=4, - GAS_TX_DATA_PER_NON_ZERO=68, - GAS_TX_BASE=21_000, - GAS_TX_CREATE=32_000, - GAS_LOG=375, - GAS_LOG_DATA_PER_BYTE=8, - GAS_LOG_TOPIC=375, - GAS_KECCAK256=30, - GAS_KECCAK256_PER_WORD=6, - GAS_COPY=3, - GAS_BLOCK_HASH=20, - GAS_PRECOMPILE_ECRECOVER=3_000, - GAS_PRECOMPILE_SHA256_BASE=60, - GAS_PRECOMPILE_SHA256_PER_WORD=12, - GAS_PRECOMPILE_RIPEMD160_BASE=600, - GAS_PRECOMPILE_RIPEMD160_PER_WORD=120, - GAS_PRECOMPILE_IDENTITY_BASE=15, - GAS_PRECOMPILE_IDENTITY_PER_WORD=3, + REFUND_AUTH_PER_EXISTING_ACCOUNT=0, + # Precompiles + PRECOMPILE_ECRECOVER=3_000, + PRECOMPILE_SHA256_BASE=60, + PRECOMPILE_SHA256_PER_WORD=12, + PRECOMPILE_RIPEMD160_BASE=600, + PRECOMPILE_RIPEMD160_PER_WORD=120, + PRECOMPILE_IDENTITY_BASE=15, + PRECOMPILE_IDENTITY_PER_WORD=3, + # Static Opcodes + OPCODE_ADD=VERY_LOW, + OPCODE_SUB=VERY_LOW, + OPCODE_MUL=LOW, + OPCODE_DIV=LOW, + OPCODE_SDIV=LOW, + OPCODE_MOD=LOW, + OPCODE_SMOD=LOW, + OPCODE_ADDMOD=MID, + OPCODE_MULMOD=MID, + OPCODE_SIGNEXTEND=LOW, + OPCODE_LT=VERY_LOW, + OPCODE_GT=VERY_LOW, + OPCODE_SLT=VERY_LOW, + OPCODE_SGT=VERY_LOW, + OPCODE_EQ=VERY_LOW, + OPCODE_ISZERO=VERY_LOW, + OPCODE_AND=VERY_LOW, + OPCODE_OR=VERY_LOW, + OPCODE_XOR=VERY_LOW, + OPCODE_NOT=VERY_LOW, + OPCODE_BYTE=VERY_LOW, + OPCODE_JUMP=MID, + OPCODE_JUMPI=HIGH, + OPCODE_JUMPDEST=1, + OPCODE_CALLDATALOAD=VERY_LOW, + OPCODE_BLOCKHASH=20, + OPCODE_COINBASE=BASE, + OPCODE_PUSH=VERY_LOW, + OPCODE_DUP=VERY_LOW, + OPCODE_SWAP=VERY_LOW, + # Dynamic Opcode Components + OPCODE_CALLDATACOPY_BASE=VERY_LOW, + OPCODE_CODECOPY_BASE=VERY_LOW, + OPCODE_MLOAD_BASE=VERY_LOW, + OPCODE_MSTORE_BASE=VERY_LOW, + OPCODE_MSTORE8_BASE=VERY_LOW, + OPCODE_SELFDESTRUCT_BASE=5_000, + OPCODE_COPY_PER_WORD=3, + OPCODE_CREATE_BASE=32_000, + OPCODE_EXP_BASE=10, + OPCODE_EXP_PER_BYTE=50, + OPCODE_LOG_BASE=375, + OPCODE_LOG_DATA_PER_BYTE=8, + OPCODE_LOG_TOPIC=375, + OPCODE_KECCAK256_BASE=30, + OPCODE_KECCACK256_PER_WORD=6, # Zero-initialized: introduced in later forks, set via # replace() in the fork that activates them. - GAS_TX_DATA_TOKEN_STANDARD=0, - GAS_TX_DATA_TOKEN_FLOOR=0, - GAS_AUTH_PER_EMPTY_ACCOUNT=0, - REFUND_AUTH_PER_EXISTING_ACCOUNT=0, - GAS_PRECOMPILE_ECADD=0, - GAS_PRECOMPILE_ECMUL=0, - GAS_PRECOMPILE_ECPAIRING_BASE=0, - GAS_PRECOMPILE_ECPAIRING_PER_POINT=0, - GAS_PRECOMPILE_BLAKE2F_BASE=0, - GAS_PRECOMPILE_BLAKE2F_PER_ROUND=0, - GAS_PRECOMPILE_POINT_EVALUATION=0, - GAS_PRECOMPILE_BLS_G1ADD=0, - GAS_PRECOMPILE_BLS_G1MUL=0, - GAS_PRECOMPILE_BLS_G1MAP=0, - GAS_PRECOMPILE_BLS_G2ADD=0, - GAS_PRECOMPILE_BLS_G2MUL=0, - GAS_PRECOMPILE_BLS_G2MAP=0, - GAS_PRECOMPILE_BLS_PAIRING_BASE=0, - GAS_PRECOMPILE_BLS_PAIRING_PER_PAIR=0, - GAS_PRECOMPILE_P256VERIFY=0, - GAS_BLOCK_ACCESS_LIST_ITEM=0, + TX_DATA_TOKEN_STANDARD=0, + TX_DATA_TOKEN_FLOOR=0, + PRECOMPILE_ECADD=0, + PRECOMPILE_ECMUL=0, + PRECOMPILE_ECPAIRING_BASE=0, + PRECOMPILE_ECPAIRING_PER_POINT=0, + PRECOMPILE_BLAKE2F_BASE=0, + PRECOMPILE_BLAKE2F_PER_ROUND=0, + PRECOMPILE_POINT_EVALUATION=0, + PRECOMPILE_BLS_G1ADD=0, + PRECOMPILE_BLS_G1MUL=0, + PRECOMPILE_BLS_G1MAP=0, + PRECOMPILE_BLS_G2ADD=0, + PRECOMPILE_BLS_G2MUL=0, + PRECOMPILE_BLS_G2MAP=0, + PRECOMPILE_BLS_PAIRING_BASE=0, + PRECOMPILE_BLS_PAIRING_PER_PAIR=0, + PRECOMPILE_P256VERIFY=0, + BLOCK_ACCESS_LIST_ITEM=0, ) @classmethod @@ -232,9 +277,9 @@ def wrapper(opcode: OpcodeBase) -> int: # Add account access cost based on warmth if opcode.metadata["address_warm"]: - access_cost = gas_costs.GAS_WARM_ACCESS + access_cost = gas_costs.WARM_ACCESS else: - access_cost = gas_costs.GAS_COLD_ACCOUNT_ACCESS + access_cost = gas_costs.COLD_ACCOUNT_ACCESS return base_cost + access_cost @@ -252,7 +297,8 @@ def _with_data_copy( Args: base_gas: Either a constant gas cost (int) or a callable that calculates it - gas_costs: The gas costs dataclass for accessing GAS_COPY + gas_costs: The gas costs dataclass for accessing + OPCODE_COPY_PER_WORD Returns: A callable that calculates base_gas + copy_cost @@ -269,7 +315,7 @@ def wrapper(opcode: OpcodeBase) -> int: # Add copy cost based on data size data_size = opcode.metadata["data_size"] word_count = (data_size + 31) // 32 - copy_cost = gas_costs.GAS_COPY * word_count + copy_cost = gas_costs.OPCODE_COPY_PER_WORD * word_count return base_cost + copy_cost @@ -297,60 +343,62 @@ def opcode_gas_map( return { # Stop and arithmetic operations Opcodes.STOP: 0, - Opcodes.ADD: gas_costs.GAS_VERY_LOW, - Opcodes.MUL: gas_costs.GAS_LOW, - Opcodes.SUB: gas_costs.GAS_VERY_LOW, - Opcodes.DIV: gas_costs.GAS_LOW, - Opcodes.SDIV: gas_costs.GAS_LOW, - Opcodes.MOD: gas_costs.GAS_LOW, - Opcodes.SMOD: gas_costs.GAS_LOW, - Opcodes.ADDMOD: gas_costs.GAS_MID, - Opcodes.MULMOD: gas_costs.GAS_MID, + Opcodes.ADD: gas_costs.OPCODE_ADD, + Opcodes.MUL: gas_costs.OPCODE_MUL, + Opcodes.SUB: gas_costs.OPCODE_SUB, + Opcodes.DIV: gas_costs.OPCODE_DIV, + Opcodes.SDIV: gas_costs.OPCODE_SDIV, + Opcodes.MOD: gas_costs.OPCODE_MOD, + Opcodes.SMOD: gas_costs.OPCODE_SMOD, + Opcodes.ADDMOD: gas_costs.OPCODE_ADDMOD, + Opcodes.MULMOD: gas_costs.OPCODE_MULMOD, Opcodes.EXP: lambda op: ( - gas_costs.GAS_EXPONENTIATION - + gas_costs.GAS_EXPONENTIATION_PER_BYTE + gas_costs.OPCODE_EXP_BASE + + gas_costs.OPCODE_EXP_PER_BYTE * ((op.metadata["exponent"].bit_length() + 7) // 8) ), - Opcodes.SIGNEXTEND: gas_costs.GAS_LOW, + Opcodes.SIGNEXTEND: gas_costs.OPCODE_SIGNEXTEND, # Comparison & bitwise logic operations - Opcodes.LT: gas_costs.GAS_VERY_LOW, - Opcodes.GT: gas_costs.GAS_VERY_LOW, - Opcodes.SLT: gas_costs.GAS_VERY_LOW, - Opcodes.SGT: gas_costs.GAS_VERY_LOW, - Opcodes.EQ: gas_costs.GAS_VERY_LOW, - Opcodes.ISZERO: gas_costs.GAS_VERY_LOW, - Opcodes.AND: gas_costs.GAS_VERY_LOW, - Opcodes.OR: gas_costs.GAS_VERY_LOW, - Opcodes.XOR: gas_costs.GAS_VERY_LOW, - Opcodes.NOT: gas_costs.GAS_VERY_LOW, - Opcodes.BYTE: gas_costs.GAS_VERY_LOW, + Opcodes.LT: gas_costs.OPCODE_LT, + Opcodes.GT: gas_costs.OPCODE_GT, + Opcodes.SLT: gas_costs.OPCODE_SLT, + Opcodes.SGT: gas_costs.OPCODE_SGT, + Opcodes.EQ: gas_costs.OPCODE_EQ, + Opcodes.ISZERO: gas_costs.OPCODE_ISZERO, + Opcodes.AND: gas_costs.OPCODE_AND, + Opcodes.OR: gas_costs.OPCODE_OR, + Opcodes.XOR: gas_costs.OPCODE_XOR, + Opcodes.NOT: gas_costs.OPCODE_NOT, + Opcodes.BYTE: gas_costs.OPCODE_BYTE, # SHA3 Opcodes.SHA3: cls._with_memory_expansion( lambda op: ( - gas_costs.GAS_KECCAK256 - + gas_costs.GAS_KECCAK256_PER_WORD + gas_costs.OPCODE_KECCAK256_BASE + + gas_costs.OPCODE_KECCACK256_PER_WORD * ((op.metadata["data_size"] + 31) // 32) ), memory_expansion_calculator, ), # Environmental information - Opcodes.ADDRESS: gas_costs.GAS_BASE, + Opcodes.ADDRESS: gas_costs.BASE, Opcodes.BALANCE: cls._with_account_access(0, gas_costs), - Opcodes.ORIGIN: gas_costs.GAS_BASE, - Opcodes.CALLER: gas_costs.GAS_BASE, - Opcodes.CALLVALUE: gas_costs.GAS_BASE, - Opcodes.CALLDATALOAD: gas_costs.GAS_VERY_LOW, - Opcodes.CALLDATASIZE: gas_costs.GAS_BASE, + Opcodes.ORIGIN: gas_costs.BASE, + Opcodes.CALLER: gas_costs.BASE, + Opcodes.CALLVALUE: gas_costs.BASE, + Opcodes.CALLDATALOAD: gas_costs.OPCODE_CALLDATALOAD, + Opcodes.CALLDATASIZE: gas_costs.BASE, Opcodes.CALLDATACOPY: cls._with_memory_expansion( - cls._with_data_copy(gas_costs.GAS_VERY_LOW, gas_costs), + cls._with_data_copy( + gas_costs.OPCODE_CALLDATACOPY_BASE, gas_costs + ), memory_expansion_calculator, ), - Opcodes.CODESIZE: gas_costs.GAS_BASE, + Opcodes.CODESIZE: gas_costs.BASE, Opcodes.CODECOPY: cls._with_memory_expansion( - cls._with_data_copy(gas_costs.GAS_VERY_LOW, gas_costs), + cls._with_data_copy(gas_costs.OPCODE_CODECOPY_BASE, gas_costs), memory_expansion_calculator, ), - Opcodes.GASPRICE: gas_costs.GAS_BASE, + Opcodes.GASPRICE: gas_costs.BASE, Opcodes.EXTCODESIZE: cls._with_account_access(0, gas_costs), Opcodes.EXTCODECOPY: cls._with_memory_expansion( cls._with_data_copy( @@ -360,94 +408,97 @@ def opcode_gas_map( memory_expansion_calculator, ), # Block information - Opcodes.BLOCKHASH: gas_costs.GAS_BLOCK_HASH, - Opcodes.COINBASE: gas_costs.GAS_BASE, - Opcodes.TIMESTAMP: gas_costs.GAS_BASE, - Opcodes.NUMBER: gas_costs.GAS_BASE, - Opcodes.PREVRANDAO: gas_costs.GAS_BASE, - Opcodes.GASLIMIT: gas_costs.GAS_BASE, + Opcodes.BLOCKHASH: gas_costs.OPCODE_BLOCKHASH, + Opcodes.COINBASE: gas_costs.OPCODE_COINBASE, + Opcodes.TIMESTAMP: gas_costs.BASE, + Opcodes.NUMBER: gas_costs.BASE, + Opcodes.PREVRANDAO: gas_costs.BASE, + Opcodes.GASLIMIT: gas_costs.BASE, # Stack, memory, storage and flow operations - Opcodes.POP: gas_costs.GAS_BASE, + Opcodes.POP: gas_costs.BASE, Opcodes.MLOAD: cls._with_memory_expansion( - gas_costs.GAS_VERY_LOW, memory_expansion_calculator + gas_costs.OPCODE_MLOAD_BASE, + memory_expansion_calculator, ), Opcodes.MSTORE: cls._with_memory_expansion( - gas_costs.GAS_VERY_LOW, memory_expansion_calculator + gas_costs.OPCODE_MSTORE_BASE, + memory_expansion_calculator, ), Opcodes.MSTORE8: cls._with_memory_expansion( - gas_costs.GAS_VERY_LOW, memory_expansion_calculator + gas_costs.OPCODE_MSTORE8_BASE, + memory_expansion_calculator, ), Opcodes.SLOAD: lambda op: ( - gas_costs.GAS_WARM_SLOAD + gas_costs.WARM_SLOAD if op.metadata["key_warm"] - else gas_costs.GAS_COLD_STORAGE_ACCESS + else gas_costs.COLD_STORAGE_ACCESS ), Opcodes.SSTORE: lambda op: cls._calculate_sstore_gas( op, gas_costs ), - Opcodes.JUMP: gas_costs.GAS_MID, - Opcodes.JUMPI: gas_costs.GAS_HIGH, - Opcodes.PC: gas_costs.GAS_BASE, - Opcodes.MSIZE: gas_costs.GAS_BASE, - Opcodes.GAS: gas_costs.GAS_BASE, - Opcodes.JUMPDEST: gas_costs.GAS_JUMPDEST, + Opcodes.JUMP: gas_costs.OPCODE_JUMP, + Opcodes.JUMPI: gas_costs.OPCODE_JUMPI, + Opcodes.PC: gas_costs.BASE, + Opcodes.MSIZE: gas_costs.BASE, + Opcodes.GAS: gas_costs.BASE, + Opcodes.JUMPDEST: gas_costs.OPCODE_JUMPDEST, # Push operations (PUSH1 through PUSH32) **{ - getattr(Opcodes, f"PUSH{i}"): gas_costs.GAS_VERY_LOW + getattr(Opcodes, f"PUSH{i}"): gas_costs.OPCODE_PUSH for i in range(1, 33) }, # Dup operations (DUP1 through DUP16) **{ - getattr(Opcodes, f"DUP{i}"): gas_costs.GAS_VERY_LOW + getattr(Opcodes, f"DUP{i}"): gas_costs.OPCODE_DUP for i in range(1, 17) }, # Swap operations (SWAP1 through SWAP16) **{ - getattr(Opcodes, f"SWAP{i}"): gas_costs.GAS_VERY_LOW + getattr(Opcodes, f"SWAP{i}"): gas_costs.OPCODE_SWAP for i in range(1, 17) }, # Logging operations Opcodes.LOG0: cls._with_memory_expansion( lambda op: ( - gas_costs.GAS_LOG - + gas_costs.GAS_LOG_DATA_PER_BYTE + gas_costs.OPCODE_LOG_BASE + + gas_costs.OPCODE_LOG_DATA_PER_BYTE * op.metadata["data_size"] ), memory_expansion_calculator, ), Opcodes.LOG1: cls._with_memory_expansion( lambda op: ( - gas_costs.GAS_LOG - + gas_costs.GAS_LOG_DATA_PER_BYTE + gas_costs.OPCODE_LOG_BASE + + gas_costs.OPCODE_LOG_DATA_PER_BYTE * op.metadata["data_size"] - + gas_costs.GAS_LOG_TOPIC + + gas_costs.OPCODE_LOG_TOPIC ), memory_expansion_calculator, ), Opcodes.LOG2: cls._with_memory_expansion( lambda op: ( - gas_costs.GAS_LOG - + gas_costs.GAS_LOG_DATA_PER_BYTE + gas_costs.OPCODE_LOG_BASE + + gas_costs.OPCODE_LOG_DATA_PER_BYTE * op.metadata["data_size"] - + gas_costs.GAS_LOG_TOPIC * 2 + + gas_costs.OPCODE_LOG_TOPIC * 2 ), memory_expansion_calculator, ), Opcodes.LOG3: cls._with_memory_expansion( lambda op: ( - gas_costs.GAS_LOG - + gas_costs.GAS_LOG_DATA_PER_BYTE + gas_costs.OPCODE_LOG_BASE + + gas_costs.OPCODE_LOG_DATA_PER_BYTE * op.metadata["data_size"] - + gas_costs.GAS_LOG_TOPIC * 3 + + gas_costs.OPCODE_LOG_TOPIC * 3 ), memory_expansion_calculator, ), Opcodes.LOG4: cls._with_memory_expansion( lambda op: ( - gas_costs.GAS_LOG - + gas_costs.GAS_LOG_DATA_PER_BYTE + gas_costs.OPCODE_LOG_BASE + + gas_costs.OPCODE_LOG_DATA_PER_BYTE * op.metadata["data_size"] - + gas_costs.GAS_LOG_TOPIC * 4 + + gas_costs.OPCODE_LOG_TOPIC * 4 ), memory_expansion_calculator, ), @@ -570,15 +621,13 @@ def _calculate_sstore_refund( # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - refund += ( - gas_costs.GAS_STORAGE_SET - gas_costs.GAS_WARM_SLOAD - ) + refund += gas_costs.STORAGE_SET - gas_costs.WARM_SLOAD else: # Slot was originally non-empty and was UPDATED earlier refund += ( - gas_costs.GAS_COLD_STORAGE_WRITE - - gas_costs.GAS_COLD_STORAGE_ACCESS - - gas_costs.GAS_WARM_SLOAD + gas_costs.COLD_STORAGE_WRITE + - gas_costs.COLD_STORAGE_ACCESS + - gas_costs.WARM_SLOAD ) return refund @@ -596,20 +645,18 @@ def _calculate_sstore_gas( current_value = original_value new_value = metadata["new_value"] - gas_cost = ( - 0 if metadata["key_warm"] else gas_costs.GAS_COLD_STORAGE_ACCESS - ) + gas_cost = 0 if metadata["key_warm"] else gas_costs.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += gas_costs.GAS_STORAGE_SET + gas_cost += gas_costs.STORAGE_SET else: gas_cost += ( - gas_costs.GAS_COLD_STORAGE_WRITE - - gas_costs.GAS_COLD_STORAGE_ACCESS + gas_costs.COLD_STORAGE_WRITE + - gas_costs.COLD_STORAGE_ACCESS ) else: - gas_cost += gas_costs.GAS_WARM_SLOAD + gas_cost += gas_costs.WARM_SLOAD return gas_cost @@ -624,9 +671,9 @@ def _calculate_call_gas( # Base cost depends on address warmth if metadata["address_warm"]: - base_cost = gas_costs.GAS_WARM_ACCESS + base_cost = gas_costs.WARM_ACCESS else: - base_cost = gas_costs.GAS_COLD_ACCOUNT_ACCESS + base_cost = gas_costs.COLD_ACCOUNT_ACCESS return base_cost @@ -636,7 +683,7 @@ def _calculate_create_gas( ) -> int: """CREATE gas is constant at Frontier.""" del opcode - return gas_costs.GAS_CREATE + return gas_costs.OPCODE_CREATE_BASE @classmethod def _calculate_create2_gas( @@ -658,7 +705,7 @@ def _calculate_return_gas( # Code deposit cost when returning from initcode code_deposit_size = metadata["code_deposit_size"] - return gas_costs.GAS_CODE_DEPOSIT_PER_BYTE * code_deposit_size + return gas_costs.CODE_DEPOSIT_PER_BYTE * code_deposit_size @classmethod def _calculate_selfdestruct_gas( @@ -667,15 +714,15 @@ def _calculate_selfdestruct_gas( """Calculate SELFDESTRUCT gas cost based on metadata.""" metadata = opcode.metadata - base_cost = gas_costs.GAS_SELF_DESTRUCT + base_cost = gas_costs.OPCODE_SELFDESTRUCT_BASE # Check if the beneficiary is cold if not metadata["address_warm"]: - base_cost += gas_costs.GAS_COLD_ACCOUNT_ACCESS + base_cost += gas_costs.COLD_ACCOUNT_ACCESS # Check if creating a new account if metadata["account_new"]: - base_cost += gas_costs.GAS_NEW_ACCOUNT + base_cost += gas_costs.NEW_ACCOUNT return base_cost @@ -694,7 +741,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.GAS_MEMORY * w) + ((w * w) // 512) + return (gas_costs.MEMORY_PER_WORD * w) + ((w * w) // 512) return c(new_words) - c(previous_words) @@ -715,8 +762,8 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int: num_zeros = raw.count(0) num_non_zeros = len(raw) - num_zeros return ( - num_zeros * gas_costs.GAS_TX_DATA_PER_ZERO - + num_non_zeros * gas_costs.GAS_TX_DATA_PER_NON_ZERO + num_zeros * gas_costs.TX_DATA_PER_ZERO + + num_non_zeros * gas_costs.TX_DATA_PER_NON_ZERO ) return fn @@ -794,11 +841,11 @@ def fn( f"Authorizations are not supported in {cls.name()}" ) - intrinsic_cost: int = gas_costs.GAS_TX_BASE + intrinsic_cost: int = gas_costs.TX_BASE if contract_creation: intrinsic_cost += ( - gas_costs.GAS_CODE_INIT_PER_WORD + gas_costs.CODE_INIT_PER_WORD * ceiling_division(len(Bytes(calldata)), 32) ) diff --git a/packages/testing/src/execution_testing/forks/gas_costs.py b/packages/testing/src/execution_testing/forks/gas_costs.py index c41b6519d8d..7e637b1d37c 100644 --- a/packages/testing/src/execution_testing/forks/gas_costs.py +++ b/packages/testing/src/execution_testing/forks/gas_costs.py @@ -2,92 +2,147 @@ from dataclasses import dataclass +# Common Gas Cost Tiers +BASE = 2 +VERY_LOW = 3 +LOW = 5 +MID = 8 +HIGH = 10 + @dataclass(kw_only=True, frozen=True) class GasCosts: """Class that contains the gas cost constants for any fork.""" - 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 - GAS_TX_ACCESS_LIST_ADDRESS: int - GAS_TX_ACCESS_LIST_STORAGE_KEY: int - GAS_WARM_SLOAD: int - GAS_COLD_STORAGE_ACCESS: int - GAS_STORAGE_SET: int - GAS_COLD_STORAGE_WRITE: int - GAS_STORAGE_RESET: int - - GAS_SELF_DESTRUCT: int - GAS_CREATE: int - - GAS_CODE_DEPOSIT_PER_BYTE: int - GAS_CODE_INIT_PER_WORD: int - - GAS_CALL_VALUE: int - GAS_CALL_STIPEND: int - GAS_NEW_ACCOUNT: int - - GAS_EXPONENTIATION: int - GAS_EXPONENTIATION_PER_BYTE: int - - GAS_MEMORY: int - GAS_TX_BASE: int - GAS_TX_CREATE: int - GAS_TX_DATA_PER_ZERO: int - GAS_TX_DATA_PER_NON_ZERO: int - GAS_TX_DATA_TOKEN_STANDARD: int - GAS_TX_DATA_TOKEN_FLOOR: int - - GAS_LOG: int - GAS_LOG_DATA_PER_BYTE: int - GAS_LOG_TOPIC: int - - GAS_KECCAK256: int - GAS_KECCAK256_PER_WORD: int - - GAS_COPY: int - GAS_BLOCK_HASH: int - - GAS_AUTH_PER_EMPTY_ACCOUNT: int - - # Precompiled contract gas constants - GAS_PRECOMPILE_ECRECOVER: int - GAS_PRECOMPILE_SHA256_BASE: int - GAS_PRECOMPILE_SHA256_PER_WORD: int - GAS_PRECOMPILE_RIPEMD160_BASE: int - GAS_PRECOMPILE_RIPEMD160_PER_WORD: int - GAS_PRECOMPILE_IDENTITY_BASE: int - GAS_PRECOMPILE_IDENTITY_PER_WORD: int - - GAS_PRECOMPILE_ECADD: int - GAS_PRECOMPILE_ECMUL: int - GAS_PRECOMPILE_ECPAIRING_BASE: int - GAS_PRECOMPILE_ECPAIRING_PER_POINT: int - - GAS_PRECOMPILE_BLAKE2F_BASE: int - GAS_PRECOMPILE_BLAKE2F_PER_ROUND: int - - GAS_PRECOMPILE_POINT_EVALUATION: int - - GAS_PRECOMPILE_BLS_G1ADD: int - GAS_PRECOMPILE_BLS_G1MUL: int - GAS_PRECOMPILE_BLS_G1MAP: int - GAS_PRECOMPILE_BLS_G2ADD: int - GAS_PRECOMPILE_BLS_G2MUL: int - GAS_PRECOMPILE_BLS_G2MAP: int - GAS_PRECOMPILE_BLS_PAIRING_BASE: int - GAS_PRECOMPILE_BLS_PAIRING_PER_PAIR: int - - GAS_PRECOMPILE_P256VERIFY: int - - # Refund constants + # Tiers + BASE: int + VERY_LOW: int + LOW: int + MID: int + HIGH: int + + # Access + WARM_ACCESS: int + COLD_ACCOUNT_ACCESS: int + WARM_SLOAD: int + COLD_STORAGE_ACCESS: int + + # Storage + STORAGE_SET: int + COLD_STORAGE_WRITE: int + STORAGE_RESET: int + + # Call + CALL_VALUE: int + CALL_STIPEND: int + NEW_ACCOUNT: int + + # Contract Creation + CODE_DEPOSIT_PER_BYTE: int + CODE_INIT_PER_WORD: int + + # Authorization + AUTH_PER_EMPTY_ACCOUNT: int + + # Utility + MEMORY_PER_WORD: int + + # Transactions + TX_BASE: int + TX_CREATE: int + TX_DATA_PER_ZERO: int + TX_DATA_PER_NON_ZERO: int + TX_DATA_TOKEN_STANDARD: int + TX_DATA_TOKEN_FLOOR: int + TX_ACCESS_LIST_ADDRESS: int + TX_ACCESS_LIST_STORAGE_KEY: int + + # Refunds REFUND_STORAGE_CLEAR: int REFUND_AUTH_PER_EXISTING_ACCOUNT: int - GAS_BLOCK_ACCESS_LIST_ITEM: int + # Precompiles + PRECOMPILE_ECRECOVER: int + PRECOMPILE_SHA256_BASE: int + PRECOMPILE_SHA256_PER_WORD: int + PRECOMPILE_RIPEMD160_BASE: int + PRECOMPILE_RIPEMD160_PER_WORD: int + PRECOMPILE_IDENTITY_BASE: int + PRECOMPILE_IDENTITY_PER_WORD: int + PRECOMPILE_ECADD: int + PRECOMPILE_ECMUL: int + PRECOMPILE_ECPAIRING_BASE: int + PRECOMPILE_ECPAIRING_PER_POINT: int + PRECOMPILE_BLAKE2F_BASE: int + PRECOMPILE_BLAKE2F_PER_ROUND: int + PRECOMPILE_POINT_EVALUATION: int + PRECOMPILE_BLS_G1ADD: int + PRECOMPILE_BLS_G1MUL: int + PRECOMPILE_BLS_G1MAP: int + PRECOMPILE_BLS_G2ADD: int + PRECOMPILE_BLS_G2MUL: int + PRECOMPILE_BLS_G2MAP: int + PRECOMPILE_BLS_PAIRING_BASE: int + PRECOMPILE_BLS_PAIRING_PER_PAIR: int + PRECOMPILE_P256VERIFY: int + + # Block Access Lists + BLOCK_ACCESS_LIST_ITEM: int + + # Opcodes + OPCODE_ADD: int + OPCODE_SUB: int + OPCODE_MUL: int + OPCODE_DIV: int + OPCODE_SDIV: int + OPCODE_MOD: int + OPCODE_SMOD: int + OPCODE_ADDMOD: int + OPCODE_MULMOD: int + OPCODE_SIGNEXTEND: int + OPCODE_LT: int + OPCODE_GT: int + OPCODE_SLT: int + OPCODE_SGT: int + OPCODE_EQ: int + OPCODE_ISZERO: int + OPCODE_AND: int + OPCODE_OR: int + OPCODE_XOR: int + OPCODE_NOT: int + OPCODE_BYTE: int + OPCODE_JUMP: int + OPCODE_JUMPI: int + OPCODE_JUMPDEST: int + OPCODE_CALLDATALOAD: int + OPCODE_BLOCKHASH: int + OPCODE_COINBASE: int + OPCODE_PUSH: int + OPCODE_DUP: int + OPCODE_SWAP: int + + # Dynamic Opcode Components + OPCODE_CALLDATACOPY_BASE: int + OPCODE_CODECOPY_BASE: int + OPCODE_MLOAD_BASE: int + OPCODE_MSTORE_BASE: int + OPCODE_MSTORE8_BASE: int + OPCODE_SELFDESTRUCT_BASE: int + OPCODE_COPY_PER_WORD: int + OPCODE_CREATE_BASE: int + OPCODE_EXP_BASE: int + OPCODE_EXP_PER_BYTE: int + OPCODE_LOG_BASE: int + OPCODE_LOG_DATA_PER_BYTE: int + OPCODE_LOG_TOPIC: int + OPCODE_KECCAK256_BASE: int + OPCODE_KECCACK256_PER_WORD: int + + # Defined post-Frontier + OPCODE_SHL: int = 0 + OPCODE_SHR: int = 0 + OPCODE_SAR: int = 0 + OPCODE_RETURNDATACOPY_BASE: int = 0 + OPCODE_BLOBHASH: int = 0 + OPCODE_MCOPY_BASE: int = 0 + OPCODE_CLZ: int = 0 diff --git a/packages/testing/src/execution_testing/forks/tests/test_opcode_gas_costs.py b/packages/testing/src/execution_testing/forks/tests/test_opcode_gas_costs.py index 39fb7ac2279..472b499edd0 100644 --- a/packages/testing/src/execution_testing/forks/tests/test_opcode_gas_costs.py +++ b/packages/testing/src/execution_testing/forks/tests/test_opcode_gas_costs.py @@ -15,55 +15,55 @@ Osaka, Op.MSTORE(new_memory_size=1), Osaka.memory_expansion_gas_calculator()(new_bytes=1) - + Osaka.gas_costs().GAS_VERY_LOW, + + Osaka.gas_costs().VERY_LOW, id="mstore_memory_expansion", ), pytest.param( Osaka, Op.SSTORE, - Osaka.gas_costs().GAS_STORAGE_SET - + Osaka.gas_costs().GAS_COLD_STORAGE_ACCESS, + Osaka.gas_costs().STORAGE_SET + + Osaka.gas_costs().COLD_STORAGE_ACCESS, id="sstore_defaults", ), pytest.param( Osaka, Op.SSTORE(key_warm=True), - Osaka.gas_costs().GAS_STORAGE_SET, + Osaka.gas_costs().STORAGE_SET, id="sstore_warm_key", ), # EXP tests pytest.param( Osaka, Op.EXP(exponent=0), - Osaka.gas_costs().GAS_EXPONENTIATION, + Osaka.gas_costs().OPCODE_EXP_BASE, id="exp_zero_exponent", ), pytest.param( Osaka, Op.EXP(exponent=0xFFFFFF), # 3 bytes - Osaka.gas_costs().GAS_EXPONENTIATION - + Osaka.gas_costs().GAS_EXPONENTIATION_PER_BYTE * 3, + Osaka.gas_costs().OPCODE_EXP_BASE + + Osaka.gas_costs().OPCODE_EXP_PER_BYTE * 3, id="exp_three_bytes", ), pytest.param( Osaka, Op.EXP(exponent=0x1FFFFFF), # 3 bytes - Osaka.gas_costs().GAS_EXPONENTIATION - + Osaka.gas_costs().GAS_EXPONENTIATION_PER_BYTE * 4, + Osaka.gas_costs().OPCODE_EXP_BASE + + Osaka.gas_costs().OPCODE_EXP_PER_BYTE * 4, id="exp_three_bytes_plus_one_bit", ), # SHA3 tests pytest.param( Osaka, Op.SHA3(data_size=0), - Osaka.gas_costs().GAS_KECCAK256, + Osaka.gas_costs().OPCODE_KECCAK256_BASE, id="sha3_zero_data", ), pytest.param( Osaka, Op.SHA3(data_size=64, new_memory_size=96), - Osaka.gas_costs().GAS_KECCAK256 - + Osaka.gas_costs().GAS_KECCAK256_PER_WORD * 2 + Osaka.gas_costs().OPCODE_KECCAK256_BASE + + Osaka.gas_costs().OPCODE_KECCACK256_PER_WORD * 2 + Osaka.memory_expansion_gas_calculator()(new_bytes=96), id="sha3_with_data_and_memory", ), @@ -71,21 +71,21 @@ pytest.param( Osaka, Op.BALANCE(address_warm=False), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS, + Osaka.gas_costs().COLD_ACCOUNT_ACCESS, id="balance_cold_address", ), pytest.param( Osaka, Op.BALANCE(address_warm=True), - Osaka.gas_costs().GAS_WARM_ACCESS, + Osaka.gas_costs().WARM_ACCESS, id="balance_warm_address", ), # CALLDATACOPY tests pytest.param( Osaka, Op.CALLDATACOPY(data_size=32, new_memory_size=32), - Osaka.gas_costs().GAS_VERY_LOW - + Osaka.gas_costs().GAS_COPY * 1 + Osaka.gas_costs().VERY_LOW + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 1 + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="calldatacopy_one_word", ), @@ -94,8 +94,8 @@ Op.CALLDATACOPY( data_size=64, new_memory_size=64, old_memory_size=32 ), - Osaka.gas_costs().GAS_VERY_LOW - + Osaka.gas_costs().GAS_COPY * 2 + Osaka.gas_costs().VERY_LOW + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 2 + Osaka.memory_expansion_gas_calculator()( new_bytes=64, previous_bytes=32 ), @@ -105,8 +105,8 @@ pytest.param( Osaka, Op.CODECOPY(data_size=96, new_memory_size=96), - Osaka.gas_costs().GAS_VERY_LOW - + Osaka.gas_costs().GAS_COPY * 3 + Osaka.gas_costs().VERY_LOW + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 3 + Osaka.memory_expansion_gas_calculator()(new_bytes=96), id="codecopy_three_words", ), @@ -114,13 +114,13 @@ pytest.param( Osaka, Op.EXTCODESIZE(address_warm=False), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS, + Osaka.gas_costs().COLD_ACCOUNT_ACCESS, id="extcodesize_cold", ), pytest.param( Osaka, Op.EXTCODESIZE(address_warm=True), - Osaka.gas_costs().GAS_WARM_ACCESS, + Osaka.gas_costs().WARM_ACCESS, id="extcodesize_warm", ), # EXTCODECOPY tests @@ -129,8 +129,8 @@ Op.EXTCODECOPY( address_warm=True, data_size=32, new_memory_size=32 ), - Osaka.gas_costs().GAS_WARM_ACCESS - + Osaka.gas_costs().GAS_COPY * 1 + Osaka.gas_costs().WARM_ACCESS + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 1 + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="extcodecopy_warm", ), @@ -139,8 +139,8 @@ Op.EXTCODECOPY( address_warm=False, data_size=64, new_memory_size=64 ), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS - + Osaka.gas_costs().GAS_COPY * 2 + Osaka.gas_costs().COLD_ACCOUNT_ACCESS + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 2 + Osaka.memory_expansion_gas_calculator()(new_bytes=64), id="extcodecopy_cold", ), @@ -148,21 +148,21 @@ pytest.param( Osaka, Op.EXTCODEHASH(address_warm=False), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS, + Osaka.gas_costs().COLD_ACCOUNT_ACCESS, id="extcodehash_cold", ), pytest.param( Osaka, Op.EXTCODEHASH(address_warm=True), - Osaka.gas_costs().GAS_WARM_ACCESS, + Osaka.gas_costs().WARM_ACCESS, id="extcodehash_warm", ), # RETURNDATACOPY tests pytest.param( Osaka, Op.RETURNDATACOPY(data_size=32, new_memory_size=32), - Osaka.gas_costs().GAS_VERY_LOW - + Osaka.gas_costs().GAS_COPY * 1 + Osaka.gas_costs().VERY_LOW + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 1 + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="returndatacopy", ), @@ -170,7 +170,7 @@ pytest.param( Osaka, Op.MLOAD(new_memory_size=32), - Osaka.gas_costs().GAS_VERY_LOW + Osaka.gas_costs().VERY_LOW + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="mload_memory_expansion", ), @@ -178,7 +178,7 @@ pytest.param( Osaka, Op.MSTORE8(new_memory_size=1), - Osaka.gas_costs().GAS_VERY_LOW + Osaka.gas_costs().VERY_LOW + Osaka.memory_expansion_gas_calculator()(new_bytes=1), id="mstore8_memory_expansion", ), @@ -186,29 +186,29 @@ pytest.param( Osaka, Op.SLOAD(key_warm=False), - Osaka.gas_costs().GAS_COLD_STORAGE_ACCESS, + Osaka.gas_costs().COLD_STORAGE_ACCESS, id="sload_cold", ), pytest.param( Osaka, Op.SLOAD(key_warm=True), - Osaka.gas_costs().GAS_WARM_SLOAD, + Osaka.gas_costs().WARM_SLOAD, id="sload_warm", ), # MCOPY tests pytest.param( Osaka, Op.MCOPY(data_size=32, new_memory_size=32), - Osaka.gas_costs().GAS_VERY_LOW - + Osaka.gas_costs().GAS_COPY * 1 + Osaka.gas_costs().VERY_LOW + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 1 + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="mcopy_one_word", ), pytest.param( Osaka, Op.MCOPY(data_size=96, new_memory_size=128, old_memory_size=64), - Osaka.gas_costs().GAS_VERY_LOW - + Osaka.gas_costs().GAS_COPY * 3 + Osaka.gas_costs().VERY_LOW + + Osaka.gas_costs().OPCODE_COPY_PER_WORD * 3 + Osaka.memory_expansion_gas_calculator()( new_bytes=128, previous_bytes=64 ), @@ -218,8 +218,8 @@ pytest.param( Osaka, Op.LOG0(data_size=32, new_memory_size=32), - Osaka.gas_costs().GAS_LOG - + Osaka.gas_costs().GAS_LOG_DATA_PER_BYTE * 32 + Osaka.gas_costs().OPCODE_LOG_BASE + + Osaka.gas_costs().OPCODE_LOG_DATA_PER_BYTE * 32 + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="log0", ), @@ -227,9 +227,9 @@ pytest.param( Osaka, Op.LOG1(data_size=64, new_memory_size=64), - Osaka.gas_costs().GAS_LOG - + Osaka.gas_costs().GAS_LOG_DATA_PER_BYTE * 64 - + Osaka.gas_costs().GAS_LOG_TOPIC + Osaka.gas_costs().OPCODE_LOG_BASE + + Osaka.gas_costs().OPCODE_LOG_DATA_PER_BYTE * 64 + + Osaka.gas_costs().OPCODE_LOG_TOPIC + Osaka.memory_expansion_gas_calculator()(new_bytes=64), id="log1", ), @@ -237,9 +237,9 @@ pytest.param( Osaka, Op.LOG2(data_size=128, new_memory_size=128), - Osaka.gas_costs().GAS_LOG - + Osaka.gas_costs().GAS_LOG_DATA_PER_BYTE * 128 - + Osaka.gas_costs().GAS_LOG_TOPIC * 2 + Osaka.gas_costs().OPCODE_LOG_BASE + + Osaka.gas_costs().OPCODE_LOG_DATA_PER_BYTE * 128 + + Osaka.gas_costs().OPCODE_LOG_TOPIC * 2 + Osaka.memory_expansion_gas_calculator()(new_bytes=128), id="log2", ), @@ -247,9 +247,9 @@ pytest.param( Osaka, Op.LOG3(data_size=256, new_memory_size=256), - Osaka.gas_costs().GAS_LOG - + Osaka.gas_costs().GAS_LOG_DATA_PER_BYTE * 256 - + Osaka.gas_costs().GAS_LOG_TOPIC * 3 + Osaka.gas_costs().OPCODE_LOG_BASE + + Osaka.gas_costs().OPCODE_LOG_DATA_PER_BYTE * 256 + + Osaka.gas_costs().OPCODE_LOG_TOPIC * 3 + Osaka.memory_expansion_gas_calculator()(new_bytes=256), id="log3", ), @@ -257,9 +257,9 @@ pytest.param( Osaka, Op.LOG4(data_size=512, new_memory_size=512), - Osaka.gas_costs().GAS_LOG - + Osaka.gas_costs().GAS_LOG_DATA_PER_BYTE * 512 - + Osaka.gas_costs().GAS_LOG_TOPIC * 4 + Osaka.gas_costs().OPCODE_LOG_BASE + + Osaka.gas_costs().OPCODE_LOG_DATA_PER_BYTE * 512 + + Osaka.gas_costs().OPCODE_LOG_TOPIC * 4 + Osaka.memory_expansion_gas_calculator()(new_bytes=512), id="log4", ), @@ -267,9 +267,9 @@ pytest.param( Osaka, Op.CREATE(init_code_size=100, new_memory_size=100), - Osaka.gas_costs().GAS_CREATE + Osaka.gas_costs().OPCODE_CREATE_BASE # (100 + 31) // 32 = 4 - + Osaka.gas_costs().GAS_CODE_INIT_PER_WORD * 4 + + Osaka.gas_costs().CODE_INIT_PER_WORD * 4 + Osaka.memory_expansion_gas_calculator()(new_bytes=100), id="create_with_initcode", ), @@ -277,9 +277,9 @@ pytest.param( Osaka, Op.CREATE2(init_code_size=64, new_memory_size=64), - Osaka.gas_costs().GAS_CREATE - + Osaka.gas_costs().GAS_CODE_INIT_PER_WORD * 2 - + Osaka.gas_costs().GAS_KECCAK256_PER_WORD * 2 + Osaka.gas_costs().OPCODE_CREATE_BASE + + Osaka.gas_costs().CODE_INIT_PER_WORD * 2 + + Osaka.gas_costs().OPCODE_KECCACK256_PER_WORD * 2 + Osaka.memory_expansion_gas_calculator()(new_bytes=64), id="create2_with_initcode_and_hash", ), @@ -289,15 +289,15 @@ Op.CALL( address_warm=True, value_transfer=False, new_memory_size=64 ), - Osaka.gas_costs().GAS_WARM_ACCESS + Osaka.gas_costs().WARM_ACCESS + Osaka.memory_expansion_gas_calculator()(new_bytes=64), id="call_warm_no_value", ), pytest.param( Osaka, Op.CALL(address_warm=False, delegated_address=True), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS - + Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS, + Osaka.gas_costs().COLD_ACCOUNT_ACCESS + + Osaka.gas_costs().COLD_ACCOUNT_ACCESS, id="call_cold_delegated_address", ), pytest.param( @@ -307,22 +307,22 @@ delegated_address=True, delegated_address_warm=True, ), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS - + Osaka.gas_costs().GAS_WARM_ACCESS, + Osaka.gas_costs().COLD_ACCOUNT_ACCESS + + Osaka.gas_costs().WARM_ACCESS, id="call_warm_delegated_address", ), pytest.param( Osaka, Op.CALL(address_warm=False, value_transfer=True, account_new=True), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS - + Osaka.gas_costs().GAS_CALL_VALUE - + Osaka.gas_costs().GAS_NEW_ACCOUNT, + Osaka.gas_costs().COLD_ACCOUNT_ACCESS + + Osaka.gas_costs().CALL_VALUE + + Osaka.gas_costs().NEW_ACCOUNT, id="call_cold_account_new", ), pytest.param( Homestead, Op.CALL(address_warm=False, value_transfer=True, account_new=True), - Homestead.gas_costs().GAS_COLD_ACCOUNT_ACCESS, + Homestead.gas_costs().COLD_ACCOUNT_ACCESS, id="call_cold_account_new_homestead", ), pytest.param( @@ -333,8 +333,8 @@ account_new=False, new_memory_size=32, ), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS - + Osaka.gas_costs().GAS_CALL_VALUE + Osaka.gas_costs().COLD_ACCOUNT_ACCESS + + Osaka.gas_costs().CALL_VALUE + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="call_cold_with_value", ), @@ -346,9 +346,9 @@ account_new=True, new_memory_size=32, ), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS - + Osaka.gas_costs().GAS_CALL_VALUE - + Osaka.gas_costs().GAS_NEW_ACCOUNT + Osaka.gas_costs().COLD_ACCOUNT_ACCESS + + Osaka.gas_costs().CALL_VALUE + + Osaka.gas_costs().NEW_ACCOUNT + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="call_cold_new_account", ), @@ -358,7 +358,7 @@ Op.CALLCODE( address_warm=True, value_transfer=False, new_memory_size=32 ), - Osaka.gas_costs().GAS_WARM_ACCESS + Osaka.gas_costs().WARM_ACCESS + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="callcode_warm", ), @@ -366,14 +366,14 @@ pytest.param( Osaka, Op.DELEGATECALL(address_warm=True, new_memory_size=32), - Osaka.gas_costs().GAS_WARM_ACCESS + Osaka.gas_costs().WARM_ACCESS + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="delegatecall_warm", ), pytest.param( Osaka, Op.DELEGATECALL(address_warm=False, new_memory_size=64), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS + Osaka.gas_costs().COLD_ACCOUNT_ACCESS + Osaka.memory_expansion_gas_calculator()(new_bytes=64), id="delegatecall_cold", ), @@ -381,14 +381,14 @@ pytest.param( Osaka, Op.STATICCALL(address_warm=True, new_memory_size=32), - Osaka.gas_costs().GAS_WARM_ACCESS + Osaka.gas_costs().WARM_ACCESS + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="staticcall_warm", ), pytest.param( Osaka, Op.STATICCALL(address_warm=False, new_memory_size=0), - Osaka.gas_costs().GAS_COLD_ACCOUNT_ACCESS, + Osaka.gas_costs().COLD_ACCOUNT_ACCESS, id="staticcall_cold_no_memory", ), # RETURN tests @@ -401,7 +401,7 @@ pytest.param( Osaka, Op.RETURN(code_deposit_size=100, new_memory_size=32), - Osaka.gas_costs().GAS_CODE_DEPOSIT_PER_BYTE * 100 + Osaka.gas_costs().CODE_DEPOSIT_PER_BYTE * 100 + Osaka.memory_expansion_gas_calculator()(new_bytes=32), id="return_with_code_deposit", ), @@ -416,7 +416,7 @@ pytest.param( Osaka, Op.CLZ, - Osaka.gas_costs().GAS_LOW, + Osaka.gas_costs().LOW, id="clz_osaka", ), ], @@ -432,20 +432,19 @@ def test_opcode_gas_costs(fork: Fork, opcode: Op, expected_cost: int) -> None: pytest.param( Osaka, Op.ADD + Op.SUB, - Osaka.gas_costs().GAS_VERY_LOW * 2, + Osaka.gas_costs().VERY_LOW * 2, id="sum_of_opcodes", ), pytest.param( Osaka, Op.ADD(1, 1), - Osaka.gas_costs().GAS_VERY_LOW * 3, + Osaka.gas_costs().VERY_LOW * 3, id="opcode_with_args", ), pytest.param( Osaka, Op.SSTORE(1, 2, key_warm=True), - Osaka.gas_costs().GAS_STORAGE_SET - + Osaka.gas_costs().GAS_VERY_LOW * 2, + Osaka.gas_costs().STORAGE_SET + Osaka.gas_costs().VERY_LOW * 2, id="opcode_with_metadata", ), ], @@ -540,69 +539,69 @@ def test_bytecode_refunds( # noqa: D103 pytest.param( Osaka, Op.SSTORE(key_warm=True, original_value=0, new_value=0), - Osaka.gas_costs().GAS_WARM_SLOAD, + Osaka.gas_costs().WARM_SLOAD, id="sstore_noop_zero_warm", # 0 → 0 ), pytest.param( Osaka, Op.SSTORE(key_warm=False, original_value=0, new_value=0), - Osaka.gas_costs().GAS_COLD_STORAGE_ACCESS - + Osaka.gas_costs().GAS_WARM_SLOAD, + Osaka.gas_costs().COLD_STORAGE_ACCESS + + Osaka.gas_costs().WARM_SLOAD, id="sstore_noop_zero_cold", # 0 → 0 ), pytest.param( Osaka, Op.SSTORE(key_warm=True, original_value=5, new_value=5), - Osaka.gas_costs().GAS_WARM_SLOAD, + Osaka.gas_costs().WARM_SLOAD, id="sstore_noop_nonzero_warm", # 5 → 5 ), pytest.param( Osaka, Op.SSTORE(key_warm=False, original_value=5, new_value=5), - Osaka.gas_costs().GAS_COLD_STORAGE_ACCESS - + Osaka.gas_costs().GAS_WARM_SLOAD, + Osaka.gas_costs().COLD_STORAGE_ACCESS + + Osaka.gas_costs().WARM_SLOAD, id="sstore_noop_nonzero_cold", # 5 → 5 ), # Create storage: 0 → X (original == 0) pytest.param( Osaka, Op.SSTORE(key_warm=True, new_value=5), - Osaka.gas_costs().GAS_STORAGE_SET, + Osaka.gas_costs().STORAGE_SET, id="sstore_create_warm", # 0 → 5 ), pytest.param( Osaka, Op.SSTORE(key_warm=False, new_value=5), - Osaka.gas_costs().GAS_COLD_STORAGE_ACCESS - + Osaka.gas_costs().GAS_STORAGE_SET, + Osaka.gas_costs().COLD_STORAGE_ACCESS + + Osaka.gas_costs().STORAGE_SET, id="sstore_create_cold", # 0 → 5 ), # Modify storage: X → Y (original != 0, new != 0, new != original) pytest.param( Osaka, Op.SSTORE(key_warm=True, original_value=5, new_value=7), - Osaka.gas_costs().GAS_STORAGE_RESET, + Osaka.gas_costs().STORAGE_RESET, id="sstore_modify_warm", # 5 → 7 ), pytest.param( Osaka, Op.SSTORE(key_warm=False, original_value=5, new_value=7), - Osaka.gas_costs().GAS_COLD_STORAGE_ACCESS - + Osaka.gas_costs().GAS_STORAGE_RESET, + Osaka.gas_costs().COLD_STORAGE_ACCESS + + Osaka.gas_costs().STORAGE_RESET, id="sstore_modify_cold", # 5 → 7 ), # Clear storage: X → 0 (original != 0, new == 0) pytest.param( Osaka, Op.SSTORE(key_warm=True, original_value=5, new_value=0), - Osaka.gas_costs().GAS_STORAGE_RESET, + Osaka.gas_costs().STORAGE_RESET, id="sstore_clear_warm", # 5 → 0 ), pytest.param( Osaka, Op.SSTORE(key_warm=False, original_value=5, new_value=0), - Osaka.gas_costs().GAS_COLD_STORAGE_ACCESS - + Osaka.gas_costs().GAS_STORAGE_RESET, + Osaka.gas_costs().COLD_STORAGE_ACCESS + + Osaka.gas_costs().STORAGE_RESET, id="sstore_clear_cold", # 5 → 0 ), ], diff --git a/packages/testing/src/execution_testing/tools/utility/generators.py b/packages/testing/src/execution_testing/tools/utility/generators.py index f2e725e1dc9..78a9f172c51 100644 --- a/packages/testing/src/execution_testing/tools/utility/generators.py +++ b/packages/testing/src/execution_testing/tools/utility/generators.py @@ -358,9 +358,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.GAS_STORAGE_SET - + gas_costs.GAS_COLD_STORAGE_ACCESS - + (gas_costs.GAS_VERY_LOW * 2) + gas_costs.STORAGE_SET + + gas_costs.COLD_STORAGE_ACCESS + + (gas_costs.VERY_LOW * 2) ) modified_system_contract_code += sum( Op.SSTORE(i, 1) @@ -369,9 +369,9 @@ 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.GAS_JUMPDEST == 1, ( + assert gas_costs.OPCODE_JUMPDEST == 1, ( "JUMPDEST gas cost should be 1, but got " - f"{gas_costs.GAS_JUMPDEST}. Generator " + f"{gas_costs.OPCODE_JUMPDEST}. Generator " "`generate_system_contract_error_test` needs updating." ) modified_system_contract_code += sum( @@ -506,13 +506,13 @@ def gas_test( # 2 times GAS, POP, CALL, 6 times PUSH1 - instructions charged for at every # gas run gas_costs = fork.gas_costs() - opcode_gas_cost = gas_costs.GAS_BASE - opcode_pop_cost = gas_costs.GAS_BASE - opcode_push_cost = gas_costs.GAS_VERY_LOW + opcode_gas_cost = gas_costs.BASE + opcode_pop_cost = gas_costs.BASE + opcode_push_cost = gas_costs.VERY_LOW gas_single_gas_run = ( 2 * opcode_gas_cost + opcode_pop_cost - + gas_costs.GAS_WARM_ACCESS + + gas_costs.WARM_ACCESS + 6 * opcode_push_cost ) address_legacy_harness = pre.deploy_contract( diff --git a/src/ethereum/forks/amsterdam/block_access_lists.py b/src/ethereum/forks/amsterdam/block_access_lists.py index c6bcf176886..261b992e503 100644 --- a/src/ethereum/forks/amsterdam/block_access_lists.py +++ b/src/ethereum/forks/amsterdam/block_access_lists.py @@ -744,7 +744,7 @@ def validate_block_access_list_gas_limit( The total number of items (addresses + unique storage keys) must not exceed ``block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM``. """ - from .vm.gas import GAS_BLOCK_ACCESS_LIST_ITEM + from .vm.gas import GasCosts bal_items = Uint(0) for account in block_access_list: @@ -762,9 +762,9 @@ def validate_block_access_list_gas_limit( # Count each unique storage key as one item bal_items += Uint(len(unique_slots)) - if bal_items > block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM: + if bal_items > block_gas_limit // GasCosts.BLOCK_ACCESS_LIST_ITEM: raise BlockAccessListGasLimitExceededError( f"Block access list exceeds gas limit, {bal_items} items " f"exceeds limit of " - f"{block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM}." + f"{block_gas_limit // GasCosts.BLOCK_ACCESS_LIST_ITEM}." ) diff --git a/src/ethereum/forks/amsterdam/fork.py b/src/ethereum/forks/amsterdam/fork.py index c5dbc499c23..e673bc3d8fd 100644 --- a/src/ethereum/forks/amsterdam/fork.py +++ b/src/ethereum/forks/amsterdam/fork.py @@ -95,8 +95,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( - BLOB_SCHEDULE_MAX, - GAS_PER_BLOB, + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -106,15 +105,13 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB +MAX_BLOB_GAS_PER_BLOCK = GasCosts.BLOB_SCHEDULE_MAX * GasCosts.PER_BLOB VERSIONED_HASH_VERSION_KZG = b"\x01" GWEI_TO_WEI = U256(10**9) @@ -1122,14 +1119,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1145,12 +1142,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/amsterdam/transactions.py b/src/ethereum/forks/amsterdam/transactions.py index da7dfd13f5e..f88d5b551f8 100644 --- a/src/ethereum/forks/amsterdam/transactions.py +++ b/src/ethereum/forks/amsterdam/transactions.py @@ -28,43 +28,6 @@ ) from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - TX_MAX_GAS_LIMIT = Uint(16_777_216) @@ -608,7 +571,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -619,8 +582,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -628,31 +590,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/amsterdam/vm/eoa_delegation.py b/src/ethereum/forks/amsterdam/vm/eoa_delegation.py index 602afef3c1f..6262f42a0bc 100644 --- a/src/ethereum/forks/amsterdam/vm/eoa_delegation.py +++ b/src/ethereum/forks/amsterdam/vm/eoa_delegation.py @@ -21,14 +21,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -149,9 +148,9 @@ def calculate_delegation_cost( delegated_address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if delegated_address in evm.accessed_addresses: - delegation_gas_cost = GAS_WARM_ACCESS + delegation_gas_cost = GasCosts.WARM_ACCESS else: - delegation_gas_cost = GAS_COLD_ACCOUNT_ACCESS + delegation_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS return True, delegated_address, delegation_gas_cost @@ -199,7 +198,8 @@ def set_delegation(message: Message) -> U256: if account_exists(tx_state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/amsterdam/vm/gas.py b/src/ethereum/forks/amsterdam/vm/gas.py index 6807cba420b..b5ef8974d3e 100644 --- a/src/ethereum/forks/amsterdam/vm/gas.py +++ b/src/ethereum/forks/amsterdam/vm/gas.py @@ -25,67 +25,172 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_P256VERIFY = Uint(6900) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(14) -BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET -BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(21) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) - -GAS_BLOCK_ACCESS_LIST_ITEM = Uint(2000) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_P256VERIFY = Uint(6900) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_SCHEDULE_TARGET = U64(14) + BLOB_TARGET_GAS_PER_BLOCK = PER_BLOB * BLOB_SCHEDULE_TARGET + BLOB_BASE_COST = Uint(2**13) + BLOB_SCHEDULE_MAX = U64(21) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) + + # Block Access Lists + BLOCK_ACCESS_LIST_ITEM = Uint(2000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_CLZ = LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcode Components + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -106,8 +211,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -176,7 +281,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -231,7 +336,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -303,7 +408,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas( @@ -336,21 +441,23 @@ def calculate_excess_blob_gas( base_fee_per_gas = parent_header.base_fee_per_gas parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - target_blob_gas_price = Uint(GAS_PER_BLOB) + target_blob_gas_price = Uint(GasCosts.PER_BLOB) target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) - base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas + base_blob_tx_price = GasCosts.BLOB_BASE_COST * base_fee_per_gas if base_blob_tx_price > target_blob_gas_price: - blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET + blob_schedule_delta = ( + GasCosts.BLOB_SCHEDULE_MAX - GasCosts.BLOB_SCHEDULE_TARGET + ) return ( excess_blob_gas - + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX + + blob_gas_used * blob_schedule_delta // GasCosts.BLOB_SCHEDULE_MAX ) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -369,7 +476,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -390,9 +497,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/amsterdam/vm/instructions/arithmetic.py b/src/ethereum/forks/amsterdam/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/amsterdam/vm/instructions/bitwise.py b/src/ethereum/forks/amsterdam/vm/instructions/bitwise.py index cc6fa2fbb23..7674d3c720f 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/bitwise.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: @@ -262,7 +265,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_CLZ) # OPERATION bit_length = U256(x.bit_length()) diff --git a/src/ethereum/forks/amsterdam/vm/instructions/block.py b/src/ethereum/forks/amsterdam/vm/instructions/block.py index e563a2e96e8..8c93840b384 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/block.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/amsterdam/vm/instructions/comparison.py b/src/ethereum/forks/amsterdam/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/comparison.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/amsterdam/vm/instructions/control_flow.py b/src/ethereum/forks/amsterdam/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/control_flow.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/amsterdam/vm/instructions/environment.py b/src/ethereum/forks/amsterdam/vm/instructions/environment.py index f5f89bdfa59..431cd3ba4c6 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/environment.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -75,12 +68,11 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - is_cold_access = address not in evm.accessed_addresses - gas_cost = GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS - if is_cold_access: + if address in evm.accessed_addresses: + charge_gas(evm, GasCosts.WARM_ACCESS) + else: evm.accessed_addresses.add(address) - - charge_gas(evm, gas_cost) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -108,7 +100,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -131,7 +123,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -154,7 +146,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -178,7 +170,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -203,7 +195,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -232,11 +224,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -261,7 +256,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -290,11 +285,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -319,7 +317,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -342,14 +340,11 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - is_cold_access = address not in evm.accessed_addresses - access_gas_cost = ( - GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS - ) - if is_cold_access: + if address in evm.accessed_addresses: + charge_gas(evm, GasCosts.WARM_ACCESS) + else: evm.accessed_addresses.add(address) - - charge_gas(evm, access_gas_cost) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION tx_state = evm.message.tx_env.state @@ -381,19 +376,18 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - is_cold_access = address not in evm.accessed_addresses - access_gas_cost = ( - GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS - ) - total_gas_cost = access_gas_cost + copy_gas_cost + extend_memory.cost - - if is_cold_access: + if address in evm.accessed_addresses: + access_gas_cost = GasCosts.WARM_ACCESS + else: evm.accessed_addresses.add(address) + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS + + total_gas_cost = access_gas_cost + copy_gas_cost + extend_memory.cost charge_gas(evm, total_gas_cost) @@ -424,7 +418,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -450,11 +444,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -482,12 +481,11 @@ def extcodehash(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - is_cold_access = address not in evm.accessed_addresses - access_gas_cost = ( - GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS - ) - if is_cold_access: + if address in evm.accessed_addresses: + access_gas_cost = GasCosts.WARM_ACCESS + else: evm.accessed_addresses.add(address) + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -520,7 +518,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -548,7 +546,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -571,7 +569,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -598,7 +596,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/amsterdam/vm/instructions/keccak.py b/src/ethereum/forks/amsterdam/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/keccak.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/amsterdam/vm/instructions/log.py b/src/ethereum/forks/amsterdam/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/log.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/amsterdam/vm/instructions/memory.py b/src/ethereum/forks/amsterdam/vm/instructions/memory.py index 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/memory.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/amsterdam/vm/instructions/stack.py b/src/ethereum/forks/amsterdam/vm/instructions/stack.py index 0007a28acd4..366cf79f5e4 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/stack.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -63,9 +66,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +98,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +130,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/amsterdam/vm/instructions/storage.py b/src/ethereum/forks/amsterdam/vm/instructions/storage.py index 176b0d9a1c8..56e1ed28d06 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/storage.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/storage.py @@ -23,12 +23,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, check_gas, ) @@ -51,10 +46,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION tx_state = evm.message.tx_env.state @@ -84,7 +79,7 @@ def sstore(evm: Evm) -> None: new_value = pop(evm.stack) # check we have at least the stipend gas - check_gas(evm, GAS_CALL_STIPEND + Uint(1)) + check_gas(evm, GasCosts.CALL_STIPEND + Uint(1)) tx_state = evm.message.tx_env.state original_value = get_storage_original( @@ -96,37 +91,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -151,7 +150,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -181,7 +180,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) set_transient_storage( evm.message.tx_env.state, evm.message.current_target, diff --git a/src/ethereum/forks/amsterdam/vm/instructions/system.py b/src/ethereum/forks/amsterdam/vm/instructions/system.py index 1660394e56d..42a4643f9c0 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/system.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/system.py @@ -43,15 +43,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -174,7 +166,9 @@ 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, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -224,8 +218,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -269,7 +263,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -387,11 +381,11 @@ def call(evm: Evm) -> None: is_cold_access = to not in evm.accessed_addresses if is_cold_access: - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS else: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE # check static gas before state access check_gas( @@ -404,7 +398,7 @@ def call(evm: Evm) -> None: if is_cold_access: evm.accessed_addresses.add(to) - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(tx_state, to): create_gas_cost = Uint(0) @@ -494,11 +488,11 @@ def callcode(evm: Evm) -> None: is_cold_access = code_address not in evm.accessed_addresses if is_cold_access: - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS else: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE # check static gas before state access check_gas( @@ -584,11 +578,11 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE is_cold_access = beneficiary not in evm.accessed_addresses if is_cold_access: - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS # check access gas cost before state access check_gas(evm, gas_cost) @@ -602,7 +596,7 @@ def selfdestruct(evm: Evm) -> None: not is_account_alive(tx_state, beneficiary) and get_account(tx_state, evm.message.current_target).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) @@ -656,9 +650,9 @@ def delegatecall(evm: Evm) -> None: is_cold_access = code_address not in evm.accessed_addresses if is_cold_access: - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS else: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS # check static gas before state access check_gas(evm, access_gas_cost + extend_memory.cost) @@ -746,9 +740,9 @@ def staticcall(evm: Evm) -> None: is_cold_access = to not in evm.accessed_addresses if is_cold_access: - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS else: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS # check static gas before state access check_gas(evm, access_gas_cost + extend_memory.cost) diff --git a/src/ethereum/forks/amsterdam/vm/interpreter.py b/src/ethereum/forks/amsterdam/vm/interpreter.py index c22f9eef143..80b30bd7ab2 100644 --- a/src/ethereum/forks/amsterdam/vm/interpreter.py +++ b/src/ethereum/forks/amsterdam/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -201,7 +201,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..fa0d3ec4c2d 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -60,7 +58,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1ADD)) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +99,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +138,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1MAP)) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..a5b2be04018 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -61,7 +59,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2ADD)) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +100,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +139,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2MAP)) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/identity.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/p256verify.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/p256verify.py index e35ea1bb4ec..29c2e91e0f0 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/p256verify.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/p256verify.py @@ -24,7 +24,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_P256VERIFY, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -41,7 +41,7 @@ def p256verify(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_P256VERIFY) + charge_gas(evm, GasCosts.PRECOMPILE_P256VERIFY) if len(data) != 160: return diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/amsterdam/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/amsterdam/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/arrow_glacier/fork.py b/src/ethereum/forks/arrow_glacier/fork.py index f833fe71c5f..30ca8c9139a 100644 --- a/src/ethereum/forks/arrow_glacier/fork.py +++ b/src/ethereum/forks/arrow_glacier/fork.py @@ -61,13 +61,12 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(2 * 10**18) BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) BOMB_DELAY_BLOCKS = 10700000 @@ -849,14 +848,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -872,12 +871,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/arrow_glacier/transactions.py b/src/ethereum/forks/arrow_glacier/transactions.py index ca951f085c2..0e40010c617 100644 --- a/src/ethereum/forks/arrow_glacier/transactions.py +++ b/src/ethereum/forks/arrow_glacier/transactions.py @@ -23,37 +23,6 @@ from .exceptions import TransactionTypeError from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -370,7 +339,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -378,27 +347,29 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) access_list_cost = Uint(0) if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) - return GAS_TX_BASE + data_cost + create_cost + access_list_cost + return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/arrow_glacier/vm/gas.py b/src/ethereum/forks/arrow_glacier/vm/gas.py index 7ac4146d8cf..c33cf7c0487 100644 --- a/src/ethereum/forks/arrow_glacier/vm/gas.py +++ b/src/ethereum/forks/arrow_glacier/vm/gas.py @@ -22,46 +22,143 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -82,8 +179,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -135,7 +232,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -190,7 +287,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/arithmetic.py b/src/ethereum/forks/arrow_glacier/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/bitwise.py b/src/ethereum/forks/arrow_glacier/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/bitwise.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/block.py b/src/ethereum/forks/arrow_glacier/vm/instructions/block.py index bbf01739ff2..e3400f9461a 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/block.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -203,7 +203,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/comparison.py b/src/ethereum/forks/arrow_glacier/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/comparison.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/control_flow.py b/src/ethereum/forks/arrow_glacier/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/control_flow.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/environment.py b/src/ethereum/forks/arrow_glacier/vm/instructions/environment.py index fe1b70c1269..851ab39b142 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/environment.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/environment.py @@ -22,13 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,10 +67,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -103,7 +97,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -126,7 +120,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -149,7 +143,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -173,7 +167,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -198,7 +192,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -227,11 +221,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -256,7 +253,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -285,11 +282,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -314,7 +314,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -338,10 +338,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -374,16 +374,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -413,7 +413,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -439,11 +439,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -472,10 +477,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -507,7 +512,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -535,7 +540,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/keccak.py b/src/ethereum/forks/arrow_glacier/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/keccak.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/log.py b/src/ethereum/forks/arrow_glacier/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/log.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/memory.py b/src/ethereum/forks/arrow_glacier/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/memory.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/stack.py b/src/ethereum/forks/arrow_glacier/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/stack.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/storage.py b/src/ethereum/forks/arrow_glacier/vm/instructions/storage.py index d99ad70f93b..287544f353b 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/storage.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/storage.py @@ -17,12 +17,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,10 +39,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -73,7 +68,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -86,37 +81,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/arrow_glacier/vm/instructions/system.py b/src/ethereum/forks/arrow_glacier/vm/instructions/system.py index b48d2498ac3..0282da0d90e 100644 --- a/src/ethereum/forks/arrow_glacier/vm/instructions/system.py +++ b/src/ethereum/forks/arrow_glacier/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -157,7 +149,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -202,8 +194,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -242,7 +234,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -353,17 +345,17 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -433,12 +425,12 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -491,10 +483,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -503,7 +495,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -570,13 +562,17 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -629,10 +625,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to diff --git a/src/ethereum/forks/arrow_glacier/vm/interpreter.py b/src/ethereum/forks/arrow_glacier/vm/interpreter.py index 20d8c31f1e3..f2262c47175 100644 --- a/src/ethereum/forks/arrow_glacier/vm/interpreter.py +++ b/src/ethereum/forks/arrow_glacier/vm/interpreter.py @@ -45,7 +45,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -179,7 +179,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..9d8c71b806d 100644 --- a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,10 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas( + evm, + GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds, + ) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/identity.py b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/arrow_glacier/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/berlin/fork.py b/src/ethereum/forks/berlin/fork.py index 54bc85a6aa6..72d37ec2bae 100644 --- a/src/ethereum/forks/berlin/fork.py +++ b/src/ethereum/forks/berlin/fork.py @@ -56,11 +56,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(2 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) BOMB_DELAY_BLOCKS = 9000000 @@ -734,14 +733,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -757,12 +756,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/berlin/transactions.py b/src/ethereum/forks/berlin/transactions.py index 10a9e22a2c0..2721c25520c 100644 --- a/src/ethereum/forks/berlin/transactions.py +++ b/src/ethereum/forks/berlin/transactions.py @@ -23,37 +23,6 @@ from .exceptions import TransactionTypeError from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -287,7 +256,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -295,27 +264,29 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) access_list_cost = Uint(0) if isinstance(tx, AccessListTransaction): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) - return GAS_TX_BASE + data_cost + create_cost + access_list_cost + return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/berlin/vm/gas.py b/src/ethereum/forks/berlin/vm/gas.py index 80441f0e4fd..1ffb7025f2a 100644 --- a/src/ethereum/forks/berlin/vm/gas.py +++ b/src/ethereum/forks/berlin/vm/gas.py @@ -22,47 +22,143 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -REFUND_SELF_DESTRUCT = 24000 -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = 24000 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -83,8 +179,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -136,7 +232,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -191,7 +287,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/berlin/vm/instructions/arithmetic.py b/src/ethereum/forks/berlin/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/berlin/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/berlin/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/berlin/vm/instructions/bitwise.py b/src/ethereum/forks/berlin/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/berlin/vm/instructions/bitwise.py +++ b/src/ethereum/forks/berlin/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/berlin/vm/instructions/block.py b/src/ethereum/forks/berlin/vm/instructions/block.py index bbf01739ff2..e3400f9461a 100644 --- a/src/ethereum/forks/berlin/vm/instructions/block.py +++ b/src/ethereum/forks/berlin/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -203,7 +203,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/berlin/vm/instructions/comparison.py b/src/ethereum/forks/berlin/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/berlin/vm/instructions/comparison.py +++ b/src/ethereum/forks/berlin/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/berlin/vm/instructions/control_flow.py b/src/ethereum/forks/berlin/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/berlin/vm/instructions/control_flow.py +++ b/src/ethereum/forks/berlin/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/berlin/vm/instructions/environment.py b/src/ethereum/forks/berlin/vm/instructions/environment.py index 63733aca3d5..9e7b817ace6 100644 --- a/src/ethereum/forks/berlin/vm/instructions/environment.py +++ b/src/ethereum/forks/berlin/vm/instructions/environment.py @@ -22,13 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,10 +67,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -103,7 +97,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -126,7 +120,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -149,7 +143,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -173,7 +167,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -198,7 +192,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -227,11 +221,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -256,7 +253,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -285,11 +282,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -314,7 +314,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -338,10 +338,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -374,16 +374,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -413,7 +413,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -439,11 +439,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -472,10 +477,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -507,7 +512,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. diff --git a/src/ethereum/forks/berlin/vm/instructions/keccak.py b/src/ethereum/forks/berlin/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/berlin/vm/instructions/keccak.py +++ b/src/ethereum/forks/berlin/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/berlin/vm/instructions/log.py b/src/ethereum/forks/berlin/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/berlin/vm/instructions/log.py +++ b/src/ethereum/forks/berlin/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/berlin/vm/instructions/memory.py b/src/ethereum/forks/berlin/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/berlin/vm/instructions/memory.py +++ b/src/ethereum/forks/berlin/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/berlin/vm/instructions/stack.py b/src/ethereum/forks/berlin/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/berlin/vm/instructions/stack.py +++ b/src/ethereum/forks/berlin/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/berlin/vm/instructions/storage.py b/src/ethereum/forks/berlin/vm/instructions/storage.py index d99ad70f93b..287544f353b 100644 --- a/src/ethereum/forks/berlin/vm/instructions/storage.py +++ b/src/ethereum/forks/berlin/vm/instructions/storage.py @@ -17,12 +17,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,10 +39,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -73,7 +68,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -86,37 +81,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/berlin/vm/instructions/system.py b/src/ethereum/forks/berlin/vm/instructions/system.py index 4320315d945..4c0e63d6dbe 100644 --- a/src/ethereum/forks/berlin/vm/instructions/system.py +++ b/src/ethereum/forks/berlin/vm/instructions/system.py @@ -40,16 +40,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -158,7 +149,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -203,8 +194,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -243,7 +234,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -354,17 +345,17 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -434,12 +425,12 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -492,10 +483,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -504,7 +495,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT originator = evm.message.current_target @@ -515,7 +506,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += REFUND_SELF_DESTRUCT + evm.refund_counter += GasCosts.REFUND_SELF_DESTRUCT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -582,10 +573,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS message_call_gas = calculate_message_call_gas( U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost @@ -641,10 +632,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to diff --git a/src/ethereum/forks/berlin/vm/interpreter.py b/src/ethereum/forks/berlin/vm/interpreter.py index 6edd4cae8ca..1f482d07cea 100644 --- a/src/ethereum/forks/berlin/vm/interpreter.py +++ b/src/ethereum/forks/berlin/vm/interpreter.py @@ -45,7 +45,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -178,7 +178,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/berlin/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/berlin/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/berlin/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/berlin/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/berlin/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/berlin/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/berlin/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/berlin/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/berlin/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/berlin/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/berlin/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/berlin/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/berlin/vm/precompiled_contracts/identity.py b/src/ethereum/forks/berlin/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/berlin/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/berlin/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/berlin/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/berlin/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/berlin/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/berlin/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/berlin/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/berlin/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/berlin/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/berlin/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo1/fork.py b/src/ethereum/forks/bpo1/fork.py index 7e6b5ee46de..19ce50f243d 100644 --- a/src/ethereum/forks/bpo1/fork.py +++ b/src/ethereum/forks/bpo1/fork.py @@ -81,8 +81,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( - BLOB_SCHEDULE_MAX, - GAS_PER_BLOB, + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -92,15 +91,13 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB +MAX_BLOB_GAS_PER_BLOCK = GasCosts.BLOB_SCHEDULE_MAX * GasCosts.PER_BLOB VERSIONED_HASH_VERSION_KZG = b"\x01" WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address( @@ -1030,14 +1027,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1053,12 +1050,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/bpo1/transactions.py b/src/ethereum/forks/bpo1/transactions.py index c8f1826324e..486b21f99b0 100644 --- a/src/ethereum/forks/bpo1/transactions.py +++ b/src/ethereum/forks/bpo1/transactions.py @@ -28,43 +28,6 @@ ) from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - TX_MAX_GAS_LIMIT = Uint(16_777_216) @@ -601,7 +564,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -612,8 +575,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -621,31 +583,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/bpo1/vm/eoa_delegation.py b/src/ethereum/forks/bpo1/vm/eoa_delegation.py index fce580bee4a..3fd42910817 100644 --- a/src/ethereum/forks/bpo1/vm/eoa_delegation.py +++ b/src/ethereum/forks/bpo1/vm/eoa_delegation.py @@ -22,14 +22,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -147,10 +146,10 @@ def access_delegation( address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code = get_code(state, get_account(state, address).code_hash) return True, address, code, access_gas_cost @@ -199,7 +198,8 @@ def set_delegation(message: Message) -> U256: if account_exists(state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/bpo1/vm/gas.py b/src/ethereum/forks/bpo1/vm/gas.py index 51b439cd0a0..232bbdd4f23 100644 --- a/src/ethereum/forks/bpo1/vm/gas.py +++ b/src/ethereum/forks/bpo1/vm/gas.py @@ -24,65 +24,169 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_P256VERIFY = Uint(6900) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(10) -BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET -BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(15) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(8346193) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_P256VERIFY = Uint(6900) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_SCHEDULE_TARGET = U64(10) + BLOB_TARGET_GAS_PER_BLOCK = PER_BLOB * BLOB_SCHEDULE_TARGET + BLOB_BASE_COST = Uint(2**13) + BLOB_SCHEDULE_MAX = U64(15) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(8346193) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_CLZ = LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -103,8 +207,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -156,7 +260,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -211,7 +315,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -283,7 +387,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -314,21 +418,23 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: base_fee_per_gas = parent_header.base_fee_per_gas parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - target_blob_gas_price = Uint(GAS_PER_BLOB) + target_blob_gas_price = Uint(GasCosts.PER_BLOB) target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) - base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas + base_blob_tx_price = GasCosts.BLOB_BASE_COST * base_fee_per_gas if base_blob_tx_price > target_blob_gas_price: - blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET + blob_schedule_delta = ( + GasCosts.BLOB_SCHEDULE_MAX - GasCosts.BLOB_SCHEDULE_TARGET + ) return ( excess_blob_gas - + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX + + blob_gas_used * blob_schedule_delta // GasCosts.BLOB_SCHEDULE_MAX ) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -347,7 +453,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -368,9 +474,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/bpo1/vm/instructions/arithmetic.py b/src/ethereum/forks/bpo1/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/bpo1/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/bpo1/vm/instructions/bitwise.py b/src/ethereum/forks/bpo1/vm/instructions/bitwise.py index cc6fa2fbb23..7674d3c720f 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/bitwise.py +++ b/src/ethereum/forks/bpo1/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: @@ -262,7 +265,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_CLZ) # OPERATION bit_length = U256(x.bit_length()) diff --git a/src/ethereum/forks/bpo1/vm/instructions/block.py b/src/ethereum/forks/bpo1/vm/instructions/block.py index 75810aacd39..7e32893722b 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/block.py +++ b/src/ethereum/forks/bpo1/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/bpo1/vm/instructions/comparison.py b/src/ethereum/forks/bpo1/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/comparison.py +++ b/src/ethereum/forks/bpo1/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/bpo1/vm/instructions/control_flow.py b/src/ethereum/forks/bpo1/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/control_flow.py +++ b/src/ethereum/forks/bpo1/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/bpo1/vm/instructions/environment.py b/src/ethereum/forks/bpo1/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/environment.py +++ b/src/ethereum/forks/bpo1/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/bpo1/vm/instructions/keccak.py b/src/ethereum/forks/bpo1/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/keccak.py +++ b/src/ethereum/forks/bpo1/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo1/vm/instructions/log.py b/src/ethereum/forks/bpo1/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/log.py +++ b/src/ethereum/forks/bpo1/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/bpo1/vm/instructions/memory.py b/src/ethereum/forks/bpo1/vm/instructions/memory.py index 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/memory.py +++ b/src/ethereum/forks/bpo1/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo1/vm/instructions/stack.py b/src/ethereum/forks/bpo1/vm/instructions/stack.py index 0007a28acd4..366cf79f5e4 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/stack.py +++ b/src/ethereum/forks/bpo1/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -63,9 +66,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +98,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +130,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/bpo1/vm/instructions/storage.py b/src/ethereum/forks/bpo1/vm/instructions/storage.py index fd5bf4572ff..5aa3cc6746f 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/storage.py +++ b/src/ethereum/forks/bpo1/vm/instructions/storage.py @@ -23,12 +23,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -50,10 +45,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +74,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +87,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +148,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +175,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/bpo1/vm/instructions/system.py b/src/ethereum/forks/bpo1/vm/instructions/system.py index 29c3fe9e6e2..1fe8daf44d5 100644 --- a/src/ethereum/forks/bpo1/vm/instructions/system.py +++ b/src/ethereum/forks/bpo1/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +158,10 @@ 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, + GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,8 +211,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -261,7 +256,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -374,10 +369,10 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( @@ -388,10 +383,10 @@ def call(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -463,10 +458,10 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -476,7 +471,7 @@ def callcode(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -531,10 +526,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -543,7 +538,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -604,10 +599,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -673,10 +668,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( diff --git a/src/ethereum/forks/bpo1/vm/interpreter.py b/src/ethereum/forks/bpo1/vm/interpreter.py index 9c05883b7dc..b79580a6429 100644 --- a/src/ethereum/forks/bpo1/vm/interpreter.py +++ b/src/ethereum/forks/bpo1/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -191,7 +191,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..d1f63224a0c 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -60,7 +58,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, GasCosts.PRECOMPILE_BLS_G1ADD) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +99,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +138,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, GasCosts.PRECOMPILE_BLS_G1MAP) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..2fd32313f89 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -61,7 +59,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, GasCosts.PRECOMPILE_BLS_G2ADD) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +100,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +139,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, GasCosts.PRECOMPILE_BLS_G2MAP) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/identity.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/p256verify.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/p256verify.py index e35ea1bb4ec..29c2e91e0f0 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/p256verify.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/p256verify.py @@ -24,7 +24,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_P256VERIFY, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -41,7 +41,7 @@ def p256verify(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_P256VERIFY) + charge_gas(evm, GasCosts.PRECOMPILE_P256VERIFY) if len(data) != 160: return diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo1/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/bpo1/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/bpo1/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/bpo1/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo2/fork.py b/src/ethereum/forks/bpo2/fork.py index 7e6b5ee46de..19ce50f243d 100644 --- a/src/ethereum/forks/bpo2/fork.py +++ b/src/ethereum/forks/bpo2/fork.py @@ -81,8 +81,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( - BLOB_SCHEDULE_MAX, - GAS_PER_BLOB, + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -92,15 +91,13 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB +MAX_BLOB_GAS_PER_BLOCK = GasCosts.BLOB_SCHEDULE_MAX * GasCosts.PER_BLOB VERSIONED_HASH_VERSION_KZG = b"\x01" WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address( @@ -1030,14 +1027,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1053,12 +1050,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/bpo2/transactions.py b/src/ethereum/forks/bpo2/transactions.py index c8f1826324e..486b21f99b0 100644 --- a/src/ethereum/forks/bpo2/transactions.py +++ b/src/ethereum/forks/bpo2/transactions.py @@ -28,43 +28,6 @@ ) from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - TX_MAX_GAS_LIMIT = Uint(16_777_216) @@ -601,7 +564,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -612,8 +575,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -621,31 +583,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/bpo2/vm/eoa_delegation.py b/src/ethereum/forks/bpo2/vm/eoa_delegation.py index fce580bee4a..3fd42910817 100644 --- a/src/ethereum/forks/bpo2/vm/eoa_delegation.py +++ b/src/ethereum/forks/bpo2/vm/eoa_delegation.py @@ -22,14 +22,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -147,10 +146,10 @@ def access_delegation( address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code = get_code(state, get_account(state, address).code_hash) return True, address, code, access_gas_cost @@ -199,7 +198,8 @@ def set_delegation(message: Message) -> U256: if account_exists(state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/bpo2/vm/gas.py b/src/ethereum/forks/bpo2/vm/gas.py index 5c30cd6a340..50edd7d5d7a 100644 --- a/src/ethereum/forks/bpo2/vm/gas.py +++ b/src/ethereum/forks/bpo2/vm/gas.py @@ -24,65 +24,169 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_P256VERIFY = Uint(6900) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(14) -BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET -BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(21) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_P256VERIFY = Uint(6900) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_SCHEDULE_TARGET = U64(14) + BLOB_TARGET_GAS_PER_BLOCK = PER_BLOB * BLOB_SCHEDULE_TARGET + BLOB_BASE_COST = Uint(2**13) + BLOB_SCHEDULE_MAX = U64(21) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_CLZ = LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -103,8 +207,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -156,7 +260,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -211,7 +315,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -283,7 +387,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -314,21 +418,23 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: base_fee_per_gas = parent_header.base_fee_per_gas parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - target_blob_gas_price = Uint(GAS_PER_BLOB) + target_blob_gas_price = Uint(GasCosts.PER_BLOB) target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) - base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas + base_blob_tx_price = GasCosts.BLOB_BASE_COST * base_fee_per_gas if base_blob_tx_price > target_blob_gas_price: - blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET + blob_schedule_delta = ( + GasCosts.BLOB_SCHEDULE_MAX - GasCosts.BLOB_SCHEDULE_TARGET + ) return ( excess_blob_gas - + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX + + blob_gas_used * blob_schedule_delta // GasCosts.BLOB_SCHEDULE_MAX ) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -347,7 +453,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -368,9 +474,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/bpo2/vm/instructions/arithmetic.py b/src/ethereum/forks/bpo2/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/bpo2/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/bpo2/vm/instructions/bitwise.py b/src/ethereum/forks/bpo2/vm/instructions/bitwise.py index cc6fa2fbb23..8b41a55d2b2 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/bitwise.py +++ b/src/ethereum/forks/bpo2/vm/instructions/bitwise.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -34,7 +34,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +59,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +84,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +108,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +134,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +169,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +199,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +229,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: @@ -262,7 +262,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_CLZ) # OPERATION bit_length = U256(x.bit_length()) diff --git a/src/ethereum/forks/bpo2/vm/instructions/block.py b/src/ethereum/forks/bpo2/vm/instructions/block.py index 9923433c7b6..76ab809b06b 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/block.py +++ b/src/ethereum/forks/bpo2/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/bpo2/vm/instructions/comparison.py b/src/ethereum/forks/bpo2/vm/instructions/comparison.py index a6a3d99bc86..ee5c881ef0d 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/comparison.py +++ b/src/ethereum/forks/bpo2/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/bpo2/vm/instructions/control_flow.py b/src/ethereum/forks/bpo2/vm/instructions/control_flow.py index b3b1f2316a7..d74e7b90340 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/control_flow.py +++ b/src/ethereum/forks/bpo2/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/bpo2/vm/instructions/environment.py b/src/ethereum/forks/bpo2/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/environment.py +++ b/src/ethereum/forks/bpo2/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/bpo2/vm/instructions/keccak.py b/src/ethereum/forks/bpo2/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/keccak.py +++ b/src/ethereum/forks/bpo2/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo2/vm/instructions/log.py b/src/ethereum/forks/bpo2/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/log.py +++ b/src/ethereum/forks/bpo2/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/bpo2/vm/instructions/memory.py b/src/ethereum/forks/bpo2/vm/instructions/memory.py index 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/memory.py +++ b/src/ethereum/forks/bpo2/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo2/vm/instructions/stack.py b/src/ethereum/forks/bpo2/vm/instructions/stack.py index 0007a28acd4..d7b3df986b0 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/stack.py +++ b/src/ethereum/forks/bpo2/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # 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, GasCosts.OPCODE_DUP) 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, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/bpo2/vm/instructions/storage.py b/src/ethereum/forks/bpo2/vm/instructions/storage.py index fd5bf4572ff..dbbd8db40ca 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/storage.py +++ b/src/ethereum/forks/bpo2/vm/instructions/storage.py @@ -22,15 +22,7 @@ ) from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext -from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, - charge_gas, -) +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -50,10 +42,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +71,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +84,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +145,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +172,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/bpo2/vm/instructions/system.py b/src/ethereum/forks/bpo2/vm/instructions/system.py index 29c3fe9e6e2..2d99ac93e61 100644 --- a/src/ethereum/forks/bpo2/vm/instructions/system.py +++ b/src/ethereum/forks/bpo2/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +158,9 @@ 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, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,8 +210,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -261,7 +255,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -374,10 +368,10 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( @@ -388,10 +382,10 @@ def call(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -463,10 +457,10 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -476,7 +470,7 @@ def callcode(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -531,10 +525,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -543,7 +537,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -604,10 +598,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -673,10 +667,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( diff --git a/src/ethereum/forks/bpo2/vm/interpreter.py b/src/ethereum/forks/bpo2/vm/interpreter.py index a7b27243123..31e07e2d968 100644 --- a/src/ethereum/forks/bpo2/vm/interpreter.py +++ b/src/ethereum/forks/bpo2/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -191,7 +191,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..f77ff60a32c 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -20,12 +20,7 @@ ) from ....vm import Evm -from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, - charge_gas, -) +from ....vm.gas import GasCosts, charge_gas from ....vm.memory import buffer_read from ...exceptions import InvalidParameter from . import ( @@ -60,7 +55,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1ADD)) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +96,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +135,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1MAP)) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..b49ec065e7c 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -20,12 +20,7 @@ ) from ....vm import Evm -from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, - charge_gas, -) +from ....vm.gas import GasCosts, charge_gas from ....vm.memory import buffer_read from ...exceptions import InvalidParameter from . import ( @@ -61,7 +56,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2ADD)) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +97,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +136,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2MAP)) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/identity.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/identity.py index 133a4832bf8..2b4929fb8d2 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/identity.py @@ -16,11 +16,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def identity(evm: Evm) -> None: @@ -39,8 +35,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/p256verify.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/p256verify.py index e35ea1bb4ec..29c2e91e0f0 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/p256verify.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/p256verify.py @@ -24,7 +24,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_P256VERIFY, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -41,7 +41,7 @@ def p256verify(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_P256VERIFY) + charge_gas(evm, GasCosts.PRECOMPILE_P256VERIFY) if len(data) != 160: return diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..04d0e2ff594 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/ripemd160.py @@ -19,11 +19,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def ripemd160(evm: Evm) -> None: @@ -42,8 +38,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo2/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/bpo2/vm/precompiled_contracts/sha256.py index 04dfef6730d..f5346f1529c 100644 --- a/src/ethereum/forks/bpo2/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/bpo2/vm/precompiled_contracts/sha256.py @@ -18,11 +18,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def sha256(evm: Evm) -> None: @@ -41,8 +37,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo3/fork.py b/src/ethereum/forks/bpo3/fork.py index 7e6b5ee46de..19ce50f243d 100644 --- a/src/ethereum/forks/bpo3/fork.py +++ b/src/ethereum/forks/bpo3/fork.py @@ -81,8 +81,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( - BLOB_SCHEDULE_MAX, - GAS_PER_BLOB, + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -92,15 +91,13 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB +MAX_BLOB_GAS_PER_BLOCK = GasCosts.BLOB_SCHEDULE_MAX * GasCosts.PER_BLOB VERSIONED_HASH_VERSION_KZG = b"\x01" WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address( @@ -1030,14 +1027,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1053,12 +1050,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/bpo3/transactions.py b/src/ethereum/forks/bpo3/transactions.py index c8f1826324e..486b21f99b0 100644 --- a/src/ethereum/forks/bpo3/transactions.py +++ b/src/ethereum/forks/bpo3/transactions.py @@ -28,43 +28,6 @@ ) from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - TX_MAX_GAS_LIMIT = Uint(16_777_216) @@ -601,7 +564,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -612,8 +575,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -621,31 +583,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/bpo3/vm/eoa_delegation.py b/src/ethereum/forks/bpo3/vm/eoa_delegation.py index fce580bee4a..3fd42910817 100644 --- a/src/ethereum/forks/bpo3/vm/eoa_delegation.py +++ b/src/ethereum/forks/bpo3/vm/eoa_delegation.py @@ -22,14 +22,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -147,10 +146,10 @@ def access_delegation( address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code = get_code(state, get_account(state, address).code_hash) return True, address, code, access_gas_cost @@ -199,7 +198,8 @@ def set_delegation(message: Message) -> U256: if account_exists(state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/bpo3/vm/gas.py b/src/ethereum/forks/bpo3/vm/gas.py index 5c30cd6a340..50edd7d5d7a 100644 --- a/src/ethereum/forks/bpo3/vm/gas.py +++ b/src/ethereum/forks/bpo3/vm/gas.py @@ -24,65 +24,169 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_P256VERIFY = Uint(6900) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(14) -BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET -BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(21) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_P256VERIFY = Uint(6900) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_SCHEDULE_TARGET = U64(14) + BLOB_TARGET_GAS_PER_BLOCK = PER_BLOB * BLOB_SCHEDULE_TARGET + BLOB_BASE_COST = Uint(2**13) + BLOB_SCHEDULE_MAX = U64(21) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_CLZ = LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -103,8 +207,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -156,7 +260,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -211,7 +315,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -283,7 +387,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -314,21 +418,23 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: base_fee_per_gas = parent_header.base_fee_per_gas parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - target_blob_gas_price = Uint(GAS_PER_BLOB) + target_blob_gas_price = Uint(GasCosts.PER_BLOB) target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) - base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas + base_blob_tx_price = GasCosts.BLOB_BASE_COST * base_fee_per_gas if base_blob_tx_price > target_blob_gas_price: - blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET + blob_schedule_delta = ( + GasCosts.BLOB_SCHEDULE_MAX - GasCosts.BLOB_SCHEDULE_TARGET + ) return ( excess_blob_gas - + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX + + blob_gas_used * blob_schedule_delta // GasCosts.BLOB_SCHEDULE_MAX ) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -347,7 +453,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -368,9 +474,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/bpo3/vm/instructions/arithmetic.py b/src/ethereum/forks/bpo3/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/bpo3/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/bpo3/vm/instructions/bitwise.py b/src/ethereum/forks/bpo3/vm/instructions/bitwise.py index cc6fa2fbb23..8b41a55d2b2 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/bitwise.py +++ b/src/ethereum/forks/bpo3/vm/instructions/bitwise.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -34,7 +34,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +59,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +84,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +108,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +134,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +169,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +199,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +229,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: @@ -262,7 +262,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_CLZ) # OPERATION bit_length = U256(x.bit_length()) diff --git a/src/ethereum/forks/bpo3/vm/instructions/block.py b/src/ethereum/forks/bpo3/vm/instructions/block.py index 10fcbdbdb57..54183f4773e 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/block.py +++ b/src/ethereum/forks/bpo3/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/bpo3/vm/instructions/comparison.py b/src/ethereum/forks/bpo3/vm/instructions/comparison.py index a6a3d99bc86..ee5c881ef0d 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/comparison.py +++ b/src/ethereum/forks/bpo3/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/bpo3/vm/instructions/control_flow.py b/src/ethereum/forks/bpo3/vm/instructions/control_flow.py index b3b1f2316a7..d74e7b90340 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/control_flow.py +++ b/src/ethereum/forks/bpo3/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/bpo3/vm/instructions/environment.py b/src/ethereum/forks/bpo3/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/environment.py +++ b/src/ethereum/forks/bpo3/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/bpo3/vm/instructions/keccak.py b/src/ethereum/forks/bpo3/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/keccak.py +++ b/src/ethereum/forks/bpo3/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo3/vm/instructions/log.py b/src/ethereum/forks/bpo3/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/log.py +++ b/src/ethereum/forks/bpo3/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/bpo3/vm/instructions/memory.py b/src/ethereum/forks/bpo3/vm/instructions/memory.py index 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/memory.py +++ b/src/ethereum/forks/bpo3/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo3/vm/instructions/stack.py b/src/ethereum/forks/bpo3/vm/instructions/stack.py index 0007a28acd4..d7b3df986b0 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/stack.py +++ b/src/ethereum/forks/bpo3/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # 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, GasCosts.OPCODE_DUP) 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, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/bpo3/vm/instructions/storage.py b/src/ethereum/forks/bpo3/vm/instructions/storage.py index fd5bf4572ff..dbbd8db40ca 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/storage.py +++ b/src/ethereum/forks/bpo3/vm/instructions/storage.py @@ -22,15 +22,7 @@ ) from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext -from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, - charge_gas, -) +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -50,10 +42,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +71,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +84,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +145,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +172,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/bpo3/vm/instructions/system.py b/src/ethereum/forks/bpo3/vm/instructions/system.py index 29c3fe9e6e2..2d99ac93e61 100644 --- a/src/ethereum/forks/bpo3/vm/instructions/system.py +++ b/src/ethereum/forks/bpo3/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +158,9 @@ 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, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,8 +210,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -261,7 +255,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -374,10 +368,10 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( @@ -388,10 +382,10 @@ def call(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -463,10 +457,10 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -476,7 +470,7 @@ def callcode(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -531,10 +525,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -543,7 +537,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -604,10 +598,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -673,10 +667,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( diff --git a/src/ethereum/forks/bpo3/vm/interpreter.py b/src/ethereum/forks/bpo3/vm/interpreter.py index 4111d5b4c78..d3c301fc708 100644 --- a/src/ethereum/forks/bpo3/vm/interpreter.py +++ b/src/ethereum/forks/bpo3/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -191,7 +191,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..fa0d3ec4c2d 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -60,7 +58,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1ADD)) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +99,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +138,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1MAP)) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..a5b2be04018 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -61,7 +59,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2ADD)) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +100,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +139,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2MAP)) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/identity.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/p256verify.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/p256verify.py index e35ea1bb4ec..29c2e91e0f0 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/p256verify.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/p256verify.py @@ -24,7 +24,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_P256VERIFY, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -41,7 +41,7 @@ def p256verify(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_P256VERIFY) + charge_gas(evm, GasCosts.PRECOMPILE_P256VERIFY) if len(data) != 160: return diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo3/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/bpo3/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/bpo3/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/bpo3/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo4/fork.py b/src/ethereum/forks/bpo4/fork.py index 7e6b5ee46de..19ce50f243d 100644 --- a/src/ethereum/forks/bpo4/fork.py +++ b/src/ethereum/forks/bpo4/fork.py @@ -81,8 +81,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( - BLOB_SCHEDULE_MAX, - GAS_PER_BLOB, + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -92,15 +91,13 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB +MAX_BLOB_GAS_PER_BLOCK = GasCosts.BLOB_SCHEDULE_MAX * GasCosts.PER_BLOB VERSIONED_HASH_VERSION_KZG = b"\x01" WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address( @@ -1030,14 +1027,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1053,12 +1050,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/bpo4/transactions.py b/src/ethereum/forks/bpo4/transactions.py index c8f1826324e..486b21f99b0 100644 --- a/src/ethereum/forks/bpo4/transactions.py +++ b/src/ethereum/forks/bpo4/transactions.py @@ -28,43 +28,6 @@ ) from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - TX_MAX_GAS_LIMIT = Uint(16_777_216) @@ -601,7 +564,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -612,8 +575,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -621,31 +583,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/bpo4/vm/eoa_delegation.py b/src/ethereum/forks/bpo4/vm/eoa_delegation.py index fce580bee4a..3fd42910817 100644 --- a/src/ethereum/forks/bpo4/vm/eoa_delegation.py +++ b/src/ethereum/forks/bpo4/vm/eoa_delegation.py @@ -22,14 +22,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -147,10 +146,10 @@ def access_delegation( address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code = get_code(state, get_account(state, address).code_hash) return True, address, code, access_gas_cost @@ -199,7 +198,8 @@ def set_delegation(message: Message) -> U256: if account_exists(state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/bpo4/vm/gas.py b/src/ethereum/forks/bpo4/vm/gas.py index 5c30cd6a340..50edd7d5d7a 100644 --- a/src/ethereum/forks/bpo4/vm/gas.py +++ b/src/ethereum/forks/bpo4/vm/gas.py @@ -24,65 +24,169 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_P256VERIFY = Uint(6900) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(14) -BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET -BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(21) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_P256VERIFY = Uint(6900) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_SCHEDULE_TARGET = U64(14) + BLOB_TARGET_GAS_PER_BLOCK = PER_BLOB * BLOB_SCHEDULE_TARGET + BLOB_BASE_COST = Uint(2**13) + BLOB_SCHEDULE_MAX = U64(21) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_CLZ = LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -103,8 +207,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -156,7 +260,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -211,7 +315,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -283,7 +387,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -314,21 +418,23 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: base_fee_per_gas = parent_header.base_fee_per_gas parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - target_blob_gas_price = Uint(GAS_PER_BLOB) + target_blob_gas_price = Uint(GasCosts.PER_BLOB) target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) - base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas + base_blob_tx_price = GasCosts.BLOB_BASE_COST * base_fee_per_gas if base_blob_tx_price > target_blob_gas_price: - blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET + blob_schedule_delta = ( + GasCosts.BLOB_SCHEDULE_MAX - GasCosts.BLOB_SCHEDULE_TARGET + ) return ( excess_blob_gas - + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX + + blob_gas_used * blob_schedule_delta // GasCosts.BLOB_SCHEDULE_MAX ) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -347,7 +453,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -368,9 +474,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/bpo4/vm/instructions/arithmetic.py b/src/ethereum/forks/bpo4/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/bpo4/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/bpo4/vm/instructions/bitwise.py b/src/ethereum/forks/bpo4/vm/instructions/bitwise.py index cc6fa2fbb23..7674d3c720f 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/bitwise.py +++ b/src/ethereum/forks/bpo4/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: @@ -262,7 +265,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_CLZ) # OPERATION bit_length = U256(x.bit_length()) diff --git a/src/ethereum/forks/bpo4/vm/instructions/block.py b/src/ethereum/forks/bpo4/vm/instructions/block.py index 52145aa9f82..e53d2a57a35 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/block.py +++ b/src/ethereum/forks/bpo4/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/bpo4/vm/instructions/comparison.py b/src/ethereum/forks/bpo4/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/comparison.py +++ b/src/ethereum/forks/bpo4/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/bpo4/vm/instructions/control_flow.py b/src/ethereum/forks/bpo4/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/control_flow.py +++ b/src/ethereum/forks/bpo4/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/bpo4/vm/instructions/environment.py b/src/ethereum/forks/bpo4/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/environment.py +++ b/src/ethereum/forks/bpo4/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/bpo4/vm/instructions/keccak.py b/src/ethereum/forks/bpo4/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/keccak.py +++ b/src/ethereum/forks/bpo4/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo4/vm/instructions/log.py b/src/ethereum/forks/bpo4/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/log.py +++ b/src/ethereum/forks/bpo4/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/bpo4/vm/instructions/memory.py b/src/ethereum/forks/bpo4/vm/instructions/memory.py index 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/memory.py +++ b/src/ethereum/forks/bpo4/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo4/vm/instructions/stack.py b/src/ethereum/forks/bpo4/vm/instructions/stack.py index 0007a28acd4..366cf79f5e4 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/stack.py +++ b/src/ethereum/forks/bpo4/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -63,9 +66,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +98,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +130,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/bpo4/vm/instructions/storage.py b/src/ethereum/forks/bpo4/vm/instructions/storage.py index fd5bf4572ff..5aa3cc6746f 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/storage.py +++ b/src/ethereum/forks/bpo4/vm/instructions/storage.py @@ -23,12 +23,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -50,10 +45,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +74,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +87,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +148,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +175,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/bpo4/vm/instructions/system.py b/src/ethereum/forks/bpo4/vm/instructions/system.py index 29c3fe9e6e2..1fe8daf44d5 100644 --- a/src/ethereum/forks/bpo4/vm/instructions/system.py +++ b/src/ethereum/forks/bpo4/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +158,10 @@ 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, + GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,8 +211,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -261,7 +256,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -374,10 +369,10 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( @@ -388,10 +383,10 @@ def call(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -463,10 +458,10 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -476,7 +471,7 @@ def callcode(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -531,10 +526,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -543,7 +538,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -604,10 +599,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -673,10 +668,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( diff --git a/src/ethereum/forks/bpo4/vm/interpreter.py b/src/ethereum/forks/bpo4/vm/interpreter.py index 7e789cf4b69..de598138081 100644 --- a/src/ethereum/forks/bpo4/vm/interpreter.py +++ b/src/ethereum/forks/bpo4/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -191,7 +191,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..fa0d3ec4c2d 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -60,7 +58,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1ADD)) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +99,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +138,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1MAP)) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..a5b2be04018 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -61,7 +59,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2ADD)) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +100,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +139,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2MAP)) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/identity.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/p256verify.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/p256verify.py index e35ea1bb4ec..29c2e91e0f0 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/p256verify.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/p256verify.py @@ -24,7 +24,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_P256VERIFY, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -41,7 +41,7 @@ def p256verify(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_P256VERIFY) + charge_gas(evm, GasCosts.PRECOMPILE_P256VERIFY) if len(data) != 160: return diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo4/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/bpo4/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/bpo4/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/bpo4/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo5/fork.py b/src/ethereum/forks/bpo5/fork.py index 7e6b5ee46de..19ce50f243d 100644 --- a/src/ethereum/forks/bpo5/fork.py +++ b/src/ethereum/forks/bpo5/fork.py @@ -81,8 +81,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( - BLOB_SCHEDULE_MAX, - GAS_PER_BLOB, + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -92,15 +91,13 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB +MAX_BLOB_GAS_PER_BLOCK = GasCosts.BLOB_SCHEDULE_MAX * GasCosts.PER_BLOB VERSIONED_HASH_VERSION_KZG = b"\x01" WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address( @@ -1030,14 +1027,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1053,12 +1050,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/bpo5/transactions.py b/src/ethereum/forks/bpo5/transactions.py index c8f1826324e..486b21f99b0 100644 --- a/src/ethereum/forks/bpo5/transactions.py +++ b/src/ethereum/forks/bpo5/transactions.py @@ -28,43 +28,6 @@ ) from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - TX_MAX_GAS_LIMIT = Uint(16_777_216) @@ -601,7 +564,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -612,8 +575,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -621,31 +583,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/bpo5/vm/eoa_delegation.py b/src/ethereum/forks/bpo5/vm/eoa_delegation.py index fce580bee4a..3fd42910817 100644 --- a/src/ethereum/forks/bpo5/vm/eoa_delegation.py +++ b/src/ethereum/forks/bpo5/vm/eoa_delegation.py @@ -22,14 +22,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -147,10 +146,10 @@ def access_delegation( address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code = get_code(state, get_account(state, address).code_hash) return True, address, code, access_gas_cost @@ -199,7 +198,8 @@ def set_delegation(message: Message) -> U256: if account_exists(state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/bpo5/vm/gas.py b/src/ethereum/forks/bpo5/vm/gas.py index 5c30cd6a340..50edd7d5d7a 100644 --- a/src/ethereum/forks/bpo5/vm/gas.py +++ b/src/ethereum/forks/bpo5/vm/gas.py @@ -24,65 +24,169 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_P256VERIFY = Uint(6900) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(14) -BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET -BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(21) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_P256VERIFY = Uint(6900) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_SCHEDULE_TARGET = U64(14) + BLOB_TARGET_GAS_PER_BLOCK = PER_BLOB * BLOB_SCHEDULE_TARGET + BLOB_BASE_COST = Uint(2**13) + BLOB_SCHEDULE_MAX = U64(21) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_CLZ = LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -103,8 +207,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -156,7 +260,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -211,7 +315,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -283,7 +387,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -314,21 +418,23 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: base_fee_per_gas = parent_header.base_fee_per_gas parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - target_blob_gas_price = Uint(GAS_PER_BLOB) + target_blob_gas_price = Uint(GasCosts.PER_BLOB) target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) - base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas + base_blob_tx_price = GasCosts.BLOB_BASE_COST * base_fee_per_gas if base_blob_tx_price > target_blob_gas_price: - blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET + blob_schedule_delta = ( + GasCosts.BLOB_SCHEDULE_MAX - GasCosts.BLOB_SCHEDULE_TARGET + ) return ( excess_blob_gas - + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX + + blob_gas_used * blob_schedule_delta // GasCosts.BLOB_SCHEDULE_MAX ) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -347,7 +453,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -368,9 +474,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/bpo5/vm/instructions/arithmetic.py b/src/ethereum/forks/bpo5/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/bpo5/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/bpo5/vm/instructions/bitwise.py b/src/ethereum/forks/bpo5/vm/instructions/bitwise.py index cc6fa2fbb23..7674d3c720f 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/bitwise.py +++ b/src/ethereum/forks/bpo5/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: @@ -262,7 +265,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_CLZ) # OPERATION bit_length = U256(x.bit_length()) diff --git a/src/ethereum/forks/bpo5/vm/instructions/block.py b/src/ethereum/forks/bpo5/vm/instructions/block.py index 84930244d4c..faa2e0fa040 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/block.py +++ b/src/ethereum/forks/bpo5/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/bpo5/vm/instructions/comparison.py b/src/ethereum/forks/bpo5/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/comparison.py +++ b/src/ethereum/forks/bpo5/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/bpo5/vm/instructions/control_flow.py b/src/ethereum/forks/bpo5/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/control_flow.py +++ b/src/ethereum/forks/bpo5/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/bpo5/vm/instructions/environment.py b/src/ethereum/forks/bpo5/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/environment.py +++ b/src/ethereum/forks/bpo5/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/bpo5/vm/instructions/keccak.py b/src/ethereum/forks/bpo5/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/keccak.py +++ b/src/ethereum/forks/bpo5/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo5/vm/instructions/log.py b/src/ethereum/forks/bpo5/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/log.py +++ b/src/ethereum/forks/bpo5/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/bpo5/vm/instructions/memory.py b/src/ethereum/forks/bpo5/vm/instructions/memory.py index 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/memory.py +++ b/src/ethereum/forks/bpo5/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/bpo5/vm/instructions/stack.py b/src/ethereum/forks/bpo5/vm/instructions/stack.py index 0007a28acd4..366cf79f5e4 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/stack.py +++ b/src/ethereum/forks/bpo5/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -63,9 +66,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +98,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +130,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/bpo5/vm/instructions/storage.py b/src/ethereum/forks/bpo5/vm/instructions/storage.py index fd5bf4572ff..5aa3cc6746f 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/storage.py +++ b/src/ethereum/forks/bpo5/vm/instructions/storage.py @@ -23,12 +23,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -50,10 +45,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +74,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +87,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +148,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +175,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/bpo5/vm/instructions/system.py b/src/ethereum/forks/bpo5/vm/instructions/system.py index 29c3fe9e6e2..1fe8daf44d5 100644 --- a/src/ethereum/forks/bpo5/vm/instructions/system.py +++ b/src/ethereum/forks/bpo5/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +158,10 @@ 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, + GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,8 +211,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -261,7 +256,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -374,10 +369,10 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( @@ -388,10 +383,10 @@ def call(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -463,10 +458,10 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -476,7 +471,7 @@ def callcode(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -531,10 +526,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -543,7 +538,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -604,10 +599,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -673,10 +668,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( diff --git a/src/ethereum/forks/bpo5/vm/interpreter.py b/src/ethereum/forks/bpo5/vm/interpreter.py index d0eda4ef22d..138131315c5 100644 --- a/src/ethereum/forks/bpo5/vm/interpreter.py +++ b/src/ethereum/forks/bpo5/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -191,7 +191,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..fa0d3ec4c2d 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -60,7 +58,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1ADD)) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +99,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +138,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1MAP)) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..a5b2be04018 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -61,7 +59,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2ADD)) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +100,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +139,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2MAP)) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/identity.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/p256verify.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/p256verify.py index e35ea1bb4ec..29c2e91e0f0 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/p256verify.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/p256verify.py @@ -24,7 +24,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_P256VERIFY, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -41,7 +41,7 @@ def p256verify(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_P256VERIFY) + charge_gas(evm, GasCosts.PRECOMPILE_P256VERIFY) if len(data) != 160: return diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/bpo5/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/bpo5/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/bpo5/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/bpo5/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/byzantium/fork.py b/src/ethereum/forks/byzantium/fork.py index 3cbf03500b3..956b298980f 100644 --- a/src/ethereum/forks/byzantium/fork.py +++ b/src/ethereum/forks/byzantium/fork.py @@ -51,11 +51,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(3 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) BOMB_DELAY_BLOCKS = 3000000 @@ -711,14 +710,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -734,12 +733,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/byzantium/transactions.py b/src/ethereum/forks/byzantium/transactions.py index 278238f8d5a..e8cde82b198 100644 --- a/src/ethereum/forks/byzantium/transactions.py +++ b/src/ethereum/forks/byzantium/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(68) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/byzantium/vm/gas.py b/src/ethereum/forks/byzantium/vm/gas.py index c4aa9846029..6121e3bbce0 100644 --- a/src/ethereum/forks/byzantium/vm/gas.py +++ b/src/ethereum/forks/byzantium/vm/gas.py @@ -22,46 +22,136 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(200) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(700) -GAS_BALANCE = Uint(400) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(700) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -REFUND_SELF_DESTRUCT = 24000 -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(200) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = 24000 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_ECADD = Uint(500) + PRECOMPILE_ECMUL = Uint(40000) + PRECOMPILE_ECPAIRING_BASE = Uint(100000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(80000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(68) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) + OPCODE_EXTERNAL_BASE = Uint(700) + OPCODE_BALANCE = Uint(400) + OPCODE_CALL_BASE = Uint(700) @dataclass @@ -82,8 +172,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -135,7 +225,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -190,7 +280,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/byzantium/vm/instructions/arithmetic.py b/src/ethereum/forks/byzantium/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/byzantium/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/byzantium/vm/instructions/bitwise.py b/src/ethereum/forks/byzantium/vm/instructions/bitwise.py index 2a506f55751..62da98041ad 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/bitwise.py +++ b/src/ethereum/forks/byzantium/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): diff --git a/src/ethereum/forks/byzantium/vm/instructions/block.py b/src/ethereum/forks/byzantium/vm/instructions/block.py index 0edcbf000d1..fbca7daa37c 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/block.py +++ b/src/ethereum/forks/byzantium/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) diff --git a/src/ethereum/forks/byzantium/vm/instructions/comparison.py b/src/ethereum/forks/byzantium/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/comparison.py +++ b/src/ethereum/forks/byzantium/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/byzantium/vm/instructions/control_flow.py b/src/ethereum/forks/byzantium/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/control_flow.py +++ b/src/ethereum/forks/byzantium/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/byzantium/vm/instructions/environment.py b/src/ethereum/forks/byzantium/vm/instructions/environment.py index 0fa98ce55a5..c459b2aebec 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/environment.py +++ b/src/ethereum/forks/byzantium/vm/instructions/environment.py @@ -21,12 +21,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_COPY, - GAS_EXTERNAL, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -47,7 +42,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -70,7 +65,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -97,7 +92,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -120,7 +115,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -143,7 +138,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -167,7 +162,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -192,7 +187,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -221,11 +216,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -250,7 +248,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -279,11 +277,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -308,7 +309,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -331,7 +332,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -362,11 +363,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -394,7 +398,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -420,11 +424,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead diff --git a/src/ethereum/forks/byzantium/vm/instructions/keccak.py b/src/ethereum/forks/byzantium/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/keccak.py +++ b/src/ethereum/forks/byzantium/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/byzantium/vm/instructions/log.py b/src/ethereum/forks/byzantium/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/log.py +++ b/src/ethereum/forks/byzantium/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/byzantium/vm/instructions/memory.py b/src/ethereum/forks/byzantium/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/memory.py +++ b/src/ethereum/forks/byzantium/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/byzantium/vm/instructions/stack.py b/src/ethereum/forks/byzantium/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/stack.py +++ b/src/ethereum/forks/byzantium/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/byzantium/vm/instructions/storage.py b/src/ethereum/forks/byzantium/vm/instructions/storage.py index e1c4e4e0958..0e5aae6031d 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/storage.py +++ b/src/ethereum/forks/byzantium/vm/instructions/storage.py @@ -17,10 +17,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -41,7 +38,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -72,12 +69,12 @@ def sstore(evm: Evm) -> None: state = evm.message.block_env.state current_value = get_storage(state, evm.message.current_target, key) if new_value != 0 and current_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE if new_value == 0 and current_value != 0: - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR charge_gas(evm, gas_cost) if evm.message.is_static: diff --git a/src/ethereum/forks/byzantium/vm/instructions/system.py b/src/ethereum/forks/byzantium/vm/instructions/system.py index 9a4a7ce52ae..01e4048cc67 100644 --- a/src/ethereum/forks/byzantium/vm/instructions/system.py +++ b/src/ethereum/forks/byzantium/vm/instructions/system.py @@ -35,14 +35,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL, - GAS_CALL_VALUE, - GAS_CREATE, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -76,7 +69,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) create_message_gas = max_message_call_gas(Uint(evm.gas_left)) evm.gas_left -= create_message_gas @@ -170,7 +163,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -280,16 +273,16 @@ def call(evm: Evm) -> None: code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + create_gas_cost + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + create_gas_cost + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) if evm.message.is_static and value != U256(0): @@ -351,13 +344,13 @@ def callcode(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -404,7 +397,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if ( not is_account_alive(evm.message.block_env.state, beneficiary) and get_account( @@ -412,7 +405,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT originator = evm.message.current_target @@ -423,7 +416,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += REFUND_SELF_DESTRUCT + evm.refund_counter += GasCosts.REFUND_SELF_DESTRUCT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -488,7 +481,11 @@ def delegatecall(evm: Evm) -> None: ], ) message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -547,7 +544,7 @@ def staticcall(evm: Evm) -> None: gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) diff --git a/src/ethereum/forks/byzantium/vm/interpreter.py b/src/ethereum/forks/byzantium/vm/interpreter.py index 2cb1ccc3335..a5a72762dbd 100644 --- a/src/ethereum/forks/byzantium/vm/interpreter.py +++ b/src/ethereum/forks/byzantium/vm/interpreter.py @@ -44,7 +44,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -174,7 +174,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/byzantium/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/byzantium/vm/precompiled_contracts/alt_bn128.py index d579abb2b8a..09bed4a0282 100644 --- a/src/ethereum/forks/byzantium/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/byzantium/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(500)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(40000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(80000 * (len(data) // 192) + 100000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/byzantium/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/byzantium/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/byzantium/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/byzantium/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/byzantium/vm/precompiled_contracts/identity.py b/src/ethereum/forks/byzantium/vm/precompiled_contracts/identity.py index 133a4832bf8..2b4929fb8d2 100644 --- a/src/ethereum/forks/byzantium/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/byzantium/vm/precompiled_contracts/identity.py @@ -16,11 +16,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def identity(evm: Evm) -> None: @@ -39,8 +35,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/byzantium/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/byzantium/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..04d0e2ff594 100644 --- a/src/ethereum/forks/byzantium/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/byzantium/vm/precompiled_contracts/ripemd160.py @@ -19,11 +19,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def ripemd160(evm: Evm) -> None: @@ -42,8 +38,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/byzantium/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/byzantium/vm/precompiled_contracts/sha256.py index 04dfef6730d..f5346f1529c 100644 --- a/src/ethereum/forks/byzantium/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/byzantium/vm/precompiled_contracts/sha256.py @@ -18,11 +18,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def sha256(evm: Evm) -> None: @@ -41,8 +37,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/cancun/fork.py b/src/ethereum/forks/cancun/fork.py index 1c1dbab2865..c99cc0159e8 100644 --- a/src/ethereum/forks/cancun/fork.py +++ b/src/ethereum/forks/cancun/fork.py @@ -70,6 +70,7 @@ from .utils.message import prepare_message from .vm import Message from .vm.gas import ( + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -79,8 +80,6 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( @@ -852,14 +851,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -875,12 +874,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/cancun/transactions.py b/src/ethereum/forks/cancun/transactions.py index c94f3df0647..b8f431f64e0 100644 --- a/src/ethereum/forks/cancun/transactions.py +++ b/src/ethereum/forks/cancun/transactions.py @@ -24,37 +24,6 @@ from .exceptions import InitCodeTooLargeError, TransactionTypeError from .fork_types import VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -480,7 +449,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -488,17 +457,17 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) @@ -507,12 +476,12 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction) ): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) - return GAS_TX_BASE + data_cost + create_cost + access_list_cost + return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/cancun/vm/gas.py b/src/ethereum/forks/cancun/vm/gas.py index 0523287c6cf..c3a65792ec2 100644 --- a/src/ethereum/forks/cancun/vm/gas.py +++ b/src/ethereum/forks/cancun/vm/gas.py @@ -24,54 +24,155 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_TARGET_GAS_PER_BLOCK = U64(393216) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(3338477) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_TARGET_GAS_PER_BLOCK = U64(393216) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(3338477) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -92,8 +193,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -145,7 +246,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -200,7 +301,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -272,7 +373,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -301,10 +402,10 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: blob_gas_used = parent_header.blob_gas_used parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -323,7 +424,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -344,9 +445,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/cancun/vm/instructions/arithmetic.py b/src/ethereum/forks/cancun/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/cancun/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/cancun/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/cancun/vm/instructions/bitwise.py b/src/ethereum/forks/cancun/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/cancun/vm/instructions/bitwise.py +++ b/src/ethereum/forks/cancun/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/cancun/vm/instructions/block.py b/src/ethereum/forks/cancun/vm/instructions/block.py index 4f971a9dbf4..82378940859 100644 --- a/src/ethereum/forks/cancun/vm/instructions/block.py +++ b/src/ethereum/forks/cancun/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/cancun/vm/instructions/comparison.py b/src/ethereum/forks/cancun/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/cancun/vm/instructions/comparison.py +++ b/src/ethereum/forks/cancun/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/cancun/vm/instructions/control_flow.py b/src/ethereum/forks/cancun/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/cancun/vm/instructions/control_flow.py +++ b/src/ethereum/forks/cancun/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/cancun/vm/instructions/environment.py b/src/ethereum/forks/cancun/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/cancun/vm/instructions/environment.py +++ b/src/ethereum/forks/cancun/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE) # OPERATION blob_base_fee = calculate_blob_gas_price( diff --git a/src/ethereum/forks/cancun/vm/instructions/keccak.py b/src/ethereum/forks/cancun/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/cancun/vm/instructions/keccak.py +++ b/src/ethereum/forks/cancun/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/cancun/vm/instructions/log.py b/src/ethereum/forks/cancun/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/cancun/vm/instructions/log.py +++ b/src/ethereum/forks/cancun/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/cancun/vm/instructions/memory.py b/src/ethereum/forks/cancun/vm/instructions/memory.py index 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/cancun/vm/instructions/memory.py +++ b/src/ethereum/forks/cancun/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/cancun/vm/instructions/stack.py b/src/ethereum/forks/cancun/vm/instructions/stack.py index 0007a28acd4..366cf79f5e4 100644 --- a/src/ethereum/forks/cancun/vm/instructions/stack.py +++ b/src/ethereum/forks/cancun/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -63,9 +66,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +98,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +130,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/cancun/vm/instructions/storage.py b/src/ethereum/forks/cancun/vm/instructions/storage.py index fd5bf4572ff..5aa3cc6746f 100644 --- a/src/ethereum/forks/cancun/vm/instructions/storage.py +++ b/src/ethereum/forks/cancun/vm/instructions/storage.py @@ -23,12 +23,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -50,10 +45,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +74,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +87,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +148,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +175,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) if evm.message.is_static: raise WriteInStaticContext set_transient_storage( diff --git a/src/ethereum/forks/cancun/vm/instructions/system.py b/src/ethereum/forks/cancun/vm/instructions/system.py index db725606a08..0808eb1f7a7 100644 --- a/src/ethereum/forks/cancun/vm/instructions/system.py +++ b/src/ethereum/forks/cancun/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -165,7 +157,9 @@ 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, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -215,8 +209,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -260,7 +254,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -371,17 +365,17 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -451,12 +445,12 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -509,10 +503,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -521,7 +515,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -582,10 +576,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS message_call_gas = calculate_message_call_gas( U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost @@ -641,10 +635,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to diff --git a/src/ethereum/forks/cancun/vm/interpreter.py b/src/ethereum/forks/cancun/vm/interpreter.py index 7f4bed0129c..05d14c7aebe 100644 --- a/src/ethereum/forks/cancun/vm/interpreter.py +++ b/src/ethereum/forks/cancun/vm/interpreter.py @@ -43,7 +43,7 @@ set_code, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -171,7 +171,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/cancun/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/cancun/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/cancun/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/cancun/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/cancun/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/cancun/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/cancun/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/cancun/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/cancun/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/cancun/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/cancun/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/cancun/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/cancun/vm/precompiled_contracts/identity.py b/src/ethereum/forks/cancun/vm/precompiled_contracts/identity.py index 133a4832bf8..2b4929fb8d2 100644 --- a/src/ethereum/forks/cancun/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/cancun/vm/precompiled_contracts/identity.py @@ -16,11 +16,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def identity(evm: Evm) -> None: @@ -39,8 +35,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/cancun/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/cancun/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/cancun/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/cancun/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/cancun/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/cancun/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..04d0e2ff594 100644 --- a/src/ethereum/forks/cancun/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/cancun/vm/precompiled_contracts/ripemd160.py @@ -19,11 +19,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def ripemd160(evm: Evm) -> None: @@ -42,8 +38,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/cancun/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/cancun/vm/precompiled_contracts/sha256.py index 04dfef6730d..f5346f1529c 100644 --- a/src/ethereum/forks/cancun/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/cancun/vm/precompiled_contracts/sha256.py @@ -18,11 +18,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def sha256(evm: Evm) -> None: @@ -41,8 +37,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/constantinople/fork.py b/src/ethereum/forks/constantinople/fork.py index 7ed470d41e3..7765455cdb8 100644 --- a/src/ethereum/forks/constantinople/fork.py +++ b/src/ethereum/forks/constantinople/fork.py @@ -51,11 +51,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(2 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) BOMB_DELAY_BLOCKS = 5000000 @@ -711,14 +710,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -734,12 +733,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/constantinople/transactions.py b/src/ethereum/forks/constantinople/transactions.py index 278238f8d5a..e8cde82b198 100644 --- a/src/ethereum/forks/constantinople/transactions.py +++ b/src/ethereum/forks/constantinople/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(68) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/constantinople/vm/gas.py b/src/ethereum/forks/constantinople/vm/gas.py index f59699f0347..85e4d3be422 100644 --- a/src/ethereum/forks/constantinople/vm/gas.py +++ b/src/ethereum/forks/constantinople/vm/gas.py @@ -22,47 +22,140 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(200) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(700) -GAS_BALANCE = Uint(400) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(700) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -REFUND_SELF_DESTRUCT = 24000 -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_CODE_HASH = Uint(400) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(200) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = 24000 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_ECADD = Uint(500) + PRECOMPILE_ECMUL = Uint(40000) + PRECOMPILE_ECPAIRING_BASE = Uint(100000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(80000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(68) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_EXTCODEHASH = Uint(400) + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) + OPCODE_EXTERNAL_BASE = Uint(700) + OPCODE_BALANCE = Uint(400) + OPCODE_CALL_BASE = Uint(700) @dataclass @@ -83,8 +176,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -136,7 +229,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -191,7 +284,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/constantinople/vm/instructions/arithmetic.py b/src/ethereum/forks/constantinople/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/constantinople/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/constantinople/vm/instructions/bitwise.py b/src/ethereum/forks/constantinople/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/bitwise.py +++ b/src/ethereum/forks/constantinople/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/constantinople/vm/instructions/block.py b/src/ethereum/forks/constantinople/vm/instructions/block.py index 0edcbf000d1..fbca7daa37c 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/block.py +++ b/src/ethereum/forks/constantinople/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) diff --git a/src/ethereum/forks/constantinople/vm/instructions/comparison.py b/src/ethereum/forks/constantinople/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/comparison.py +++ b/src/ethereum/forks/constantinople/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/constantinople/vm/instructions/control_flow.py b/src/ethereum/forks/constantinople/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/control_flow.py +++ b/src/ethereum/forks/constantinople/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/constantinople/vm/instructions/environment.py b/src/ethereum/forks/constantinople/vm/instructions/environment.py index d5572be1b4a..2761ffda5fe 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/environment.py +++ b/src/ethereum/forks/constantinople/vm/instructions/environment.py @@ -22,13 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_CODE_HASH, - GAS_COPY, - GAS_EXTERNAL, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -72,7 +66,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -99,7 +93,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -122,7 +116,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -145,7 +139,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -169,7 +163,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -194,7 +188,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -223,11 +217,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -252,7 +249,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -281,11 +278,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -310,7 +310,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -333,7 +333,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -364,11 +364,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -396,7 +399,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -422,11 +425,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -454,7 +462,7 @@ def extcodehash(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_CODE_HASH) + charge_gas(evm, GasCosts.OPCODE_EXTCODEHASH) # OPERATION account = get_account(evm.message.block_env.state, address) diff --git a/src/ethereum/forks/constantinople/vm/instructions/keccak.py b/src/ethereum/forks/constantinople/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/keccak.py +++ b/src/ethereum/forks/constantinople/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/constantinople/vm/instructions/log.py b/src/ethereum/forks/constantinople/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/log.py +++ b/src/ethereum/forks/constantinople/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/constantinople/vm/instructions/memory.py b/src/ethereum/forks/constantinople/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/memory.py +++ b/src/ethereum/forks/constantinople/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/constantinople/vm/instructions/stack.py b/src/ethereum/forks/constantinople/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/stack.py +++ b/src/ethereum/forks/constantinople/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/constantinople/vm/instructions/storage.py b/src/ethereum/forks/constantinople/vm/instructions/storage.py index e1c4e4e0958..0e5aae6031d 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/storage.py +++ b/src/ethereum/forks/constantinople/vm/instructions/storage.py @@ -17,10 +17,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -41,7 +38,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -72,12 +69,12 @@ def sstore(evm: Evm) -> None: state = evm.message.block_env.state current_value = get_storage(state, evm.message.current_target, key) if new_value != 0 and current_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE if new_value == 0 and current_value != 0: - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR charge_gas(evm, gas_cost) if evm.message.is_static: diff --git a/src/ethereum/forks/constantinople/vm/instructions/system.py b/src/ethereum/forks/constantinople/vm/instructions/system.py index c251e65574d..bd66624215d 100644 --- a/src/ethereum/forks/constantinople/vm/instructions/system.py +++ b/src/ethereum/forks/constantinople/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL, - GAS_CALL_VALUE, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -157,7 +149,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -202,8 +194,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -242,7 +234,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -352,16 +344,16 @@ def call(evm: Evm) -> None: code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + create_gas_cost + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + create_gas_cost + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) if evm.message.is_static and value != U256(0): @@ -423,13 +415,13 @@ def callcode(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -476,7 +468,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if ( not is_account_alive(evm.message.block_env.state, beneficiary) and get_account( @@ -484,7 +476,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT originator = evm.message.current_target @@ -495,7 +487,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += REFUND_SELF_DESTRUCT + evm.refund_counter += GasCosts.REFUND_SELF_DESTRUCT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -561,7 +553,11 @@ def delegatecall(evm: Evm) -> None: ], ) message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -620,7 +616,7 @@ def staticcall(evm: Evm) -> None: gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) diff --git a/src/ethereum/forks/constantinople/vm/interpreter.py b/src/ethereum/forks/constantinople/vm/interpreter.py index b26937492a9..ffd3e29a5b7 100644 --- a/src/ethereum/forks/constantinople/vm/interpreter.py +++ b/src/ethereum/forks/constantinople/vm/interpreter.py @@ -44,7 +44,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -174,7 +174,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/constantinople/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/constantinople/vm/precompiled_contracts/alt_bn128.py index d579abb2b8a..09bed4a0282 100644 --- a/src/ethereum/forks/constantinople/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/constantinople/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(500)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(40000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(80000 * (len(data) // 192) + 100000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/constantinople/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/constantinople/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/constantinople/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/constantinople/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/constantinople/vm/precompiled_contracts/identity.py b/src/ethereum/forks/constantinople/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/constantinople/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/constantinople/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/constantinople/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/constantinople/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/constantinople/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/constantinople/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/constantinople/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/constantinople/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/constantinople/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/constantinople/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/dao_fork/fork.py b/src/ethereum/forks/dao_fork/fork.py index 9dc372bec66..4c9bed797f4 100644 --- a/src/ethereum/forks/dao_fork/fork.py +++ b/src/ethereum/forks/dao_fork/fork.py @@ -53,11 +53,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(5 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) @@ -721,14 +720,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -744,12 +743,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/dao_fork/transactions.py b/src/ethereum/forks/dao_fork/transactions.py index 934540874ca..e17bafae49d 100644 --- a/src/ethereum/forks/dao_fork/transactions.py +++ b/src/ethereum/forks/dao_fork/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(68) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(tx: Transaction) -> Address: diff --git a/src/ethereum/forks/dao_fork/vm/gas.py b/src/ethereum/forks/dao_fork/vm/gas.py index fc01397ceb0..f3644b8bf6a 100644 --- a/src/ethereum/forks/dao_fork/vm/gas.py +++ b/src/ethereum/forks/dao_fork/vm/gas.py @@ -24,43 +24,127 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(50) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(10) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(20) -GAS_BALANCE = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(40) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -REFUND_SELF_DESTRUCT = Uint(24000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(50) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = Uint(24000) + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(68) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(10) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_EXTERNAL_BASE = Uint(20) + OPCODE_BALANCE = Uint(20) + OPCODE_CALL_BASE = Uint(40) @dataclass @@ -81,8 +165,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -134,7 +218,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -205,8 +289,12 @@ def calculate_message_call_gas( message_call_gas: `MessageCallGas` """ - create_gas_cost = Uint(0) if account_exists(state, to) else GAS_NEW_ACCOUNT - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE - cost = GAS_CALL + gas + create_gas_cost + transfer_gas_cost - stipend = gas if value == 0 else GAS_CALL_STIPEND + gas + create_gas_cost = ( + Uint(0) if account_exists(state, to) else GasCosts.NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE + cost = ( + GasCosts.OPCODE_CALL_BASE + gas + create_gas_cost + transfer_gas_cost + ) + stipend = gas if value == 0 else GasCosts.CALL_STIPEND + gas return MessageCallGas(cost, stipend) diff --git a/src/ethereum/forks/dao_fork/vm/instructions/arithmetic.py b/src/ethereum/forks/dao_fork/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/dao_fork/vm/instructions/bitwise.py b/src/ethereum/forks/dao_fork/vm/instructions/bitwise.py index 2a506f55751..62da98041ad 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/bitwise.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): diff --git a/src/ethereum/forks/dao_fork/vm/instructions/block.py b/src/ethereum/forks/dao_fork/vm/instructions/block.py index 0edcbf000d1..fbca7daa37c 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/block.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) diff --git a/src/ethereum/forks/dao_fork/vm/instructions/comparison.py b/src/ethereum/forks/dao_fork/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/comparison.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/dao_fork/vm/instructions/control_flow.py b/src/ethereum/forks/dao_fork/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/control_flow.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/dao_fork/vm/instructions/environment.py b/src/ethereum/forks/dao_fork/vm/instructions/environment.py index 83eb5528226..d930368fdd9 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/environment.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/environment.py @@ -20,11 +20,7 @@ from ...vm.memory import buffer_read, memory_write from .. import Evm from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_COPY, - GAS_EXTERNAL, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -45,7 +41,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -68,7 +64,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -95,7 +91,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -118,7 +114,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -141,7 +137,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -165,7 +161,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -190,7 +186,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -219,11 +215,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -248,7 +247,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -277,11 +276,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -306,7 +308,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -329,7 +331,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -360,11 +362,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/dao_fork/vm/instructions/keccak.py b/src/ethereum/forks/dao_fork/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/keccak.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/dao_fork/vm/instructions/log.py b/src/ethereum/forks/dao_fork/vm/instructions/log.py index 76c02e737a4..e3e3ebd7e76 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/log.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/log.py @@ -18,9 +18,7 @@ from ...blocks import Log from .. import Evm from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -58,9 +56,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/dao_fork/vm/instructions/memory.py b/src/ethereum/forks/dao_fork/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/memory.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/dao_fork/vm/instructions/stack.py b/src/ethereum/forks/dao_fork/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/stack.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/dao_fork/vm/instructions/storage.py b/src/ethereum/forks/dao_fork/vm/instructions/storage.py index 154b4fd47bb..0b2a1cce8aa 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/storage.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/storage.py @@ -16,10 +16,7 @@ from ...state import get_storage, set_storage from .. import Evm from ..gas import ( - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -40,7 +37,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -71,12 +68,12 @@ def sstore(evm: Evm) -> None: state = evm.message.block_env.state current_value = get_storage(state, evm.message.current_target, key) if new_value != 0 and current_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE if new_value == 0 and current_value != 0: - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/dao_fork/vm/instructions/system.py b/src/ethereum/forks/dao_fork/vm/instructions/system.py index 75226650693..c40a241886a 100644 --- a/src/ethereum/forks/dao_fork/vm/instructions/system.py +++ b/src/ethereum/forks/dao_fork/vm/instructions/system.py @@ -32,10 +32,7 @@ incorporate_child_on_success, ) from ..gas import ( - GAS_CALL, - GAS_CREATE, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -68,7 +65,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) create_message_gas = evm.gas_left evm.gas_left = Uint(0) @@ -157,7 +154,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -368,7 +365,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_ZERO + gas_cost = GasCosts.ZERO originator = evm.message.current_target @@ -379,7 +376,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += int(REFUND_SELF_DESTRUCT) + evm.refund_counter += int(GasCosts.REFUND_SELF_DESTRUCT) charge_gas(evm, gas_cost) @@ -438,7 +435,7 @@ def delegatecall(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - charge_gas(evm, GAS_CALL + gas + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CALL_BASE + gas + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/dao_fork/vm/interpreter.py b/src/ethereum/forks/dao_fork/vm/interpreter.py index 4d26439da49..40bdffcc071 100644 --- a/src/ethereum/forks/dao_fork/vm/interpreter.py +++ b/src/ethereum/forks/dao_fork/vm/interpreter.py @@ -42,7 +42,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -158,7 +158,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/identity.py b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/dao_fork/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/dao_fork/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/frontier/fork.py b/src/ethereum/forks/frontier/fork.py index 5f062710138..70c52a0c056 100644 --- a/src/ethereum/forks/frontier/fork.py +++ b/src/ethereum/forks/frontier/fork.py @@ -49,11 +49,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(5 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) @@ -700,14 +699,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -723,12 +722,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/frontier/transactions.py b/src/ethereum/forks/frontier/transactions.py index 32be1dcdf0a..69b9ec52083 100644 --- a/src/ethereum/forks/frontier/transactions.py +++ b/src/ethereum/forks/frontier/transactions.py @@ -21,22 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(68) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - @slotted_freezable @dataclass @@ -138,20 +122,22 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) - return GAS_TX_BASE + data_cost + return GasCosts.TX_BASE + data_cost def recover_sender(tx: Transaction) -> Address: diff --git a/src/ethereum/forks/frontier/vm/gas.py b/src/ethereum/forks/frontier/vm/gas.py index fc01397ceb0..ec6e91a20ce 100644 --- a/src/ethereum/forks/frontier/vm/gas.py +++ b/src/ethereum/forks/frontier/vm/gas.py @@ -24,43 +24,125 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(50) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(10) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(20) -GAS_BALANCE = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(40) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -REFUND_SELF_DESTRUCT = Uint(24000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(50) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = Uint(24000) + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + + # Transactions + TX_BASE = Uint(21000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(68) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(10) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_EXTERNAL_BASE = Uint(20) + OPCODE_BALANCE = Uint(20) + OPCODE_CALL_BASE = Uint(40) @dataclass @@ -81,8 +163,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -134,7 +216,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -205,8 +287,12 @@ def calculate_message_call_gas( message_call_gas: `MessageCallGas` """ - create_gas_cost = Uint(0) if account_exists(state, to) else GAS_NEW_ACCOUNT - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE - cost = GAS_CALL + gas + create_gas_cost + transfer_gas_cost - stipend = gas if value == 0 else GAS_CALL_STIPEND + gas + create_gas_cost = ( + Uint(0) if account_exists(state, to) else GasCosts.NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE + cost = ( + GasCosts.OPCODE_CALL_BASE + gas + create_gas_cost + transfer_gas_cost + ) + stipend = gas if value == 0 else GasCosts.CALL_STIPEND + gas return MessageCallGas(cost, stipend) diff --git a/src/ethereum/forks/frontier/vm/instructions/arithmetic.py b/src/ethereum/forks/frontier/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/frontier/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/frontier/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/frontier/vm/instructions/bitwise.py b/src/ethereum/forks/frontier/vm/instructions/bitwise.py index 2a506f55751..62da98041ad 100644 --- a/src/ethereum/forks/frontier/vm/instructions/bitwise.py +++ b/src/ethereum/forks/frontier/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): diff --git a/src/ethereum/forks/frontier/vm/instructions/block.py b/src/ethereum/forks/frontier/vm/instructions/block.py index 0edcbf000d1..fbca7daa37c 100644 --- a/src/ethereum/forks/frontier/vm/instructions/block.py +++ b/src/ethereum/forks/frontier/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) diff --git a/src/ethereum/forks/frontier/vm/instructions/comparison.py b/src/ethereum/forks/frontier/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/frontier/vm/instructions/comparison.py +++ b/src/ethereum/forks/frontier/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/frontier/vm/instructions/control_flow.py b/src/ethereum/forks/frontier/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/frontier/vm/instructions/control_flow.py +++ b/src/ethereum/forks/frontier/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/frontier/vm/instructions/environment.py b/src/ethereum/forks/frontier/vm/instructions/environment.py index 83eb5528226..d930368fdd9 100644 --- a/src/ethereum/forks/frontier/vm/instructions/environment.py +++ b/src/ethereum/forks/frontier/vm/instructions/environment.py @@ -20,11 +20,7 @@ from ...vm.memory import buffer_read, memory_write from .. import Evm from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_COPY, - GAS_EXTERNAL, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -45,7 +41,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -68,7 +64,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -95,7 +91,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -118,7 +114,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -141,7 +137,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -165,7 +161,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -190,7 +186,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -219,11 +215,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -248,7 +247,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -277,11 +276,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -306,7 +308,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -329,7 +331,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -360,11 +362,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/frontier/vm/instructions/keccak.py b/src/ethereum/forks/frontier/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/frontier/vm/instructions/keccak.py +++ b/src/ethereum/forks/frontier/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/frontier/vm/instructions/log.py b/src/ethereum/forks/frontier/vm/instructions/log.py index 76c02e737a4..e3e3ebd7e76 100644 --- a/src/ethereum/forks/frontier/vm/instructions/log.py +++ b/src/ethereum/forks/frontier/vm/instructions/log.py @@ -18,9 +18,7 @@ from ...blocks import Log from .. import Evm from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -58,9 +56,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/frontier/vm/instructions/memory.py b/src/ethereum/forks/frontier/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/frontier/vm/instructions/memory.py +++ b/src/ethereum/forks/frontier/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/frontier/vm/instructions/stack.py b/src/ethereum/forks/frontier/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/frontier/vm/instructions/stack.py +++ b/src/ethereum/forks/frontier/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/frontier/vm/instructions/storage.py b/src/ethereum/forks/frontier/vm/instructions/storage.py index 154b4fd47bb..0b2a1cce8aa 100644 --- a/src/ethereum/forks/frontier/vm/instructions/storage.py +++ b/src/ethereum/forks/frontier/vm/instructions/storage.py @@ -16,10 +16,7 @@ from ...state import get_storage, set_storage from .. import Evm from ..gas import ( - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -40,7 +37,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -71,12 +68,12 @@ def sstore(evm: Evm) -> None: state = evm.message.block_env.state current_value = get_storage(state, evm.message.current_target, key) if new_value != 0 and current_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE if new_value == 0 and current_value != 0: - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/frontier/vm/instructions/system.py b/src/ethereum/forks/frontier/vm/instructions/system.py index 41c3b22d3e2..6426fbfa04c 100644 --- a/src/ethereum/forks/frontier/vm/instructions/system.py +++ b/src/ethereum/forks/frontier/vm/instructions/system.py @@ -32,9 +32,7 @@ incorporate_child_on_success, ) from ..gas import ( - GAS_CREATE, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -67,7 +65,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) create_message_gas = evm.gas_left evm.gas_left = Uint(0) @@ -155,7 +153,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -362,7 +360,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_ZERO + gas_cost = GasCosts.ZERO originator = evm.message.current_target @@ -373,7 +371,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += int(REFUND_SELF_DESTRUCT) + evm.refund_counter += int(GasCosts.REFUND_SELF_DESTRUCT) charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/frontier/vm/interpreter.py b/src/ethereum/forks/frontier/vm/interpreter.py index 842207405fa..90e59a193f0 100644 --- a/src/ethereum/forks/frontier/vm/interpreter.py +++ b/src/ethereum/forks/frontier/vm/interpreter.py @@ -42,7 +42,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -158,7 +158,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/frontier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/frontier/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/frontier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/frontier/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/frontier/vm/precompiled_contracts/identity.py b/src/ethereum/forks/frontier/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/frontier/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/frontier/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/frontier/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/frontier/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/frontier/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/frontier/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/frontier/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/frontier/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/frontier/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/frontier/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/gray_glacier/fork.py b/src/ethereum/forks/gray_glacier/fork.py index 301fdb2cd05..3629b729a31 100644 --- a/src/ethereum/forks/gray_glacier/fork.py +++ b/src/ethereum/forks/gray_glacier/fork.py @@ -62,13 +62,12 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(2 * 10**18) BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) BOMB_DELAY_BLOCKS = 11400000 @@ -850,14 +849,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -873,12 +872,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/gray_glacier/transactions.py b/src/ethereum/forks/gray_glacier/transactions.py index ca951f085c2..0e40010c617 100644 --- a/src/ethereum/forks/gray_glacier/transactions.py +++ b/src/ethereum/forks/gray_glacier/transactions.py @@ -23,37 +23,6 @@ from .exceptions import TransactionTypeError from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -370,7 +339,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -378,27 +347,29 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) access_list_cost = Uint(0) if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) - return GAS_TX_BASE + data_cost + create_cost + access_list_cost + return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/gray_glacier/vm/gas.py b/src/ethereum/forks/gray_glacier/vm/gas.py index 7ac4146d8cf..c33cf7c0487 100644 --- a/src/ethereum/forks/gray_glacier/vm/gas.py +++ b/src/ethereum/forks/gray_glacier/vm/gas.py @@ -22,46 +22,143 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -82,8 +179,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -135,7 +232,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -190,7 +287,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/arithmetic.py b/src/ethereum/forks/gray_glacier/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/bitwise.py b/src/ethereum/forks/gray_glacier/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/bitwise.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/block.py b/src/ethereum/forks/gray_glacier/vm/instructions/block.py index bbf01739ff2..e3400f9461a 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/block.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -203,7 +203,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/comparison.py b/src/ethereum/forks/gray_glacier/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/comparison.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/control_flow.py b/src/ethereum/forks/gray_glacier/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/control_flow.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/environment.py b/src/ethereum/forks/gray_glacier/vm/instructions/environment.py index fe1b70c1269..851ab39b142 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/environment.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/environment.py @@ -22,13 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,10 +67,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -103,7 +97,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -126,7 +120,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -149,7 +143,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -173,7 +167,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -198,7 +192,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -227,11 +221,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -256,7 +253,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -285,11 +282,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -314,7 +314,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -338,10 +338,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -374,16 +374,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -413,7 +413,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -439,11 +439,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -472,10 +477,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -507,7 +512,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -535,7 +540,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/keccak.py b/src/ethereum/forks/gray_glacier/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/keccak.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/log.py b/src/ethereum/forks/gray_glacier/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/log.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/memory.py b/src/ethereum/forks/gray_glacier/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/memory.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/stack.py b/src/ethereum/forks/gray_glacier/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/stack.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/storage.py b/src/ethereum/forks/gray_glacier/vm/instructions/storage.py index d99ad70f93b..287544f353b 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/storage.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/storage.py @@ -17,12 +17,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,10 +39,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -73,7 +68,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -86,37 +81,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/gray_glacier/vm/instructions/system.py b/src/ethereum/forks/gray_glacier/vm/instructions/system.py index b48d2498ac3..55c72f0fa9a 100644 --- a/src/ethereum/forks/gray_glacier/vm/instructions/system.py +++ b/src/ethereum/forks/gray_glacier/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -157,7 +149,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -202,8 +194,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -242,7 +234,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -353,17 +345,17 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -433,12 +425,12 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -491,10 +483,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -503,7 +495,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -570,10 +562,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS message_call_gas = calculate_message_call_gas( U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost @@ -629,10 +621,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to diff --git a/src/ethereum/forks/gray_glacier/vm/interpreter.py b/src/ethereum/forks/gray_glacier/vm/interpreter.py index 1135be95939..434147299b0 100644 --- a/src/ethereum/forks/gray_glacier/vm/interpreter.py +++ b/src/ethereum/forks/gray_glacier/vm/interpreter.py @@ -45,7 +45,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -179,7 +179,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/identity.py b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/gray_glacier/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/homestead/fork.py b/src/ethereum/forks/homestead/fork.py index 162a6bd1b7a..f5e7eb38b5a 100644 --- a/src/ethereum/forks/homestead/fork.py +++ b/src/ethereum/forks/homestead/fork.py @@ -49,11 +49,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(5 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) @@ -700,14 +699,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -723,12 +722,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/homestead/transactions.py b/src/ethereum/forks/homestead/transactions.py index 934540874ca..e17bafae49d 100644 --- a/src/ethereum/forks/homestead/transactions.py +++ b/src/ethereum/forks/homestead/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(68) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(tx: Transaction) -> Address: diff --git a/src/ethereum/forks/homestead/vm/gas.py b/src/ethereum/forks/homestead/vm/gas.py index fc01397ceb0..f3644b8bf6a 100644 --- a/src/ethereum/forks/homestead/vm/gas.py +++ b/src/ethereum/forks/homestead/vm/gas.py @@ -24,43 +24,127 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(50) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(10) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(20) -GAS_BALANCE = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(40) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -REFUND_SELF_DESTRUCT = Uint(24000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(50) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = Uint(24000) + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(68) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(10) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_EXTERNAL_BASE = Uint(20) + OPCODE_BALANCE = Uint(20) + OPCODE_CALL_BASE = Uint(40) @dataclass @@ -81,8 +165,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -134,7 +218,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -205,8 +289,12 @@ def calculate_message_call_gas( message_call_gas: `MessageCallGas` """ - create_gas_cost = Uint(0) if account_exists(state, to) else GAS_NEW_ACCOUNT - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE - cost = GAS_CALL + gas + create_gas_cost + transfer_gas_cost - stipend = gas if value == 0 else GAS_CALL_STIPEND + gas + create_gas_cost = ( + Uint(0) if account_exists(state, to) else GasCosts.NEW_ACCOUNT + ) + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE + cost = ( + GasCosts.OPCODE_CALL_BASE + gas + create_gas_cost + transfer_gas_cost + ) + stipend = gas if value == 0 else GasCosts.CALL_STIPEND + gas return MessageCallGas(cost, stipend) diff --git a/src/ethereum/forks/homestead/vm/instructions/arithmetic.py b/src/ethereum/forks/homestead/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/homestead/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/homestead/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/homestead/vm/instructions/bitwise.py b/src/ethereum/forks/homestead/vm/instructions/bitwise.py index 2a506f55751..62da98041ad 100644 --- a/src/ethereum/forks/homestead/vm/instructions/bitwise.py +++ b/src/ethereum/forks/homestead/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): diff --git a/src/ethereum/forks/homestead/vm/instructions/block.py b/src/ethereum/forks/homestead/vm/instructions/block.py index 0edcbf000d1..fbca7daa37c 100644 --- a/src/ethereum/forks/homestead/vm/instructions/block.py +++ b/src/ethereum/forks/homestead/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) diff --git a/src/ethereum/forks/homestead/vm/instructions/comparison.py b/src/ethereum/forks/homestead/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/homestead/vm/instructions/comparison.py +++ b/src/ethereum/forks/homestead/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/homestead/vm/instructions/control_flow.py b/src/ethereum/forks/homestead/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/homestead/vm/instructions/control_flow.py +++ b/src/ethereum/forks/homestead/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/homestead/vm/instructions/environment.py b/src/ethereum/forks/homestead/vm/instructions/environment.py index 83eb5528226..d930368fdd9 100644 --- a/src/ethereum/forks/homestead/vm/instructions/environment.py +++ b/src/ethereum/forks/homestead/vm/instructions/environment.py @@ -20,11 +20,7 @@ from ...vm.memory import buffer_read, memory_write from .. import Evm from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_COPY, - GAS_EXTERNAL, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -45,7 +41,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -68,7 +64,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -95,7 +91,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -118,7 +114,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -141,7 +137,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -165,7 +161,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -190,7 +186,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -219,11 +215,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -248,7 +247,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -277,11 +276,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -306,7 +308,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -329,7 +331,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -360,11 +362,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/homestead/vm/instructions/keccak.py b/src/ethereum/forks/homestead/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/homestead/vm/instructions/keccak.py +++ b/src/ethereum/forks/homestead/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/homestead/vm/instructions/log.py b/src/ethereum/forks/homestead/vm/instructions/log.py index 76c02e737a4..e3e3ebd7e76 100644 --- a/src/ethereum/forks/homestead/vm/instructions/log.py +++ b/src/ethereum/forks/homestead/vm/instructions/log.py @@ -18,9 +18,7 @@ from ...blocks import Log from .. import Evm from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -58,9 +56,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/homestead/vm/instructions/memory.py b/src/ethereum/forks/homestead/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/homestead/vm/instructions/memory.py +++ b/src/ethereum/forks/homestead/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/homestead/vm/instructions/stack.py b/src/ethereum/forks/homestead/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/homestead/vm/instructions/stack.py +++ b/src/ethereum/forks/homestead/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/homestead/vm/instructions/storage.py b/src/ethereum/forks/homestead/vm/instructions/storage.py index 154b4fd47bb..0b2a1cce8aa 100644 --- a/src/ethereum/forks/homestead/vm/instructions/storage.py +++ b/src/ethereum/forks/homestead/vm/instructions/storage.py @@ -16,10 +16,7 @@ from ...state import get_storage, set_storage from .. import Evm from ..gas import ( - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -40,7 +37,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -71,12 +68,12 @@ def sstore(evm: Evm) -> None: state = evm.message.block_env.state current_value = get_storage(state, evm.message.current_target, key) if new_value != 0 and current_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE if new_value == 0 and current_value != 0: - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/homestead/vm/instructions/system.py b/src/ethereum/forks/homestead/vm/instructions/system.py index 75226650693..c40a241886a 100644 --- a/src/ethereum/forks/homestead/vm/instructions/system.py +++ b/src/ethereum/forks/homestead/vm/instructions/system.py @@ -32,10 +32,7 @@ incorporate_child_on_success, ) from ..gas import ( - GAS_CALL, - GAS_CREATE, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -68,7 +65,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) create_message_gas = evm.gas_left evm.gas_left = Uint(0) @@ -157,7 +154,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -368,7 +365,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_ZERO + gas_cost = GasCosts.ZERO originator = evm.message.current_target @@ -379,7 +376,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += int(REFUND_SELF_DESTRUCT) + evm.refund_counter += int(GasCosts.REFUND_SELF_DESTRUCT) charge_gas(evm, gas_cost) @@ -438,7 +435,7 @@ def delegatecall(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - charge_gas(evm, GAS_CALL + gas + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CALL_BASE + gas + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/homestead/vm/interpreter.py b/src/ethereum/forks/homestead/vm/interpreter.py index 47530fcf783..7d12402e037 100644 --- a/src/ethereum/forks/homestead/vm/interpreter.py +++ b/src/ethereum/forks/homestead/vm/interpreter.py @@ -42,7 +42,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -158,7 +158,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/homestead/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/homestead/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/homestead/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/homestead/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/homestead/vm/precompiled_contracts/identity.py b/src/ethereum/forks/homestead/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/homestead/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/homestead/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/homestead/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/homestead/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/homestead/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/homestead/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/homestead/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/homestead/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/homestead/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/homestead/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/istanbul/fork.py b/src/ethereum/forks/istanbul/fork.py index 7ed470d41e3..7765455cdb8 100644 --- a/src/ethereum/forks/istanbul/fork.py +++ b/src/ethereum/forks/istanbul/fork.py @@ -51,11 +51,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(2 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) BOMB_DELAY_BLOCKS = 5000000 @@ -711,14 +710,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -734,12 +733,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/istanbul/transactions.py b/src/ethereum/forks/istanbul/transactions.py index a831530b311..e8cde82b198 100644 --- a/src/ethereum/forks/istanbul/transactions.py +++ b/src/ethereum/forks/istanbul/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/istanbul/vm/gas.py b/src/ethereum/forks/istanbul/vm/gas.py index 8425495cd13..ba89267f506 100644 --- a/src/ethereum/forks/istanbul/vm/gas.py +++ b/src/ethereum/forks/istanbul/vm/gas.py @@ -22,49 +22,143 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(800) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(700) -GAS_BALANCE = Uint(700) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(700) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -REFUND_SELF_DESTRUCT = 24000 -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_CODE_HASH = Uint(700) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(800) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = 24000 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_EXTCODEHASH = Uint(700) + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) + OPCODE_EXTERNAL_BASE = Uint(700) + OPCODE_BALANCE = Uint(700) + OPCODE_CALL_BASE = Uint(700) @dataclass @@ -85,8 +179,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -138,7 +232,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -193,7 +287,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/istanbul/vm/instructions/arithmetic.py b/src/ethereum/forks/istanbul/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/istanbul/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/istanbul/vm/instructions/bitwise.py b/src/ethereum/forks/istanbul/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/bitwise.py +++ b/src/ethereum/forks/istanbul/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/istanbul/vm/instructions/block.py b/src/ethereum/forks/istanbul/vm/instructions/block.py index bbf01739ff2..e3400f9461a 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/block.py +++ b/src/ethereum/forks/istanbul/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -203,7 +203,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/istanbul/vm/instructions/comparison.py b/src/ethereum/forks/istanbul/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/comparison.py +++ b/src/ethereum/forks/istanbul/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/istanbul/vm/instructions/control_flow.py b/src/ethereum/forks/istanbul/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/control_flow.py +++ b/src/ethereum/forks/istanbul/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/istanbul/vm/instructions/environment.py b/src/ethereum/forks/istanbul/vm/instructions/environment.py index f0cc93e67d8..b3ac54a689a 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/environment.py +++ b/src/ethereum/forks/istanbul/vm/instructions/environment.py @@ -22,14 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_CODE_HASH, - GAS_COPY, - GAS_EXTERNAL, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -50,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,7 +66,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -100,7 +93,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -123,7 +116,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -146,7 +139,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -170,7 +163,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -195,7 +188,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -224,11 +217,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -253,7 +249,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -282,11 +278,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -311,7 +310,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -334,7 +333,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -365,11 +364,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -397,7 +399,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -423,11 +425,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -455,7 +462,7 @@ def extcodehash(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_CODE_HASH) + charge_gas(evm, GasCosts.OPCODE_EXTCODEHASH) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -485,7 +492,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. diff --git a/src/ethereum/forks/istanbul/vm/instructions/keccak.py b/src/ethereum/forks/istanbul/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/keccak.py +++ b/src/ethereum/forks/istanbul/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/istanbul/vm/instructions/log.py b/src/ethereum/forks/istanbul/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/log.py +++ b/src/ethereum/forks/istanbul/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/istanbul/vm/instructions/memory.py b/src/ethereum/forks/istanbul/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/memory.py +++ b/src/ethereum/forks/istanbul/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/istanbul/vm/instructions/stack.py b/src/ethereum/forks/istanbul/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/stack.py +++ b/src/ethereum/forks/istanbul/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/istanbul/vm/instructions/storage.py b/src/ethereum/forks/istanbul/vm/instructions/storage.py index 99beae61e52..c34e6f31912 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/storage.py +++ b/src/ethereum/forks/istanbul/vm/instructions/storage.py @@ -17,11 +17,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -42,7 +38,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -68,7 +64,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -79,30 +75,34 @@ def sstore(evm: Evm) -> None: if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE else: - gas_cost = GAS_SLOAD + gas_cost = GasCosts.SLOAD # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_SLOAD) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.SLOAD + ) else: # Slot was originally non-empty and was UPDATED earlier - evm.refund_counter += int(GAS_COLD_STORAGE_WRITE - GAS_SLOAD) + evm.refund_counter += int( + GasCosts.COLD_STORAGE_WRITE - GasCosts.SLOAD + ) charge_gas(evm, gas_cost) if evm.message.is_static: diff --git a/src/ethereum/forks/istanbul/vm/instructions/system.py b/src/ethereum/forks/istanbul/vm/instructions/system.py index a0b00f24d1e..12f69d1131d 100644 --- a/src/ethereum/forks/istanbul/vm/instructions/system.py +++ b/src/ethereum/forks/istanbul/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL, - GAS_CALL_VALUE, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -157,7 +149,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -202,8 +194,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -242,7 +234,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -352,16 +344,16 @@ def call(evm: Evm) -> None: code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + create_gas_cost + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + create_gas_cost + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) if evm.message.is_static and value != U256(0): @@ -423,13 +415,13 @@ def callcode(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -476,7 +468,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if ( not is_account_alive(evm.message.block_env.state, beneficiary) and get_account( @@ -484,7 +476,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT originator = evm.message.current_target @@ -495,7 +487,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += REFUND_SELF_DESTRUCT + evm.refund_counter += GasCosts.REFUND_SELF_DESTRUCT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -561,7 +553,11 @@ def delegatecall(evm: Evm) -> None: ], ) message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -620,7 +616,7 @@ def staticcall(evm: Evm) -> None: gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) diff --git a/src/ethereum/forks/istanbul/vm/interpreter.py b/src/ethereum/forks/istanbul/vm/interpreter.py index 7a92f7471f3..2e3e5d6af2d 100644 --- a/src/ethereum/forks/istanbul/vm/interpreter.py +++ b/src/ethereum/forks/istanbul/vm/interpreter.py @@ -45,7 +45,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -178,7 +178,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/istanbul/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/istanbul/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/istanbul/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/istanbul/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/istanbul/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/istanbul/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/istanbul/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/istanbul/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/istanbul/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/istanbul/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/istanbul/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/istanbul/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/istanbul/vm/precompiled_contracts/identity.py b/src/ethereum/forks/istanbul/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/istanbul/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/istanbul/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/istanbul/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/istanbul/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/istanbul/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/istanbul/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/istanbul/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/istanbul/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/istanbul/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/istanbul/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/london/fork.py b/src/ethereum/forks/london/fork.py index a095e5fb6b9..622798e552e 100644 --- a/src/ethereum/forks/london/fork.py +++ b/src/ethereum/forks/london/fork.py @@ -62,13 +62,12 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(2 * 10**18) BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) INITIAL_BASE_FEE = Uint(1000000000) MAX_OMMER_DEPTH = Uint(6) @@ -858,14 +857,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -881,12 +880,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/london/transactions.py b/src/ethereum/forks/london/transactions.py index ca951f085c2..0e40010c617 100644 --- a/src/ethereum/forks/london/transactions.py +++ b/src/ethereum/forks/london/transactions.py @@ -23,37 +23,6 @@ from .exceptions import TransactionTypeError from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -370,7 +339,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -378,27 +347,29 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) access_list_cost = Uint(0) if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) - return GAS_TX_BASE + data_cost + create_cost + access_list_cost + return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/london/vm/gas.py b/src/ethereum/forks/london/vm/gas.py index 7ac4146d8cf..c33cf7c0487 100644 --- a/src/ethereum/forks/london/vm/gas.py +++ b/src/ethereum/forks/london/vm/gas.py @@ -22,46 +22,143 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -82,8 +179,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -135,7 +232,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -190,7 +287,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/london/vm/instructions/arithmetic.py b/src/ethereum/forks/london/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/london/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/london/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/london/vm/instructions/bitwise.py b/src/ethereum/forks/london/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/london/vm/instructions/bitwise.py +++ b/src/ethereum/forks/london/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/london/vm/instructions/block.py b/src/ethereum/forks/london/vm/instructions/block.py index bbf01739ff2..e3400f9461a 100644 --- a/src/ethereum/forks/london/vm/instructions/block.py +++ b/src/ethereum/forks/london/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -203,7 +203,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/london/vm/instructions/comparison.py b/src/ethereum/forks/london/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/london/vm/instructions/comparison.py +++ b/src/ethereum/forks/london/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/london/vm/instructions/control_flow.py b/src/ethereum/forks/london/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/london/vm/instructions/control_flow.py +++ b/src/ethereum/forks/london/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/london/vm/instructions/environment.py b/src/ethereum/forks/london/vm/instructions/environment.py index fe1b70c1269..851ab39b142 100644 --- a/src/ethereum/forks/london/vm/instructions/environment.py +++ b/src/ethereum/forks/london/vm/instructions/environment.py @@ -22,13 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,10 +67,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -103,7 +97,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -126,7 +120,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -149,7 +143,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -173,7 +167,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -198,7 +192,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -227,11 +221,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -256,7 +253,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -285,11 +282,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -314,7 +314,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -338,10 +338,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -374,16 +374,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -413,7 +413,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -439,11 +439,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -472,10 +477,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -507,7 +512,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -535,7 +540,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) diff --git a/src/ethereum/forks/london/vm/instructions/keccak.py b/src/ethereum/forks/london/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/london/vm/instructions/keccak.py +++ b/src/ethereum/forks/london/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/london/vm/instructions/log.py b/src/ethereum/forks/london/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/london/vm/instructions/log.py +++ b/src/ethereum/forks/london/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/london/vm/instructions/memory.py b/src/ethereum/forks/london/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/london/vm/instructions/memory.py +++ b/src/ethereum/forks/london/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/london/vm/instructions/stack.py b/src/ethereum/forks/london/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/london/vm/instructions/stack.py +++ b/src/ethereum/forks/london/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/london/vm/instructions/storage.py b/src/ethereum/forks/london/vm/instructions/storage.py index d99ad70f93b..287544f353b 100644 --- a/src/ethereum/forks/london/vm/instructions/storage.py +++ b/src/ethereum/forks/london/vm/instructions/storage.py @@ -17,12 +17,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,10 +39,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -73,7 +68,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -86,37 +81,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/london/vm/instructions/system.py b/src/ethereum/forks/london/vm/instructions/system.py index b48d2498ac3..55c72f0fa9a 100644 --- a/src/ethereum/forks/london/vm/instructions/system.py +++ b/src/ethereum/forks/london/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -157,7 +149,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -202,8 +194,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -242,7 +234,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -353,17 +345,17 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -433,12 +425,12 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -491,10 +483,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -503,7 +495,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -570,10 +562,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS message_call_gas = calculate_message_call_gas( U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost @@ -629,10 +621,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to diff --git a/src/ethereum/forks/london/vm/interpreter.py b/src/ethereum/forks/london/vm/interpreter.py index b49ca7be07f..eb067c2bb4d 100644 --- a/src/ethereum/forks/london/vm/interpreter.py +++ b/src/ethereum/forks/london/vm/interpreter.py @@ -45,7 +45,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -179,7 +179,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/london/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/london/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/london/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/london/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/london/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/london/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/london/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/london/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/london/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/london/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/london/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/london/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/london/vm/precompiled_contracts/identity.py b/src/ethereum/forks/london/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/london/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/london/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/london/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/london/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/london/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/london/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/london/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/london/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/london/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/london/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/muir_glacier/fork.py b/src/ethereum/forks/muir_glacier/fork.py index 22fbdd1d988..dc79ce95617 100644 --- a/src/ethereum/forks/muir_glacier/fork.py +++ b/src/ethereum/forks/muir_glacier/fork.py @@ -51,11 +51,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(2 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) BOMB_DELAY_BLOCKS = 9000000 @@ -713,14 +712,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -736,12 +735,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/muir_glacier/transactions.py b/src/ethereum/forks/muir_glacier/transactions.py index a831530b311..e8cde82b198 100644 --- a/src/ethereum/forks/muir_glacier/transactions.py +++ b/src/ethereum/forks/muir_glacier/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/muir_glacier/vm/gas.py b/src/ethereum/forks/muir_glacier/vm/gas.py index 8425495cd13..ba89267f506 100644 --- a/src/ethereum/forks/muir_glacier/vm/gas.py +++ b/src/ethereum/forks/muir_glacier/vm/gas.py @@ -22,49 +22,143 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(800) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(700) -GAS_BALANCE = Uint(700) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(700) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -REFUND_SELF_DESTRUCT = 24000 -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_CODE_HASH = Uint(700) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(800) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = 24000 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_EXTCODEHASH = Uint(700) + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) + OPCODE_EXTERNAL_BASE = Uint(700) + OPCODE_BALANCE = Uint(700) + OPCODE_CALL_BASE = Uint(700) @dataclass @@ -85,8 +179,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -138,7 +232,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -193,7 +287,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/arithmetic.py b/src/ethereum/forks/muir_glacier/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/bitwise.py b/src/ethereum/forks/muir_glacier/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/bitwise.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/block.py b/src/ethereum/forks/muir_glacier/vm/instructions/block.py index bbf01739ff2..e3400f9461a 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/block.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -203,7 +203,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/comparison.py b/src/ethereum/forks/muir_glacier/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/comparison.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/control_flow.py b/src/ethereum/forks/muir_glacier/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/control_flow.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/environment.py b/src/ethereum/forks/muir_glacier/vm/instructions/environment.py index f0cc93e67d8..b3ac54a689a 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/environment.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/environment.py @@ -22,14 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_CODE_HASH, - GAS_COPY, - GAS_EXTERNAL, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -50,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,7 +66,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -100,7 +93,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -123,7 +116,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -146,7 +139,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -170,7 +163,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -195,7 +188,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -224,11 +217,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -253,7 +249,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -282,11 +278,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -311,7 +310,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -334,7 +333,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -365,11 +364,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -397,7 +399,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -423,11 +425,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -455,7 +462,7 @@ def extcodehash(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_CODE_HASH) + charge_gas(evm, GasCosts.OPCODE_EXTCODEHASH) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -485,7 +492,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/keccak.py b/src/ethereum/forks/muir_glacier/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/keccak.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/log.py b/src/ethereum/forks/muir_glacier/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/log.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/memory.py b/src/ethereum/forks/muir_glacier/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/memory.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/stack.py b/src/ethereum/forks/muir_glacier/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/stack.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/storage.py b/src/ethereum/forks/muir_glacier/vm/instructions/storage.py index 99beae61e52..c34e6f31912 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/storage.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/storage.py @@ -17,11 +17,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -42,7 +38,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -68,7 +64,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -79,30 +75,34 @@ def sstore(evm: Evm) -> None: if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE else: - gas_cost = GAS_SLOAD + gas_cost = GasCosts.SLOAD # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_SLOAD) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.SLOAD + ) else: # Slot was originally non-empty and was UPDATED earlier - evm.refund_counter += int(GAS_COLD_STORAGE_WRITE - GAS_SLOAD) + evm.refund_counter += int( + GasCosts.COLD_STORAGE_WRITE - GasCosts.SLOAD + ) charge_gas(evm, gas_cost) if evm.message.is_static: diff --git a/src/ethereum/forks/muir_glacier/vm/instructions/system.py b/src/ethereum/forks/muir_glacier/vm/instructions/system.py index a0b00f24d1e..12f69d1131d 100644 --- a/src/ethereum/forks/muir_glacier/vm/instructions/system.py +++ b/src/ethereum/forks/muir_glacier/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL, - GAS_CALL_VALUE, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -157,7 +149,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -202,8 +194,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -242,7 +234,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -352,16 +344,16 @@ def call(evm: Evm) -> None: code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + create_gas_cost + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + create_gas_cost + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) if evm.message.is_static and value != U256(0): @@ -423,13 +415,13 @@ def callcode(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -476,7 +468,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if ( not is_account_alive(evm.message.block_env.state, beneficiary) and get_account( @@ -484,7 +476,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT originator = evm.message.current_target @@ -495,7 +487,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += REFUND_SELF_DESTRUCT + evm.refund_counter += GasCosts.REFUND_SELF_DESTRUCT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -561,7 +553,11 @@ def delegatecall(evm: Evm) -> None: ], ) message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -620,7 +616,7 @@ def staticcall(evm: Evm) -> None: gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) diff --git a/src/ethereum/forks/muir_glacier/vm/interpreter.py b/src/ethereum/forks/muir_glacier/vm/interpreter.py index e4f53153ce9..66db7006918 100644 --- a/src/ethereum/forks/muir_glacier/vm/interpreter.py +++ b/src/ethereum/forks/muir_glacier/vm/interpreter.py @@ -45,7 +45,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -178,7 +178,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/identity.py b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/muir_glacier/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/osaka/fork.py b/src/ethereum/forks/osaka/fork.py index 7e6b5ee46de..19ce50f243d 100644 --- a/src/ethereum/forks/osaka/fork.py +++ b/src/ethereum/forks/osaka/fork.py @@ -81,8 +81,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( - BLOB_SCHEDULE_MAX, - GAS_PER_BLOB, + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -92,15 +91,13 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB +MAX_BLOB_GAS_PER_BLOCK = GasCosts.BLOB_SCHEDULE_MAX * GasCosts.PER_BLOB VERSIONED_HASH_VERSION_KZG = b"\x01" WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address( @@ -1030,14 +1027,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1053,12 +1050,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/osaka/transactions.py b/src/ethereum/forks/osaka/transactions.py index c8f1826324e..486b21f99b0 100644 --- a/src/ethereum/forks/osaka/transactions.py +++ b/src/ethereum/forks/osaka/transactions.py @@ -28,43 +28,6 @@ ) from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - TX_MAX_GAS_LIMIT = Uint(16_777_216) @@ -601,7 +564,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -612,8 +575,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -621,31 +583,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/osaka/vm/eoa_delegation.py b/src/ethereum/forks/osaka/vm/eoa_delegation.py index ff4aca94087..474ca9ae033 100644 --- a/src/ethereum/forks/osaka/vm/eoa_delegation.py +++ b/src/ethereum/forks/osaka/vm/eoa_delegation.py @@ -22,14 +22,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -148,10 +147,10 @@ def access_delegation( address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code = get_code(state, get_account(state, address).code_hash) return True, address, code, access_gas_cost @@ -200,7 +199,8 @@ def set_delegation(message: Message) -> U256: if account_exists(state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/osaka/vm/gas.py b/src/ethereum/forks/osaka/vm/gas.py index 99ccfb48145..e54f305e45c 100644 --- a/src/ethereum/forks/osaka/vm/gas.py +++ b/src/ethereum/forks/osaka/vm/gas.py @@ -24,65 +24,169 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_P256VERIFY = Uint(6900) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(6) -BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET -BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(9) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_P256VERIFY = Uint(6900) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_SCHEDULE_TARGET = U64(6) + BLOB_TARGET_GAS_PER_BLOCK = PER_BLOB * BLOB_SCHEDULE_TARGET + BLOB_BASE_COST = Uint(2**13) + BLOB_SCHEDULE_MAX = U64(9) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_CLZ = LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -103,8 +207,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -156,7 +260,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -211,7 +315,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -283,7 +387,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -314,21 +418,23 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: base_fee_per_gas = parent_header.base_fee_per_gas parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - target_blob_gas_price = Uint(GAS_PER_BLOB) + target_blob_gas_price = Uint(GasCosts.PER_BLOB) target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) - base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas + base_blob_tx_price = GasCosts.BLOB_BASE_COST * base_fee_per_gas if base_blob_tx_price > target_blob_gas_price: - blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET + blob_schedule_delta = ( + GasCosts.BLOB_SCHEDULE_MAX - GasCosts.BLOB_SCHEDULE_TARGET + ) return ( excess_blob_gas - + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX + + blob_gas_used * blob_schedule_delta // GasCosts.BLOB_SCHEDULE_MAX ) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -347,7 +453,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -368,9 +474,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/osaka/vm/instructions/arithmetic.py b/src/ethereum/forks/osaka/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/osaka/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/osaka/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_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 cc6fa2fbb23..7674d3c720f 100644 --- a/src/ethereum/forks/osaka/vm/instructions/bitwise.py +++ b/src/ethereum/forks/osaka/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_LOW, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: @@ -262,7 +265,7 @@ def count_leading_zeros(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_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 43be9e58e23..d0aa17fe959 100644 --- a/src/ethereum/forks/osaka/vm/instructions/block.py +++ b/src/ethereum/forks/osaka/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_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 a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/osaka/vm/instructions/comparison.py +++ b/src/ethereum/forks/osaka/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_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 b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/osaka/vm/instructions/control_flow.py +++ b/src/ethereum/forks/osaka/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/osaka/vm/instructions/environment.py b/src/ethereum/forks/osaka/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/osaka/vm/instructions/environment.py +++ b/src/ethereum/forks/osaka/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_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 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/osaka/vm/instructions/keccak.py +++ b/src/ethereum/forks/osaka/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + 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 abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/osaka/vm/instructions/log.py +++ b/src/ethereum/forks/osaka/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_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 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/osaka/vm/instructions/memory.py +++ b/src/ethereum/forks/osaka/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + 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 0007a28acd4..366cf79f5e4 100644 --- a/src/ethereum/forks/osaka/vm/instructions/stack.py +++ b/src/ethereum/forks/osaka/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -63,9 +66,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +98,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +130,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) 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 fd5bf4572ff..a782cd0db25 100644 --- a/src/ethereum/forks/osaka/vm/instructions/storage.py +++ b/src/ethereum/forks/osaka/vm/instructions/storage.py @@ -23,12 +23,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -50,10 +45,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +74,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +87,36 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: - # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: - # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: - # Storage slot being restored to its original value if original_value == 0: - # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: - # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +143,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +170,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) 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 29c3fe9e6e2..0708c9041e2 100644 --- a/src/ethereum/forks/osaka/vm/instructions/system.py +++ b/src/ethereum/forks/osaka/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +158,10 @@ 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, + GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,8 +211,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -261,7 +256,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -374,10 +369,10 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( @@ -388,10 +383,10 @@ def call(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -463,10 +458,10 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -476,7 +471,7 @@ def callcode(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -489,7 +484,8 @@ def callcode(evm: Evm) -> None: # OPERATION evm.memory += b"\x00" * extend_memory.expand_by sender_balance = get_account( - evm.message.block_env.state, evm.message.current_target + evm.message.block_env.state, + evm.message.current_target, ).balance if sender_balance < value: push(evm.stack, U256(0)) @@ -531,19 +527,20 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) and get_account( - evm.message.block_env.state, evm.message.current_target + evm.message.block_env.state, + evm.message.current_target, ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -604,10 +601,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -618,7 +615,11 @@ def delegatecall(evm: Evm) -> None: access_gas_cost += delegated_access_gas_cost message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + access_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -673,10 +674,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( diff --git a/src/ethereum/forks/osaka/vm/interpreter.py b/src/ethereum/forks/osaka/vm/interpreter.py index bdbf6520cc7..b956f824d0e 100644 --- a/src/ethereum/forks/osaka/vm/interpreter.py +++ b/src/ethereum/forks/osaka/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -191,7 +191,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..9d8c71b806d 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,10 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas( + evm, + GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds, + ) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..fa0d3ec4c2d 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -60,7 +58,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1ADD)) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +99,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +138,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1MAP)) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..a5b2be04018 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -61,7 +59,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2ADD)) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +100,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +139,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2MAP)) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/identity.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/p256verify.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/p256verify.py index e35ea1bb4ec..29c2e91e0f0 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/p256verify.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/p256verify.py @@ -24,7 +24,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_P256VERIFY, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -41,7 +41,7 @@ def p256verify(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_P256VERIFY) + charge_gas(evm, GasCosts.PRECOMPILE_P256VERIFY) if len(data) != 160: return diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/osaka/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/osaka/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/osaka/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/osaka/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/paris/fork.py b/src/ethereum/forks/paris/fork.py index 601f7064cfb..46202fa5a8e 100644 --- a/src/ethereum/forks/paris/fork.py +++ b/src/ethereum/forks/paris/fork.py @@ -57,12 +57,11 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) @@ -617,14 +616,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -640,12 +639,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/paris/transactions.py b/src/ethereum/forks/paris/transactions.py index 3b2f8b4425f..7ee0abbf8ef 100644 --- a/src/ethereum/forks/paris/transactions.py +++ b/src/ethereum/forks/paris/transactions.py @@ -23,37 +23,6 @@ from .exceptions import TransactionTypeError -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -370,7 +339,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -378,27 +347,29 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) access_list_cost = Uint(0) if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) - return GAS_TX_BASE + data_cost + create_cost + access_list_cost + return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/paris/vm/gas.py b/src/ethereum/forks/paris/vm/gas.py index 7ac4146d8cf..d4536445c43 100644 --- a/src/ethereum/forks/paris/vm/gas.py +++ b/src/ethereum/forks/paris/vm/gas.py @@ -22,46 +22,143 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -82,8 +179,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -135,7 +232,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -190,7 +287,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/paris/vm/instructions/arithmetic.py b/src/ethereum/forks/paris/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/paris/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/paris/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/paris/vm/instructions/bitwise.py b/src/ethereum/forks/paris/vm/instructions/bitwise.py index 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/paris/vm/instructions/bitwise.py +++ b/src/ethereum/forks/paris/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/paris/vm/instructions/block.py b/src/ethereum/forks/paris/vm/instructions/block.py index 3aa1fb2f6b6..19216cef9d5 100644 --- a/src/ethereum/forks/paris/vm/instructions/block.py +++ b/src/ethereum/forks/paris/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/paris/vm/instructions/comparison.py b/src/ethereum/forks/paris/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/paris/vm/instructions/comparison.py +++ b/src/ethereum/forks/paris/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/paris/vm/instructions/control_flow.py b/src/ethereum/forks/paris/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/paris/vm/instructions/control_flow.py +++ b/src/ethereum/forks/paris/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/paris/vm/instructions/environment.py b/src/ethereum/forks/paris/vm/instructions/environment.py index ba2bb42a425..588022b5722 100644 --- a/src/ethereum/forks/paris/vm/instructions/environment.py +++ b/src/ethereum/forks/paris/vm/instructions/environment.py @@ -22,13 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,10 +67,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -103,7 +97,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -126,7 +120,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -149,7 +143,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -173,7 +167,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -198,7 +192,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -227,11 +221,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -256,7 +253,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -285,11 +282,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -314,7 +314,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -338,10 +338,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -374,16 +374,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -413,7 +413,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -439,11 +439,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -472,10 +477,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -507,7 +512,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -535,7 +540,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) diff --git a/src/ethereum/forks/paris/vm/instructions/keccak.py b/src/ethereum/forks/paris/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/paris/vm/instructions/keccak.py +++ b/src/ethereum/forks/paris/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/paris/vm/instructions/log.py b/src/ethereum/forks/paris/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/paris/vm/instructions/log.py +++ b/src/ethereum/forks/paris/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/paris/vm/instructions/memory.py b/src/ethereum/forks/paris/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/paris/vm/instructions/memory.py +++ b/src/ethereum/forks/paris/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/paris/vm/instructions/stack.py b/src/ethereum/forks/paris/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/paris/vm/instructions/stack.py +++ b/src/ethereum/forks/paris/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/paris/vm/instructions/storage.py b/src/ethereum/forks/paris/vm/instructions/storage.py index d99ad70f93b..287544f353b 100644 --- a/src/ethereum/forks/paris/vm/instructions/storage.py +++ b/src/ethereum/forks/paris/vm/instructions/storage.py @@ -17,12 +17,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,10 +39,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -73,7 +68,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -86,37 +81,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/paris/vm/instructions/system.py b/src/ethereum/forks/paris/vm/instructions/system.py index 2e9a8766a1e..01791beb50f 100644 --- a/src/ethereum/forks/paris/vm/instructions/system.py +++ b/src/ethereum/forks/paris/vm/instructions/system.py @@ -39,15 +39,7 @@ ) from ..exceptions import Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -156,7 +148,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -201,8 +193,8 @@ def create2(evm: Evm) -> None: call_data_words = ceil32(Uint(memory_size)) // Uint(32) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost, ) @@ -241,7 +233,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -352,17 +344,17 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -432,12 +424,12 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -490,10 +482,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -502,7 +494,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -565,10 +557,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS message_call_gas = calculate_message_call_gas( U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost @@ -624,10 +616,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to diff --git a/src/ethereum/forks/paris/vm/interpreter.py b/src/ethereum/forks/paris/vm/interpreter.py index 92af867690a..32cb2e3b4de 100644 --- a/src/ethereum/forks/paris/vm/interpreter.py +++ b/src/ethereum/forks/paris/vm/interpreter.py @@ -43,7 +43,7 @@ set_code, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -167,7 +167,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/paris/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/paris/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/paris/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/paris/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/paris/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/paris/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/paris/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/paris/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/paris/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/paris/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/paris/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/paris/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/paris/vm/precompiled_contracts/identity.py b/src/ethereum/forks/paris/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/paris/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/paris/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/paris/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/paris/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/paris/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/paris/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/paris/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/paris/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/paris/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/paris/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/prague/fork.py b/src/ethereum/forks/prague/fork.py index b1189cfa75e..9a14a702850 100644 --- a/src/ethereum/forks/prague/fork.py +++ b/src/ethereum/forks/prague/fork.py @@ -80,6 +80,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( + GasCosts, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -89,8 +90,6 @@ BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( @@ -1013,14 +1012,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -1036,12 +1035,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/prague/transactions.py b/src/ethereum/forks/prague/transactions.py index 485a2460ba4..48845de1aa6 100644 --- a/src/ethereum/forks/prague/transactions.py +++ b/src/ethereum/forks/prague/transactions.py @@ -24,43 +24,6 @@ from .exceptions import InitCodeTooLargeError, TransactionTypeError from .fork_types import Authorization, VersionedHash -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_TOKEN_FLOOR = Uint(10) -""" -Minimum gas cost per byte of calldata as per [EIP-7623]. Used to calculate -the minimum gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_DATA_TOKEN_STANDARD = Uint(4) -""" -Gas cost per byte of calldata as per [EIP-7623]. Used to calculate the -gas cost for transactions that include calldata. - -[EIP-7623]: https://eips.ethereum.org/EIPS/eip-7623 -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -593,7 +556,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -604,8 +567,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size. """ - from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros @@ -613,31 +575,33 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]: tokens_in_calldata = num_zeros + num_non_zeros * Uint(4) # EIP-7623 floor price (note: no EVM costs) calldata_floor_gas_cost = ( - tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE + tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE ) - data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD + data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if has_access_list(tx): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) auth_cost = Uint(0) if isinstance(tx, SetCodeTransaction): - auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)) + auth_cost += Uint( + GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations) + ) return ( Uint( - GAS_TX_BASE + GasCosts.TX_BASE + data_cost + create_cost + access_list_cost diff --git a/src/ethereum/forks/prague/vm/eoa_delegation.py b/src/ethereum/forks/prague/vm/eoa_delegation.py index fce580bee4a..3fd42910817 100644 --- a/src/ethereum/forks/prague/vm/eoa_delegation.py +++ b/src/ethereum/forks/prague/vm/eoa_delegation.py @@ -22,14 +22,13 @@ set_code, ) from ..utils.hexadecimal import hex_to_address -from ..vm.gas import GAS_COLD_ACCOUNT_ACCESS, GAS_WARM_ACCESS +from ..vm.gas import GasCosts from . import Evm, Message SET_CODE_TX_MAGIC = b"\x05" EOA_DELEGATION_MARKER = b"\xef\x01\x00" EOA_DELEGATION_MARKER_LENGTH = len(EOA_DELEGATION_MARKER) EOA_DELEGATED_CODE_LENGTH = 23 -GAS_AUTH_PER_EMPTY_ACCOUNT = 25000 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12500 NULL_ADDRESS = hex_to_address("0x0000000000000000000000000000000000000000") @@ -147,10 +146,10 @@ def access_delegation( address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code = get_code(state, get_account(state, address).code_hash) return True, address, code, access_gas_cost @@ -199,7 +198,8 @@ def set_delegation(message: Message) -> U256: if account_exists(state, authority): refund_counter += U256( - GAS_AUTH_PER_EMPTY_ACCOUNT - REFUND_AUTH_PER_EXISTING_ACCOUNT + GasCosts.AUTH_PER_EMPTY_ACCOUNT + - REFUND_AUTH_PER_EXISTING_ACCOUNT ) if auth.address == NULL_ADDRESS: diff --git a/src/ethereum/forks/prague/vm/gas.py b/src/ethereum/forks/prague/vm/gas.py index 121292173ef..94352384934 100644 --- a/src/ethereum/forks/prague/vm/gas.py +++ b/src/ethereum/forks/prague/vm/gas.py @@ -24,61 +24,164 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) -GAS_BLOBHASH_OPCODE = Uint(3) -GAS_PRECOMPILE_POINT_EVALUATION = Uint(50000) - -GAS_PER_BLOB = U64(2**17) -BLOB_TARGET_GAS_PER_BLOCK = U64(786432) -BLOB_MIN_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716) - -GAS_PRECOMPILE_BLS_G1ADD = Uint(375) -GAS_PRECOMPILE_BLS_G1MUL = Uint(12000) -GAS_PRECOMPILE_BLS_G1MAP = Uint(5500) -GAS_PRECOMPILE_BLS_G2ADD = Uint(600) -GAS_PRECOMPILE_BLS_G2MUL = Uint(22500) -GAS_PRECOMPILE_BLS_G2MAP = Uint(23800) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Authorization + AUTH_PER_EMPTY_ACCOUNT = 25000 + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_POINT_EVALUATION = Uint(50000) + PRECOMPILE_BLS_G1ADD = Uint(375) + PRECOMPILE_BLS_G1MUL = Uint(12000) + PRECOMPILE_BLS_G1MAP = Uint(5500) + PRECOMPILE_BLS_G2ADD = Uint(600) + PRECOMPILE_BLS_G2MUL = Uint(22500) + PRECOMPILE_BLS_G2MAP = Uint(23800) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Blobs + PER_BLOB = U64(2**17) + BLOB_TARGET_GAS_PER_BLOCK = U64(786432) + BLOB_MIN_GASPRICE = Uint(1) + BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_TOKEN_STANDARD = Uint(4) + TX_DATA_TOKEN_FLOOR = Uint(10) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_BLOBBASEFEE = BASE + OPCODE_BLOBHASH = Uint(3) + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MCOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -99,8 +202,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -152,7 +255,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -207,7 +310,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -279,7 +382,7 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) def calculate_excess_blob_gas(parent_header: Header) -> U64: @@ -308,10 +411,10 @@ def calculate_excess_blob_gas(parent_header: Header) -> U64: blob_gas_used = parent_header.blob_gas_used parent_blob_gas = excess_blob_gas + blob_gas_used - if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: + if parent_blob_gas < GasCosts.BLOB_TARGET_GAS_PER_BLOCK: return U64(0) - return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK + return parent_blob_gas - GasCosts.BLOB_TARGET_GAS_PER_BLOCK def calculate_total_blob_gas(tx: Transaction) -> U64: @@ -330,7 +433,7 @@ def calculate_total_blob_gas(tx: Transaction) -> U64: """ if isinstance(tx, BlobTransaction): - return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) + return GasCosts.PER_BLOB * U64(len(tx.blob_versioned_hashes)) else: return U64(0) @@ -351,9 +454,9 @@ def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint: """ return taylor_exponential( - BLOB_MIN_GASPRICE, + GasCosts.BLOB_MIN_GASPRICE, Uint(excess_blob_gas), - BLOB_BASE_FEE_UPDATE_FRACTION, + GasCosts.BLOB_BASE_FEE_UPDATE_FRACTION, ) diff --git a/src/ethereum/forks/prague/vm/instructions/arithmetic.py b/src/ethereum/forks/prague/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/prague/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/prague/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_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 41dabe8185b..1de6c615931 100644 --- a/src/ethereum/forks/prague/vm/instructions/bitwise.py +++ b/src/ethereum/forks/prague/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +172,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +202,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +232,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_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 b3bfb500a09..4c405ad5194 100644 --- a/src/ethereum/forks/prague/vm/instructions/block.py +++ b/src/ethereum/forks/prague/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_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 a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/prague/vm/instructions/comparison.py +++ b/src/ethereum/forks/prague/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_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 b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/prague/vm/instructions/control_flow.py +++ b/src/ethereum/forks/prague/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/prague/vm/instructions/environment.py b/src/ethereum/forks/prague/vm/instructions/environment.py index 5848530a960..7fa57b90d8b 100644 --- a/src/ethereum/forks/prague/vm/instructions/environment.py +++ b/src/ethereum/forks/prague/vm/instructions/environment.py @@ -23,14 +23,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_BLOBHASH_OPCODE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_blob_gas_price, calculate_gas_extend_memory, charge_gas, @@ -52,7 +45,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -76,10 +69,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -106,7 +99,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -129,7 +122,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -152,7 +145,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -176,7 +169,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -201,7 +194,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -230,11 +223,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -259,7 +255,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -288,11 +284,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -317,7 +316,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -341,10 +340,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -377,16 +376,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -416,7 +415,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -442,11 +441,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -475,10 +479,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -510,7 +514,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -538,7 +542,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) @@ -561,7 +565,7 @@ def blob_hash(evm: Evm) -> None: index = pop(evm.stack) # GAS - charge_gas(evm, GAS_BLOBHASH_OPCODE) + charge_gas(evm, GasCosts.OPCODE_BLOBHASH) # OPERATION if int(index) < len(evm.message.tx_env.blob_versioned_hashes): @@ -588,7 +592,7 @@ def blob_base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_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 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/prague/vm/instructions/keccak.py +++ b/src/ethereum/forks/prague/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + 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 abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/prague/vm/instructions/log.py +++ b/src/ethereum/forks/prague/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_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 6e111051ee3..bba3ddf19d5 100644 --- a/src/ethereum/forks/prague/vm/instructions/memory.py +++ b/src/ethereum/forks/prague/vm/instructions/memory.py @@ -18,9 +18,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_COPY, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +47,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -80,7 +78,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -108,7 +106,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -135,7 +133,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) @@ -161,12 +159,15 @@ def mcopy(evm: Evm) -> None: # GAS words = ceil32(Uint(length)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_MCOPY_BASE + 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 0007a28acd4..366cf79f5e4 100644 --- a/src/ethereum/forks/prague/vm/instructions/stack.py +++ b/src/ethereum/forks/prague/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -63,9 +66,9 @@ def push_n(evm: Evm, num_bytes: int) -> None: # GAS if num_bytes == 0: - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -95,7 +98,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -127,7 +130,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) 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 fd5bf4572ff..5aa3cc6746f 100644 --- a/src/ethereum/forks/prague/vm/instructions/storage.py +++ b/src/ethereum/forks/prague/vm/instructions/storage.py @@ -23,12 +23,7 @@ from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -50,10 +45,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -79,7 +74,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -92,37 +87,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) @@ -149,7 +148,7 @@ def tload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) # OPERATION value = get_transient_storage( @@ -176,7 +175,7 @@ def tstore(evm: Evm) -> None: new_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) 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 29c3fe9e6e2..2d99ac93e61 100644 --- a/src/ethereum/forks/prague/vm/instructions/system.py +++ b/src/ethereum/forks/prague/vm/instructions/system.py @@ -40,15 +40,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -166,7 +158,9 @@ 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, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -216,8 +210,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -261,7 +255,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -374,10 +368,10 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( @@ -388,10 +382,10 @@ def call(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -463,10 +457,10 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -476,7 +470,7 @@ def callcode(evm: Evm) -> None: ) = access_delegation(evm, code_address) access_gas_cost += delegated_access_gas_cost - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -531,10 +525,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -543,7 +537,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -604,10 +598,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS ( disable_precompiles, @@ -673,10 +667,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to ( diff --git a/src/ethereum/forks/prague/vm/interpreter.py b/src/ethereum/forks/prague/vm/interpreter.py index 290f2831710..fd41c59a310 100644 --- a/src/ethereum/forks/prague/vm/interpreter.py +++ b/src/ethereum/forks/prague/vm/interpreter.py @@ -46,7 +46,7 @@ ) from ..vm import Message from ..vm.eoa_delegation import get_delegated_code_address, set_delegation -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -191,7 +191,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/prague/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/prague/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g1.py b/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g1.py index 9c03c820465..fa0d3ec4c2d 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g1.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g1.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G1ADD, - GAS_PRECOMPILE_BLS_G1MAP, - GAS_PRECOMPILE_BLS_G1MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -60,7 +58,7 @@ def bls12_g1_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1ADD)) # OPERATION p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128))) @@ -101,7 +99,7 @@ def bls12_g1_msm(evm: Evm) -> None: else: discount = Uint(G1_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G1MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -140,7 +138,7 @@ def bls12_map_fp_to_g1(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G1MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G1MAP)) # OPERATION fp = int.from_bytes(data, "big") diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g2.py b/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g2.py index 7a80d78b10c..a5b2be04018 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g2.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/bls12_381/bls12_381_g2.py @@ -21,9 +21,7 @@ from ....vm import Evm from ....vm.gas import ( - GAS_PRECOMPILE_BLS_G2ADD, - GAS_PRECOMPILE_BLS_G2MAP, - GAS_PRECOMPILE_BLS_G2MUL, + GasCosts, charge_gas, ) from ....vm.memory import buffer_read @@ -61,7 +59,7 @@ def bls12_g2_add(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2ADD)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2ADD)) # OPERATION p1 = bytes_to_g2(buffer_read(data, U256(0), U256(256))) @@ -102,7 +100,7 @@ def bls12_g2_msm(evm: Evm) -> None: else: discount = Uint(G2_MAX_DISCOUNT) - gas_cost = Uint(k) * GAS_PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER + gas_cost = Uint(k) * GasCosts.PRECOMPILE_BLS_G2MUL * discount // MULTIPLIER charge_gas(evm, gas_cost) # OPERATION @@ -141,7 +139,7 @@ def bls12_map_fp2_to_g2(evm: Evm) -> None: raise InvalidParameter("Invalid Input Length") # GAS - charge_gas(evm, Uint(GAS_PRECOMPILE_BLS_G2MAP)) + charge_gas(evm, Uint(GasCosts.PRECOMPILE_BLS_G2MAP)) # OPERATION field_element = bytes_to_fq2(data) diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/prague/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/identity.py b/src/ethereum/forks/prague/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/point_evaluation.py b/src/ethereum/forks/prague/vm/precompiled_contracts/point_evaluation.py index ce1d022d049..d2d105ba13b 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/point_evaluation.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/point_evaluation.py @@ -22,7 +22,7 @@ from ...vm import Evm from ...vm.exceptions import KZGProofError -from ...vm.gas import GAS_PRECOMPILE_POINT_EVALUATION, charge_gas +from ...vm.gas import GasCosts, charge_gas FIELD_ELEMENTS_PER_BLOB = 4096 BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # noqa: E501 @@ -51,7 +51,7 @@ def point_evaluation(evm: Evm) -> None: proof = Bytes48(data[144:192]) # GAS - charge_gas(evm, GAS_PRECOMPILE_POINT_EVALUATION) + charge_gas(evm, GasCosts.PRECOMPILE_POINT_EVALUATION) if kzg_commitment_to_versioned_hash(commitment) != versioned_hash: raise KZGProofError diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/prague/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/prague/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/prague/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/prague/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/prague/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/shanghai/fork.py b/src/ethereum/forks/shanghai/fork.py index ed186933edf..804d9894155 100644 --- a/src/ethereum/forks/shanghai/fork.py +++ b/src/ethereum/forks/shanghai/fork.py @@ -58,12 +58,11 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) @@ -652,14 +651,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -675,12 +674,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/shanghai/transactions.py b/src/ethereum/forks/shanghai/transactions.py index 871782b3a73..459c70cb23c 100644 --- a/src/ethereum/forks/shanghai/transactions.py +++ b/src/ethereum/forks/shanghai/transactions.py @@ -23,37 +23,6 @@ from .exceptions import InitCodeTooLargeError, TransactionTypeError -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(16) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - -GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400) -""" -Gas cost for including an address in the access list of a transaction. -""" - -GAS_TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) -""" -Gas cost for including a storage key in the access list of a transaction. -""" - @slotted_freezable @dataclass @@ -380,7 +349,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) 4. Cost for access list entries (if applicable) @@ -388,29 +357,29 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ - from .vm.gas import init_code_cost + from .vm.gas import GasCosts, init_code_cost num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data)) + create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data)) else: create_cost = Uint(0) access_list_cost = Uint(0) if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): for access in tx.access_list: - access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS + access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS access_list_cost += ( - ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY + ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY ) - return GAS_TX_BASE + data_cost + create_cost + access_list_cost + return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/shanghai/vm/gas.py b/src/ethereum/forks/shanghai/vm/gas.py index 44d049d552f..ca3de745672 100644 --- a/src/ethereum/forks/shanghai/vm/gas.py +++ b/src/ethereum/forks/shanghai/vm/gas.py @@ -22,47 +22,145 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 4800 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) -GAS_RETURN_DATA_COPY = Uint(3) -GAS_FAST_STEP = Uint(5) -GAS_PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) -GAS_COLD_STORAGE_ACCESS = Uint(2100) -GAS_COLD_ACCOUNT_ACCESS = Uint(2600) -GAS_WARM_ACCESS = Uint(100) -GAS_CODE_INIT_PER_WORD = Uint(2) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + WARM_ACCESS = Uint(100) + COLD_ACCOUNT_ACCESS = Uint(2600) + COLD_STORAGE_ACCESS = Uint(2100) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + CODE_INIT_PER_WORD = Uint(2) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + FAST_STEP = Uint(5) + + # Refunds + REFUND_STORAGE_CLEAR = 4800 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) + PRECOMPILE_ECADD = Uint(150) + PRECOMPILE_ECMUL = Uint(6000) + PRECOMPILE_ECPAIRING_BASE = Uint(45000) + PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(16) + TX_ACCESS_LIST_ADDRESS = Uint(2400) + TX_ACCESS_LIST_STORAGE_KEY = Uint(1900) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_SHL = VERY_LOW + OPCODE_SHR = VERY_LOW + OPCODE_SAR = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_PREVRANDAO = BASE + OPCODE_RETURNDATASIZE = BASE + OPCODE_CHAINID = BASE + OPCODE_BASEFEE = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_PUSH0 = BASE + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_RETURNDATACOPY_BASE = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) @dataclass @@ -83,8 +181,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -136,7 +234,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -191,7 +289,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) @@ -263,4 +361,4 @@ def init_code_cost(init_code_length: Uint) -> Uint: The gas to be charged for the init code. """ - return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) + return GasCosts.CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) diff --git a/src/ethereum/forks/shanghai/vm/instructions/arithmetic.py b/src/ethereum/forks/shanghai/vm/instructions/arithmetic.py index b7b1a370ad4..c361db7373f 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/shanghai/vm/instructions/arithmetic.py @@ -17,14 +17,7 @@ from ethereum.utils.numeric import get_sign from .. import Evm -from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, - charge_gas, -) +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -44,7 +37,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +64,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +91,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +118,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +151,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +184,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +214,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +245,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +276,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +311,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +341,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/shanghai/vm/instructions/bitwise.py b/src/ethereum/forks/shanghai/vm/instructions/bitwise.py index 41dabe8185b..99b62433076 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/bitwise.py +++ b/src/ethereum/forks/shanghai/vm/instructions/bitwise.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 GasCosts, charge_gas from ..stack import pop, push @@ -34,7 +34,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +59,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +84,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +108,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +134,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): @@ -169,7 +169,7 @@ def bitwise_shl(evm: Evm) -> None: value = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHL) # OPERATION if shift < Uint(256): @@ -199,7 +199,7 @@ def bitwise_shr(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SHR) # OPERATION if shift < U256(256): @@ -229,7 +229,7 @@ def bitwise_sar(evm: Evm) -> None: signed_value = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SAR) # OPERATION if shift < 256: diff --git a/src/ethereum/forks/shanghai/vm/instructions/block.py b/src/ethereum/forks/shanghai/vm/instructions/block.py index de2569869bd..cfba646567f 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/block.py +++ b/src/ethereum/forks/shanghai/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -40,7 +40,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -89,7 +89,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -123,7 +123,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -156,7 +156,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -189,7 +189,7 @@ def prev_randao(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PREVRANDAO) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.prev_randao)) @@ -222,7 +222,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) @@ -252,7 +252,7 @@ def chain_id(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CHAINID) # OPERATION push(evm.stack, U256(evm.message.block_env.chain_id)) diff --git a/src/ethereum/forks/shanghai/vm/instructions/comparison.py b/src/ethereum/forks/shanghai/vm/instructions/comparison.py index a6a3d99bc86..ee5c881ef0d 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/comparison.py +++ b/src/ethereum/forks/shanghai/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/shanghai/vm/instructions/control_flow.py b/src/ethereum/forks/shanghai/vm/instructions/control_flow.py index b3b1f2316a7..d74e7b90340 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/control_flow.py +++ b/src/ethereum/forks/shanghai/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_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, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/shanghai/vm/instructions/environment.py b/src/ethereum/forks/shanghai/vm/instructions/environment.py index ba2bb42a425..588022b5722 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/environment.py +++ b/src/ethereum/forks/shanghai/vm/instructions/environment.py @@ -22,13 +22,7 @@ from .. import Evm from ..exceptions import OutOfBoundsRead from ..gas import ( - GAS_BASE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_COPY, - GAS_FAST_STEP, - GAS_RETURN_DATA_COPY, - GAS_VERY_LOW, - GAS_WARM_ACCESS, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -49,7 +43,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -73,10 +67,10 @@ def balance(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_addresses.add(address) - charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) + charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -103,7 +97,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -126,7 +120,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -149,7 +143,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -173,7 +167,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -198,7 +192,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -227,11 +221,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -256,7 +253,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -285,11 +282,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -314,7 +314,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -338,10 +338,10 @@ def extcodesize(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -374,16 +374,16 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) @@ -413,7 +413,7 @@ def returndatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE) # OPERATION push(evm.stack, U256(len(evm.return_data))) @@ -439,11 +439,16 @@ def returndatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_RETURN_DATA_COPY * words + copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words 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, + GasCosts.OPCODE_RETURNDATACOPY_BASE + + copy_gas_cost + + extend_memory.cost, + ) if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): raise OutOfBoundsRead @@ -472,10 +477,10 @@ def extcodehash(evm: Evm) -> None: # GAS if address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS charge_gas(evm, access_gas_cost) @@ -507,7 +512,7 @@ def self_balance(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_FAST_STEP) + charge_gas(evm, GasCosts.FAST_STEP) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -535,7 +540,7 @@ def base_fee(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_BASEFEE) # OPERATION push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) diff --git a/src/ethereum/forks/shanghai/vm/instructions/keccak.py b/src/ethereum/forks/shanghai/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/keccak.py +++ b/src/ethereum/forks/shanghai/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/shanghai/vm/instructions/log.py b/src/ethereum/forks/shanghai/vm/instructions/log.py index abc297df6fa..bd5e652db22 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/log.py +++ b/src/ethereum/forks/shanghai/vm/instructions/log.py @@ -19,9 +19,7 @@ from .. import Evm from ..exceptions import WriteInStaticContext from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -59,9 +57,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/shanghai/vm/instructions/memory.py b/src/ethereum/forks/shanghai/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/memory.py +++ b/src/ethereum/forks/shanghai/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/shanghai/vm/instructions/stack.py b/src/ethereum/forks/shanghai/vm/instructions/stack.py index 0007a28acd4..d7b3df986b0 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/stack.py +++ b/src/ethereum/forks/shanghai/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 GasCosts, 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, GasCosts.OPCODE_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, GasCosts.OPCODE_PUSH0) else: - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # 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, GasCosts.OPCODE_DUP) 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, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/shanghai/vm/instructions/storage.py b/src/ethereum/forks/shanghai/vm/instructions/storage.py index d99ad70f93b..0936a10b1e1 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/storage.py +++ b/src/ethereum/forks/shanghai/vm/instructions/storage.py @@ -16,15 +16,7 @@ from ...state import get_storage, get_storage_original, set_storage from .. import Evm from ..exceptions import OutOfGasError, WriteInStaticContext -from ..gas import ( - GAS_CALL_STIPEND, - GAS_COLD_STORAGE_ACCESS, - GAS_COLD_STORAGE_WRITE, - GAS_STORAGE_SET, - GAS_WARM_ACCESS, - REFUND_STORAGE_CLEAR, - charge_gas, -) +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -44,10 +36,10 @@ def sload(evm: Evm) -> None: # GAS if (evm.message.current_target, key) in evm.accessed_storage_keys: - charge_gas(evm, GAS_WARM_ACCESS) + charge_gas(evm, GasCosts.WARM_ACCESS) else: evm.accessed_storage_keys.add((evm.message.current_target, key)) - charge_gas(evm, GAS_COLD_STORAGE_ACCESS) + charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS) # OPERATION value = get_storage( @@ -73,7 +65,7 @@ def sstore(evm: Evm) -> None: # STACK key = pop(evm.stack).to_be_bytes32() new_value = pop(evm.stack) - if evm.gas_left <= GAS_CALL_STIPEND: + if evm.gas_left <= GasCosts.CALL_STIPEND: raise OutOfGasError state = evm.message.block_env.state @@ -86,37 +78,41 @@ def sstore(evm: Evm) -> None: if (evm.message.current_target, key) not in evm.accessed_storage_keys: evm.accessed_storage_keys.add((evm.message.current_target, key)) - gas_cost += GAS_COLD_STORAGE_ACCESS + gas_cost += GasCosts.COLD_STORAGE_ACCESS if original_value == current_value and current_value != new_value: if original_value == 0: - gas_cost += GAS_STORAGE_SET + gas_cost += GasCosts.STORAGE_SET else: - gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_STORAGE_ACCESS + gas_cost += ( + GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS + ) else: - gas_cost += GAS_WARM_ACCESS + gas_cost += GasCosts.WARM_ACCESS # Refund Counter Calculation if current_value != new_value: if original_value != 0 and current_value != 0 and new_value == 0: # Storage is cleared for the first time in the transaction - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR if original_value != 0 and current_value == 0: # Gas refund issued earlier to be reversed - evm.refund_counter -= REFUND_STORAGE_CLEAR + evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR if original_value == new_value: # Storage slot being restored to its original value if original_value == 0: # Slot was originally empty and was SET earlier - evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS) + evm.refund_counter += int( + GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS + ) else: # Slot was originally non-empty and was UPDATED earlier evm.refund_counter += int( - GAS_COLD_STORAGE_WRITE - - GAS_COLD_STORAGE_ACCESS - - GAS_WARM_ACCESS + GasCosts.COLD_STORAGE_WRITE + - GasCosts.COLD_STORAGE_ACCESS + - GasCosts.WARM_ACCESS ) charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/shanghai/vm/instructions/system.py b/src/ethereum/forks/shanghai/vm/instructions/system.py index e5abcae2236..b3fc0cd3dbb 100644 --- a/src/ethereum/forks/shanghai/vm/instructions/system.py +++ b/src/ethereum/forks/shanghai/vm/instructions/system.py @@ -39,15 +39,7 @@ ) from ..exceptions import OutOfGasError, Revert, WriteInStaticContext from ..gas import ( - GAS_CALL_VALUE, - GAS_COLD_ACCOUNT_ACCESS, - GAS_CREATE, - GAS_KECCAK256_PER_WORD, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_WARM_ACCESS, - GAS_ZERO, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -164,7 +156,9 @@ 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, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -214,8 +208,8 @@ def create2(evm: Evm) -> None: init_code_gas = init_code_cost(Uint(memory_size)) charge_gas( evm, - GAS_CREATE - + GAS_KECCAK256_PER_WORD * call_data_words + GasCosts.OPCODE_CREATE_BASE + + GasCosts.OPCODE_KECCACK256_PER_WORD * call_data_words + extend_memory.cost + init_code_gas, ) @@ -259,7 +253,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -370,17 +364,17 @@ def call(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -450,12 +444,12 @@ def callcode(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, @@ -508,10 +502,10 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if beneficiary not in evm.accessed_addresses: evm.accessed_addresses.add(beneficiary) - gas_cost += GAS_COLD_ACCOUNT_ACCESS + gas_cost += GasCosts.COLD_ACCOUNT_ACCESS if ( not is_account_alive(evm.message.block_env.state, beneficiary) @@ -520,7 +514,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT charge_gas(evm, gas_cost) if evm.message.is_static: @@ -583,10 +577,10 @@ def delegatecall(evm: Evm) -> None: ) if code_address in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(code_address) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS message_call_gas = calculate_message_call_gas( U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost @@ -642,10 +636,10 @@ def staticcall(evm: Evm) -> None: ) if to in evm.accessed_addresses: - access_gas_cost = GAS_WARM_ACCESS + access_gas_cost = GasCosts.WARM_ACCESS else: evm.accessed_addresses.add(to) - access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS code_address = to diff --git a/src/ethereum/forks/shanghai/vm/interpreter.py b/src/ethereum/forks/shanghai/vm/interpreter.py index 6485ebe11f2..d4ec312b4fa 100644 --- a/src/ethereum/forks/shanghai/vm/interpreter.py +++ b/src/ethereum/forks/shanghai/vm/interpreter.py @@ -43,7 +43,7 @@ set_code, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -168,7 +168,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: if len(contract_code) > 0: diff --git a/src/ethereum/forks/shanghai/vm/precompiled_contracts/alt_bn128.py b/src/ethereum/forks/shanghai/vm/precompiled_contracts/alt_bn128.py index 214725d8da0..09bed4a0282 100644 --- a/src/ethereum/forks/shanghai/vm/precompiled_contracts/alt_bn128.py +++ b/src/ethereum/forks/shanghai/vm/precompiled_contracts/alt_bn128.py @@ -31,7 +31,7 @@ from py_ecc.typing import Optimized_Point3D as Point3D from ...vm import Evm -from ...vm.gas import charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read from ..exceptions import InvalidParameter, OutOfGasError @@ -149,7 +149,7 @@ def alt_bn128_add(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(150)) + charge_gas(evm, GasCosts.PRECOMPILE_ECADD) # OPERATION try: @@ -177,7 +177,7 @@ def alt_bn128_mul(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(6000)) + charge_gas(evm, GasCosts.PRECOMPILE_ECMUL) # OPERATION try: @@ -205,7 +205,11 @@ def alt_bn128_pairing_check(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) + charge_gas( + evm, + GasCosts.PRECOMPILE_ECPAIRING_PER_POINT * Uint(len(data) // 192) + + GasCosts.PRECOMPILE_ECPAIRING_BASE, + ) # OPERATION if len(data) % 192 != 0: diff --git a/src/ethereum/forks/shanghai/vm/precompiled_contracts/blake2f.py b/src/ethereum/forks/shanghai/vm/precompiled_contracts/blake2f.py index c5eaff7d62a..ae53b1ab4b5 100644 --- a/src/ethereum/forks/shanghai/vm/precompiled_contracts/blake2f.py +++ b/src/ethereum/forks/shanghai/vm/precompiled_contracts/blake2f.py @@ -14,7 +14,7 @@ from ethereum.crypto.blake2 import Blake2b from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_BLAKE2F_PER_ROUND, charge_gas +from ...vm.gas import GasCosts, charge_gas from ..exceptions import InvalidParameter @@ -35,7 +35,7 @@ def blake2f(evm: Evm) -> None: blake2b = Blake2b() rounds, h, m, t_0, t_1, f = blake2b.get_blake2_parameters(data) - charge_gas(evm, GAS_PRECOMPILE_BLAKE2F_PER_ROUND * rounds) + charge_gas(evm, GasCosts.PRECOMPILE_BLAKE2F_PER_ROUND * rounds) if f not in [0, 1]: raise InvalidParameter diff --git a/src/ethereum/forks/shanghai/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/shanghai/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/shanghai/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/shanghai/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/shanghai/vm/precompiled_contracts/identity.py b/src/ethereum/forks/shanghai/vm/precompiled_contracts/identity.py index 133a4832bf8..2b4929fb8d2 100644 --- a/src/ethereum/forks/shanghai/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/shanghai/vm/precompiled_contracts/identity.py @@ -16,11 +16,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def identity(evm: Evm) -> None: @@ -39,8 +35,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/shanghai/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/shanghai/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..04d0e2ff594 100644 --- a/src/ethereum/forks/shanghai/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/shanghai/vm/precompiled_contracts/ripemd160.py @@ -19,11 +19,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def ripemd160(evm: Evm) -> None: @@ -42,8 +38,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/shanghai/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/shanghai/vm/precompiled_contracts/sha256.py index 04dfef6730d..f5346f1529c 100644 --- a/src/ethereum/forks/shanghai/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/shanghai/vm/precompiled_contracts/sha256.py @@ -18,11 +18,7 @@ from ethereum.utils.numeric import ceil32 from ...vm import Evm -from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, - charge_gas, -) +from ...vm.gas import GasCosts, charge_gas def sha256(evm: Evm) -> None: @@ -41,8 +37,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/spurious_dragon/fork.py b/src/ethereum/forks/spurious_dragon/fork.py index a115049d968..7ca5fada91b 100644 --- a/src/ethereum/forks/spurious_dragon/fork.py +++ b/src/ethereum/forks/spurious_dragon/fork.py @@ -51,11 +51,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(5 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) @@ -709,14 +708,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -732,12 +731,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/spurious_dragon/transactions.py b/src/ethereum/forks/spurious_dragon/transactions.py index 278238f8d5a..e8cde82b198 100644 --- a/src/ethereum/forks/spurious_dragon/transactions.py +++ b/src/ethereum/forks/spurious_dragon/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(68) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(chain_id: U64, tx: Transaction) -> Address: diff --git a/src/ethereum/forks/spurious_dragon/vm/gas.py b/src/ethereum/forks/spurious_dragon/vm/gas.py index 937e953a145..49c69c4653a 100644 --- a/src/ethereum/forks/spurious_dragon/vm/gas.py +++ b/src/ethereum/forks/spurious_dragon/vm/gas.py @@ -22,45 +22,129 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(200) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(50) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(700) -GAS_BALANCE = Uint(400) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(700) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -REFUND_SELF_DESTRUCT = 24000 -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(200) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = 24000 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(68) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(50) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) + OPCODE_EXTERNAL_BASE = Uint(700) + OPCODE_BALANCE = Uint(400) + OPCODE_CALL_BASE = Uint(700) @dataclass @@ -81,8 +165,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -134,7 +218,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -189,7 +273,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/arithmetic.py b/src/ethereum/forks/spurious_dragon/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/bitwise.py b/src/ethereum/forks/spurious_dragon/vm/instructions/bitwise.py index 2a506f55751..62da98041ad 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/bitwise.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/block.py b/src/ethereum/forks/spurious_dragon/vm/instructions/block.py index 0edcbf000d1..fbca7daa37c 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/block.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/comparison.py b/src/ethereum/forks/spurious_dragon/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/comparison.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/control_flow.py b/src/ethereum/forks/spurious_dragon/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/control_flow.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/environment.py b/src/ethereum/forks/spurious_dragon/vm/instructions/environment.py index 83eb5528226..d930368fdd9 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/environment.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/environment.py @@ -20,11 +20,7 @@ from ...vm.memory import buffer_read, memory_write from .. import Evm from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_COPY, - GAS_EXTERNAL, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -45,7 +41,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -68,7 +64,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -95,7 +91,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -118,7 +114,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -141,7 +137,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -165,7 +161,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -190,7 +186,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -219,11 +215,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -248,7 +247,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -277,11 +276,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -306,7 +308,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -329,7 +331,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -360,11 +362,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/keccak.py b/src/ethereum/forks/spurious_dragon/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/keccak.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/log.py b/src/ethereum/forks/spurious_dragon/vm/instructions/log.py index 76c02e737a4..e3e3ebd7e76 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/log.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/log.py @@ -18,9 +18,7 @@ from ...blocks import Log from .. import Evm from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -58,9 +56,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/memory.py b/src/ethereum/forks/spurious_dragon/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/memory.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/stack.py b/src/ethereum/forks/spurious_dragon/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/stack.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/storage.py b/src/ethereum/forks/spurious_dragon/vm/instructions/storage.py index 154b4fd47bb..0b2a1cce8aa 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/storage.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/storage.py @@ -16,10 +16,7 @@ from ...state import get_storage, set_storage from .. import Evm from ..gas import ( - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -40,7 +37,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -71,12 +68,12 @@ def sstore(evm: Evm) -> None: state = evm.message.block_env.state current_value = get_storage(state, evm.message.current_target, key) if new_value != 0 and current_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE if new_value == 0 and current_value != 0: - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/spurious_dragon/vm/instructions/system.py b/src/ethereum/forks/spurious_dragon/vm/instructions/system.py index e35d7a5a7c7..037a54da3f9 100644 --- a/src/ethereum/forks/spurious_dragon/vm/instructions/system.py +++ b/src/ethereum/forks/spurious_dragon/vm/instructions/system.py @@ -34,14 +34,7 @@ incorporate_child_on_success, ) from ..gas import ( - GAS_CALL, - GAS_CALL_VALUE, - GAS_CREATE, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -75,7 +68,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) create_message_gas = max_message_call_gas(Uint(evm.gas_left)) evm.gas_left -= create_message_gas @@ -164,7 +157,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -268,16 +261,16 @@ def call(evm: Evm) -> None: code_address = to - create_gas_cost = GAS_NEW_ACCOUNT + create_gas_cost = GasCosts.NEW_ACCOUNT if value == 0 or is_account_alive(evm.message.block_env.state, to): create_gas_cost = Uint(0) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + create_gas_cost + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + create_gas_cost + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -337,13 +330,13 @@ def callcode(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -388,7 +381,7 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if ( not is_account_alive(evm.message.block_env.state, beneficiary) and get_account( @@ -396,7 +389,7 @@ def selfdestruct(evm: Evm) -> None: ).balance != 0 ): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT originator = evm.message.current_target @@ -407,7 +400,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += REFUND_SELF_DESTRUCT + evm.refund_counter += GasCosts.REFUND_SELF_DESTRUCT charge_gas(evm, gas_cost) @@ -470,7 +463,11 @@ def delegatecall(evm: Evm) -> None: ], ) message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) diff --git a/src/ethereum/forks/spurious_dragon/vm/interpreter.py b/src/ethereum/forks/spurious_dragon/vm/interpreter.py index e65ffc2020a..c970cbc1ee4 100644 --- a/src/ethereum/forks/spurious_dragon/vm/interpreter.py +++ b/src/ethereum/forks/spurious_dragon/vm/interpreter.py @@ -44,7 +44,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -173,7 +173,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/identity.py b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/spurious_dragon/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/tangerine_whistle/fork.py b/src/ethereum/forks/tangerine_whistle/fork.py index 162a6bd1b7a..f5e7eb38b5a 100644 --- a/src/ethereum/forks/tangerine_whistle/fork.py +++ b/src/ethereum/forks/tangerine_whistle/fork.py @@ -49,11 +49,10 @@ ) from .trie import root, trie_set from .utils.message import prepare_message +from .vm.gas import GasCosts from .vm.interpreter import process_message_call BLOCK_REWARD = U256(5 * 10**18) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) MINIMUM_DIFFICULTY = Uint(131072) MAX_OMMER_DEPTH = Uint(6) @@ -700,14 +699,14 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: The bounds of the gas limit, ``max_adjustment_delta``, is set as the quotient of the parent block's gas limit and the - ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is - passed through as a parameter is greater than or equal to the *sum* of - the parent's gas and the adjustment delta then the limit for gas is too - high and fails this function's check. Similarly, if the limit is less - than or equal to the *difference* of the parent's gas and the adjustment - delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's - check fails because the gas limit doesn't allow for a sufficient or - reasonable amount of gas to be used on a block. + ``LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is passed + through as a parameter is greater than or equal to the *sum* of the + parent's gas and the adjustment delta then the limit for gas is too high + and fails this function's check. Similarly, if the limit is less than or + equal to the *difference* of the parent's gas and the adjustment delta *or* + the predefined ``LIMIT_MINIMUM`` then this function's check fails because + the gas limit doesn't allow for a sufficient or reasonable amount of gas to + be used on a block. Parameters ---------- @@ -723,12 +722,12 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: True if gas limit constraints are satisfied, False otherwise. """ - max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR + max_adjustment_delta = parent_gas_limit // GasCosts.LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False if gas_limit <= parent_gas_limit - max_adjustment_delta: return False - if gas_limit < GAS_LIMIT_MINIMUM: + if gas_limit < GasCosts.LIMIT_MINIMUM: return False return True diff --git a/src/ethereum/forks/tangerine_whistle/transactions.py b/src/ethereum/forks/tangerine_whistle/transactions.py index 934540874ca..e17bafae49d 100644 --- a/src/ethereum/forks/tangerine_whistle/transactions.py +++ b/src/ethereum/forks/tangerine_whistle/transactions.py @@ -21,27 +21,6 @@ from .fork_types import Address -GAS_TX_BASE = Uint(21000) -""" -Base cost of a transaction in gas units. This is the minimum amount of gas -required to execute a transaction. -""" - -GAS_TX_DATA_PER_NON_ZERO = Uint(68) -""" -Gas cost per non-zero byte in the transaction data. -""" - -GAS_TX_DATA_PER_ZERO = Uint(4) -""" -Gas cost per zero byte in the transaction data. -""" - -GAS_TX_CREATE = Uint(32000) -""" -Additional gas cost for creating a new contract. -""" - @slotted_freezable @dataclass @@ -143,26 +122,28 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: for all operations to be implemented. The intrinsic cost includes: - 1. Base cost (`GAS_TX_BASE`) + 1. Base cost (`TX_BASE`) 2. Cost for data (zero and non-zero bytes) 3. Cost for contract creation (if applicable) This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction. """ + from .vm.gas import GasCosts + num_zeros = Uint(tx.data.count(0)) num_non_zeros = ulen(tx.data) - num_zeros data_cost = ( - num_zeros * GAS_TX_DATA_PER_ZERO - + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO + num_zeros * GasCosts.TX_DATA_PER_ZERO + + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO ) if tx.to == Bytes0(b""): - create_cost = GAS_TX_CREATE + create_cost = GasCosts.TX_CREATE else: create_cost = Uint(0) - return GAS_TX_BASE + data_cost + create_cost + return GasCosts.TX_BASE + data_cost + create_cost def recover_sender(tx: Transaction) -> Address: diff --git a/src/ethereum/forks/tangerine_whistle/vm/gas.py b/src/ethereum/forks/tangerine_whistle/vm/gas.py index 56a9451c117..1dff8b9c25a 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/gas.py +++ b/src/ethereum/forks/tangerine_whistle/vm/gas.py @@ -22,45 +22,129 @@ from . import Evm from .exceptions import OutOfGasError -GAS_JUMPDEST = Uint(1) -GAS_BASE = Uint(2) -GAS_VERY_LOW = Uint(3) -GAS_SLOAD = Uint(200) -GAS_STORAGE_SET = Uint(20000) -GAS_COLD_STORAGE_WRITE = Uint(5000) -REFUND_STORAGE_CLEAR = 15000 -GAS_LOW = Uint(5) -GAS_MID = Uint(8) -GAS_HIGH = Uint(10) -GAS_EXPONENTIATION = Uint(10) -GAS_EXPONENTIATION_PER_BYTE = Uint(10) -GAS_MEMORY = Uint(3) -GAS_KECCAK256 = Uint(30) -GAS_KECCAK256_PER_WORD = Uint(6) -GAS_COPY = Uint(3) -GAS_BLOCK_HASH = Uint(20) -GAS_EXTERNAL = Uint(700) -GAS_BALANCE = Uint(400) -GAS_LOG = Uint(375) -GAS_LOG_DATA_PER_BYTE = Uint(8) -GAS_LOG_TOPIC = Uint(375) -GAS_CREATE = Uint(32000) -GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) -GAS_ZERO = Uint(0) -GAS_CALL = Uint(700) -GAS_NEW_ACCOUNT = Uint(25000) -GAS_CALL_VALUE = Uint(9000) -GAS_CALL_STIPEND = Uint(2300) -GAS_SELF_DESTRUCT = Uint(5000) -GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) -REFUND_SELF_DESTRUCT = 24000 -GAS_PRECOMPILE_ECRECOVER = Uint(3000) -GAS_PRECOMPILE_SHA256_BASE = Uint(60) -GAS_PRECOMPILE_SHA256_PER_WORD = Uint(12) -GAS_PRECOMPILE_RIPEMD160_BASE = Uint(600) -GAS_PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) -GAS_PRECOMPILE_IDENTITY_BASE = Uint(15) -GAS_PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + +# These values may be patched at runtime by a future gas repricing utility +class GasCosts: + """ + Constant gas values for the EVM. + """ + + # Tiers + BASE = Uint(2) + VERY_LOW = Uint(3) + LOW = Uint(5) + MID = Uint(8) + HIGH = Uint(10) + + # Access + SLOAD = Uint(200) + + # Storage + STORAGE_SET = Uint(20000) + COLD_STORAGE_WRITE = Uint(5000) + + # Call + CALL_VALUE = Uint(9000) + CALL_STIPEND = Uint(2300) + NEW_ACCOUNT = Uint(25000) + + # Contract Creation + CODE_DEPOSIT_PER_BYTE = Uint(200) + + # Utility + ZERO = Uint(0) + MEMORY_PER_WORD = Uint(3) + + # Refunds + REFUND_STORAGE_CLEAR = 15000 + REFUND_SELF_DESTRUCT = 24000 + + # Precompiles + PRECOMPILE_ECRECOVER = Uint(3000) + PRECOMPILE_SHA256_BASE = Uint(60) + PRECOMPILE_SHA256_PER_WORD = Uint(12) + PRECOMPILE_RIPEMD160_BASE = Uint(600) + PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) + PRECOMPILE_IDENTITY_BASE = Uint(15) + PRECOMPILE_IDENTITY_PER_WORD = Uint(3) + + # Transactions + TX_BASE = Uint(21000) + TX_CREATE = Uint(32000) + TX_DATA_PER_ZERO = Uint(4) + TX_DATA_PER_NON_ZERO = Uint(68) + + # Block + LIMIT_ADJUSTMENT_FACTOR = Uint(1024) + LIMIT_MINIMUM = Uint(5000) + + # Static Opcodes + OPCODE_ADD = VERY_LOW + OPCODE_SUB = VERY_LOW + OPCODE_MUL = LOW + OPCODE_DIV = LOW + OPCODE_SDIV = LOW + OPCODE_MOD = LOW + OPCODE_SMOD = LOW + OPCODE_ADDMOD = MID + OPCODE_MULMOD = MID + OPCODE_SIGNEXTEND = LOW + OPCODE_LT = VERY_LOW + OPCODE_GT = VERY_LOW + OPCODE_SLT = VERY_LOW + OPCODE_SGT = VERY_LOW + OPCODE_EQ = VERY_LOW + OPCODE_ISZERO = VERY_LOW + OPCODE_AND = VERY_LOW + OPCODE_OR = VERY_LOW + OPCODE_XOR = VERY_LOW + OPCODE_NOT = VERY_LOW + OPCODE_BYTE = VERY_LOW + OPCODE_JUMP = MID + OPCODE_JUMPI = HIGH + OPCODE_JUMPDEST = Uint(1) + OPCODE_CALLDATALOAD = VERY_LOW + OPCODE_BLOCKHASH = Uint(20) + OPCODE_COINBASE = BASE + OPCODE_POP = BASE + OPCODE_MSIZE = BASE + OPCODE_PC = BASE + OPCODE_GAS = BASE + OPCODE_ADDRESS = BASE + OPCODE_ORIGIN = BASE + OPCODE_CALLER = BASE + OPCODE_CALLVALUE = BASE + OPCODE_CALLDATASIZE = BASE + OPCODE_CODESIZE = BASE + OPCODE_GASPRICE = BASE + OPCODE_TIMESTAMP = BASE + OPCODE_NUMBER = BASE + OPCODE_GASLIMIT = BASE + OPCODE_DIFFICULTY = BASE + OPCODE_PUSH = VERY_LOW + OPCODE_DUP = VERY_LOW + OPCODE_SWAP = VERY_LOW + + # Dynamic Opcodes + OPCODE_CALLDATACOPY_BASE = VERY_LOW + OPCODE_CODECOPY_BASE = VERY_LOW + OPCODE_MLOAD_BASE = VERY_LOW + OPCODE_MSTORE_BASE = VERY_LOW + OPCODE_MSTORE8_BASE = VERY_LOW + OPCODE_COPY_PER_WORD = Uint(3) + OPCODE_CREATE_BASE = Uint(32000) + OPCODE_EXP_BASE = Uint(10) + OPCODE_EXP_PER_BYTE = Uint(10) + OPCODE_KECCAK256_BASE = Uint(30) + OPCODE_KECCACK256_PER_WORD = Uint(6) + OPCODE_LOG_BASE = Uint(375) + OPCODE_LOG_DATA_PER_BYTE = Uint(8) + OPCODE_LOG_TOPIC = Uint(375) + OPCODE_SELFDESTRUCT_BASE = Uint(5000) + OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) + OPCODE_EXTERNAL_BASE = Uint(700) + OPCODE_BALANCE = Uint(400) + OPCODE_CALL_BASE = Uint(700) @dataclass @@ -81,8 +165,8 @@ class ExtendMemory: @dataclass class MessageCallGas: """ - Define the gas cost and gas given to the sub-call for - executing the call opcodes. + Define the gas cost and gas given to the sub-call for executing the call + opcodes. `cost`: `ethereum.base_types.Uint` The gas required to execute the call opcode, excludes @@ -134,7 +218,7 @@ def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint: """ size_in_words = ceil32(size_in_bytes) // Uint(32) - linear_cost = size_in_words * GAS_MEMORY + linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD quadratic_cost = size_in_words ** Uint(2) // Uint(512) total_gas_cost = linear_cost + quadratic_cost try: @@ -189,7 +273,7 @@ def calculate_message_call_gas( gas_left: Uint, memory_cost: Uint, extra_gas: Uint, - call_stipend: Uint = GAS_CALL_STIPEND, + call_stipend: Uint = GasCosts.CALL_STIPEND, ) -> MessageCallGas: """ Calculates the MessageCallGas (cost and gas made available to the sub-call) diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/arithmetic.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/arithmetic.py index b7b1a370ad4..4c7423cba8e 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/arithmetic.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/arithmetic.py @@ -18,11 +18,7 @@ from .. import Evm from ..gas import ( - GAS_EXPONENTIATION, - GAS_EXPONENTIATION_PER_BYTE, - GAS_LOW, - GAS_MID, - GAS_VERY_LOW, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -44,7 +40,7 @@ def add(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ADD) # OPERATION result = x.wrapping_add(y) @@ -71,7 +67,7 @@ def sub(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SUB) # OPERATION result = x.wrapping_sub(y) @@ -98,7 +94,7 @@ def mul(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MUL) # OPERATION result = x.wrapping_mul(y) @@ -125,7 +121,7 @@ def div(evm: Evm) -> None: divisor = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_DIV) # OPERATION if divisor == 0: @@ -158,7 +154,7 @@ def sdiv(evm: Evm) -> None: divisor = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SDIV) # OPERATION if divisor == 0: @@ -191,7 +187,7 @@ def mod(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_MOD) # OPERATION if y == 0: @@ -221,7 +217,7 @@ def smod(evm: Evm) -> None: y = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SMOD) # OPERATION if y == 0: @@ -252,7 +248,7 @@ def addmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_ADDMOD) # OPERATION if z == 0: @@ -283,7 +279,7 @@ def mulmod(evm: Evm) -> None: z = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_MULMOD) # OPERATION if z == 0: @@ -318,7 +314,9 @@ def exp(evm: Evm) -> None: exponent_bits = exponent.bit_length() exponent_bytes = (exponent_bits + Uint(7)) // Uint(8) charge_gas( - evm, GAS_EXPONENTIATION + GAS_EXPONENTIATION_PER_BYTE * exponent_bytes + evm, + GasCosts.OPCODE_EXP_BASE + + GasCosts.OPCODE_EXP_PER_BYTE * exponent_bytes, ) # OPERATION @@ -346,7 +344,7 @@ def signextend(evm: Evm) -> None: value = pop(evm.stack) # GAS - charge_gas(evm, GAS_LOW) + charge_gas(evm, GasCosts.OPCODE_SIGNEXTEND) # OPERATION if byte_num > U256(31): diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/bitwise.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/bitwise.py index 2a506f55751..62da98041ad 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/bitwise.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/bitwise.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def bitwise_and(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_AND) # OPERATION push(evm.stack, x & y) @@ -59,7 +62,7 @@ def bitwise_or(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_OR) # OPERATION push(evm.stack, x | y) @@ -84,7 +87,7 @@ def bitwise_xor(evm: Evm) -> None: y = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_XOR) # OPERATION push(evm.stack, x ^ y) @@ -108,7 +111,7 @@ def bitwise_not(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_NOT) # OPERATION push(evm.stack, ~x) @@ -134,7 +137,7 @@ def get_byte(evm: Evm) -> None: word = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_BYTE) # OPERATION if byte_index >= U256(32): diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/block.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/block.py index 0edcbf000d1..fbca7daa37c 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/block.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/block.py @@ -14,7 +14,7 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_BASE, GAS_BLOCK_HASH, charge_gas +from ..gas import GasCosts, charge_gas from ..stack import pop, push @@ -33,7 +33,7 @@ def block_hash(evm: Evm) -> None: block_number = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BLOCK_HASH) + charge_gas(evm, GasCosts.OPCODE_BLOCKHASH) # OPERATION max_block_number = block_number + Uint(256) @@ -75,7 +75,7 @@ def coinbase(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_COINBASE) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.block_env.coinbase)) @@ -102,7 +102,7 @@ def timestamp(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_TIMESTAMP) # OPERATION push(evm.stack, evm.message.block_env.time) @@ -128,7 +128,7 @@ def number(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_NUMBER) # OPERATION push(evm.stack, U256(evm.message.block_env.number)) @@ -154,7 +154,7 @@ def difficulty(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_DIFFICULTY) # OPERATION push(evm.stack, U256(evm.message.block_env.difficulty)) @@ -180,7 +180,7 @@ def gas_limit(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASLIMIT) # OPERATION push(evm.stack, U256(evm.message.block_env.block_gas_limit)) diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/comparison.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/comparison.py index a6a3d99bc86..22d3d8916b1 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/comparison.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/comparison.py @@ -14,7 +14,10 @@ from ethereum_types.numeric import U256, Uint from .. import Evm -from ..gas import GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..stack import pop, push @@ -34,7 +37,7 @@ def less_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_LT) # OPERATION result = U256(left < right) @@ -60,7 +63,7 @@ def signed_less_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SLT) # OPERATION result = U256(left < right) @@ -87,7 +90,7 @@ def greater_than(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_GT) # OPERATION result = U256(left > right) @@ -113,7 +116,7 @@ def signed_greater_than(evm: Evm) -> None: right = pop(evm.stack).to_signed() # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SGT) # OPERATION result = U256(left > right) @@ -140,7 +143,7 @@ def equal(evm: Evm) -> None: right = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_EQ) # OPERATION result = U256(left == right) @@ -166,7 +169,7 @@ def is_zero(evm: Evm) -> None: x = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_ISZERO) # OPERATION result = U256(x == 0) diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/control_flow.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/control_flow.py index b3b1f2316a7..548a05d3163 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/control_flow.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/control_flow.py @@ -13,7 +13,10 @@ 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 ( + GasCosts, + charge_gas, +) from .. import Evm from ..exceptions import InvalidJumpDestError from ..stack import pop, push @@ -57,7 +60,7 @@ def jump(evm: Evm) -> None: jump_dest = Uint(pop(evm.stack)) # GAS - charge_gas(evm, GAS_MID) + charge_gas(evm, GasCosts.OPCODE_JUMP) # OPERATION if jump_dest not in evm.valid_jump_destinations: @@ -84,7 +87,7 @@ def jumpi(evm: Evm) -> None: conditional_value = pop(evm.stack) # GAS - charge_gas(evm, GAS_HIGH) + charge_gas(evm, GasCosts.OPCODE_JUMPI) # OPERATION if conditional_value == 0: @@ -113,7 +116,7 @@ def pc(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_PC) # OPERATION push(evm.stack, U256(evm.pc)) @@ -137,7 +140,7 @@ def gas_left(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GAS) # OPERATION push(evm.stack, U256(evm.gas_left)) @@ -162,7 +165,7 @@ def jumpdest(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_JUMPDEST) + charge_gas(evm, GasCosts.OPCODE_JUMPDEST) # OPERATION pass diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/environment.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/environment.py index 83eb5528226..d930368fdd9 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/environment.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/environment.py @@ -20,11 +20,7 @@ from ...vm.memory import buffer_read, memory_write from .. import Evm from ..gas import ( - GAS_BALANCE, - GAS_BASE, - GAS_COPY, - GAS_EXTERNAL, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -45,7 +41,7 @@ def address(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ADDRESS) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.current_target)) @@ -68,7 +64,7 @@ def balance(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_BALANCE) + charge_gas(evm, GasCosts.OPCODE_BALANCE) # OPERATION # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. @@ -95,7 +91,7 @@ def origin(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_ORIGIN) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) @@ -118,7 +114,7 @@ def caller(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLER) # OPERATION push(evm.stack, U256.from_be_bytes(evm.message.caller)) @@ -141,7 +137,7 @@ def callvalue(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLVALUE) # OPERATION push(evm.stack, evm.message.value) @@ -165,7 +161,7 @@ def calldataload(evm: Evm) -> None: start_index = pop(evm.stack) # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD) # OPERATION value = buffer_read(evm.message.data, start_index, U256(32)) @@ -190,7 +186,7 @@ def calldatasize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE) # OPERATION push(evm.stack, U256(len(evm.message.data))) @@ -219,11 +215,14 @@ def calldatacopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -248,7 +247,7 @@ def codesize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_CODESIZE) # OPERATION push(evm.stack, U256(len(evm.code))) @@ -277,11 +276,14 @@ def codecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words 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, + GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -306,7 +308,7 @@ def gasprice(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_GASPRICE) # OPERATION push(evm.stack, U256(evm.message.tx_env.gas_price)) @@ -329,7 +331,7 @@ def extcodesize(evm: Evm) -> None: address = to_address_masked(pop(evm.stack)) # GAS - charge_gas(evm, GAS_EXTERNAL) + charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE) # OPERATION account = get_account(evm.message.block_env.state, address) @@ -360,11 +362,14 @@ def extcodecopy(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - copy_gas_cost = GAS_COPY * words + copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words extend_memory = calculate_gas_extend_memory( evm.memory, [(memory_start_index, size)] ) - charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) + charge_gas( + evm, + GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/keccak.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/keccak.py index 8661c5d62f5..c8099ee0ecc 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/keccak.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/keccak.py @@ -18,8 +18,7 @@ from .. import Evm from ..gas import ( - GAS_KECCAK256, - GAS_KECCAK256_PER_WORD, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,11 +45,14 @@ def keccak(evm: Evm) -> None: # GAS words = ceil32(Uint(size)) // Uint(32) - word_gas_cost = GAS_KECCAK256_PER_WORD * words + word_gas_cost = GasCosts.OPCODE_KECCACK256_PER_WORD * words 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, + GasCosts.OPCODE_KECCAK256_BASE + word_gas_cost + extend_memory.cost, + ) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/log.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/log.py index 76c02e737a4..e3e3ebd7e76 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/log.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/log.py @@ -18,9 +18,7 @@ from ...blocks import Log from .. import Evm from ..gas import ( - GAS_LOG, - GAS_LOG_DATA_PER_BYTE, - GAS_LOG_TOPIC, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -58,9 +56,9 @@ def log_n(evm: Evm, num_topics: int) -> None: ) charge_gas( evm, - GAS_LOG - + GAS_LOG_DATA_PER_BYTE * Uint(size) - + GAS_LOG_TOPIC * Uint(num_topics) + GasCosts.OPCODE_LOG_BASE + + GasCosts.OPCODE_LOG_DATA_PER_BYTE * Uint(size) + + GasCosts.OPCODE_LOG_TOPIC * Uint(num_topics) + extend_memory.cost, ) diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/memory.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/memory.py index 3a242ba2f7a..93861811559 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/memory.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/memory.py @@ -16,8 +16,7 @@ from .. import Evm from ..gas import ( - GAS_BASE, - GAS_VERY_LOW, + GasCosts, calculate_gas_extend_memory, charge_gas, ) @@ -46,7 +45,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, GasCosts.OPCODE_MSTORE_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -77,7 +76,7 @@ def mstore8(evm: Evm) -> None: evm.memory, [(start_position, U256(1))] ) - charge_gas(evm, GAS_VERY_LOW + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_MSTORE8_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -105,7 +104,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, GasCosts.OPCODE_MLOAD_BASE + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -132,7 +131,7 @@ def msize(evm: Evm) -> None: pass # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_MSIZE) # OPERATION push(evm.stack, U256(len(evm.memory))) diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/stack.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/stack.py index 0fc0d3fe4b5..9104c1e9749 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/stack.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/stack.py @@ -17,7 +17,10 @@ from .. import Evm, stack from ..exceptions import StackUnderflowError -from ..gas import GAS_BASE, GAS_VERY_LOW, charge_gas +from ..gas import ( + GasCosts, + charge_gas, +) from ..memory import buffer_read @@ -35,7 +38,7 @@ def pop(evm: Evm) -> None: stack.pop(evm.stack) # GAS - charge_gas(evm, GAS_BASE) + charge_gas(evm, GasCosts.OPCODE_POP) # OPERATION pass @@ -62,7 +65,7 @@ def push_n(evm: Evm, num_bytes: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_PUSH) # OPERATION data_to_push = U256.from_be_bytes( @@ -92,7 +95,7 @@ def dup_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_DUP) if item_number >= len(evm.stack): raise StackUnderflowError data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] @@ -124,7 +127,7 @@ def swap_n(evm: Evm, item_number: int) -> None: pass # GAS - charge_gas(evm, GAS_VERY_LOW) + charge_gas(evm, GasCosts.OPCODE_SWAP) if item_number >= len(evm.stack): raise StackUnderflowError evm.stack[-1], evm.stack[-1 - item_number] = ( diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/storage.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/storage.py index 154b4fd47bb..0b2a1cce8aa 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/storage.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/storage.py @@ -16,10 +16,7 @@ from ...state import get_storage, set_storage from .. import Evm from ..gas import ( - GAS_COLD_STORAGE_WRITE, - GAS_SLOAD, - GAS_STORAGE_SET, - REFUND_STORAGE_CLEAR, + GasCosts, charge_gas, ) from ..stack import pop, push @@ -40,7 +37,7 @@ def sload(evm: Evm) -> None: key = pop(evm.stack).to_be_bytes32() # GAS - charge_gas(evm, GAS_SLOAD) + charge_gas(evm, GasCosts.SLOAD) # OPERATION value = get_storage( @@ -71,12 +68,12 @@ def sstore(evm: Evm) -> None: state = evm.message.block_env.state current_value = get_storage(state, evm.message.current_target, key) if new_value != 0 and current_value == 0: - gas_cost = GAS_STORAGE_SET + gas_cost = GasCosts.STORAGE_SET else: - gas_cost = GAS_COLD_STORAGE_WRITE + gas_cost = GasCosts.COLD_STORAGE_WRITE if new_value == 0 and current_value != 0: - evm.refund_counter += REFUND_STORAGE_CLEAR + evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR charge_gas(evm, gas_cost) diff --git a/src/ethereum/forks/tangerine_whistle/vm/instructions/system.py b/src/ethereum/forks/tangerine_whistle/vm/instructions/system.py index 50a359402b1..6ef0f1a0015 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/instructions/system.py +++ b/src/ethereum/forks/tangerine_whistle/vm/instructions/system.py @@ -33,14 +33,7 @@ incorporate_child_on_success, ) from ..gas import ( - GAS_CALL, - GAS_CALL_VALUE, - GAS_CREATE, - GAS_NEW_ACCOUNT, - GAS_SELF_DESTRUCT, - GAS_SELF_DESTRUCT_NEW_ACCOUNT, - GAS_ZERO, - REFUND_SELF_DESTRUCT, + GasCosts, calculate_gas_extend_memory, calculate_message_call_gas, charge_gas, @@ -74,7 +67,7 @@ def create(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_CREATE + extend_memory.cost) + charge_gas(evm, GasCosts.OPCODE_CREATE_BASE + extend_memory.cost) create_message_gas = max_message_call_gas(Uint(evm.gas_left)) evm.gas_left -= create_message_gas @@ -163,7 +156,7 @@ def return_(evm: Evm) -> None: evm.memory, [(memory_start_position, memory_size)] ) - charge_gas(evm, GAS_ZERO + extend_memory.cost) + charge_gas(evm, GasCosts.ZERO + extend_memory.cost) # OPERATION evm.memory += b"\x00" * extend_memory.expand_by @@ -268,14 +261,14 @@ def call(evm: Evm) -> None: code_address = to _account_exists = account_exists(evm.message.block_env.state, to) - create_gas_cost = Uint(0) if _account_exists else GAS_NEW_ACCOUNT - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + create_gas_cost = Uint(0) if _account_exists else GasCosts.NEW_ACCOUNT + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + create_gas_cost + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + create_gas_cost + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -335,13 +328,13 @@ def callcode(evm: Evm) -> None: (memory_output_start_position, memory_output_size), ], ) - transfer_gas_cost = Uint(0) if value == 0 else GAS_CALL_VALUE + transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE message_call_gas = calculate_message_call_gas( value, gas, Uint(evm.gas_left), extend_memory.cost, - GAS_CALL + transfer_gas_cost, + GasCosts.OPCODE_CALL_BASE + transfer_gas_cost, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) @@ -386,9 +379,9 @@ def selfdestruct(evm: Evm) -> None: beneficiary = to_address_masked(pop(evm.stack)) # GAS - gas_cost = GAS_SELF_DESTRUCT + gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE if not account_exists(evm.message.block_env.state, beneficiary): - gas_cost += GAS_SELF_DESTRUCT_NEW_ACCOUNT + gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT originator = evm.message.current_target @@ -399,7 +392,7 @@ def selfdestruct(evm: Evm) -> None: parent_evm = parent_evm.message.parent_evm if originator not in refunded_accounts: - evm.refund_counter += REFUND_SELF_DESTRUCT + evm.refund_counter += GasCosts.REFUND_SELF_DESTRUCT charge_gas(evm, gas_cost) @@ -459,7 +452,11 @@ def delegatecall(evm: Evm) -> None: ], ) message_call_gas = calculate_message_call_gas( - U256(0), gas, Uint(evm.gas_left), extend_memory.cost, GAS_CALL + U256(0), + gas, + Uint(evm.gas_left), + extend_memory.cost, + GasCosts.OPCODE_CALL_BASE, ) charge_gas(evm, message_call_gas.cost + extend_memory.cost) diff --git a/src/ethereum/forks/tangerine_whistle/vm/interpreter.py b/src/ethereum/forks/tangerine_whistle/vm/interpreter.py index e6e7c7729c4..a687e748de3 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/interpreter.py +++ b/src/ethereum/forks/tangerine_whistle/vm/interpreter.py @@ -42,7 +42,7 @@ touch_account, ) from ..vm import Message -from ..vm.gas import GAS_CODE_DEPOSIT_PER_BYTE, charge_gas +from ..vm.gas import GasCosts, charge_gas from ..vm.precompiled_contracts.mapping import PRE_COMPILED_CONTRACTS from . import Evm from .exceptions import ( @@ -158,7 +158,7 @@ def process_create_message(message: Message) -> Evm: if not evm.error: contract_code = evm.output contract_code_gas = ( - Uint(len(contract_code)) * GAS_CODE_DEPOSIT_PER_BYTE + ulen(contract_code) * GasCosts.CODE_DEPOSIT_PER_BYTE ) try: charge_gas(evm, contract_code_gas) diff --git a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ecrecover.py b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ecrecover.py index b6d23a58a89..17a0174f6ed 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ecrecover.py @@ -19,7 +19,7 @@ from ethereum.utils.byte import left_pad_zero_bytes from ...vm import Evm -from ...vm.gas import GAS_PRECOMPILE_ECRECOVER, charge_gas +from ...vm.gas import GasCosts, charge_gas from ...vm.memory import buffer_read @@ -37,7 +37,7 @@ def ecrecover(evm: Evm) -> None: data = evm.message.data # GAS - charge_gas(evm, GAS_PRECOMPILE_ECRECOVER) + charge_gas(evm, GasCosts.PRECOMPILE_ECRECOVER) # OPERATION message_hash_bytes = buffer_read(data, U256(0), U256(32)) diff --git a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/identity.py b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/identity.py index 133a4832bf8..cdbd61f5b0d 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/identity.py +++ b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/identity.py @@ -17,8 +17,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_IDENTITY_BASE, - GAS_PRECOMPILE_IDENTITY_PER_WORD, + GasCosts, charge_gas, ) @@ -39,8 +38,8 @@ def identity(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_IDENTITY_BASE - + GAS_PRECOMPILE_IDENTITY_PER_WORD * word_count, + GasCosts.PRECOMPILE_IDENTITY_BASE + + GasCosts.PRECOMPILE_IDENTITY_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ripemd160.py b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ripemd160.py index d4e28adf0ad..eafdf08c365 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ripemd160.py +++ b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/ripemd160.py @@ -20,8 +20,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_RIPEMD160_BASE, - GAS_PRECOMPILE_RIPEMD160_PER_WORD, + GasCosts, charge_gas, ) @@ -42,8 +41,8 @@ def ripemd160(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_RIPEMD160_BASE - + GAS_PRECOMPILE_RIPEMD160_PER_WORD * word_count, + GasCosts.PRECOMPILE_RIPEMD160_BASE + + GasCosts.PRECOMPILE_RIPEMD160_PER_WORD * word_count, ) # OPERATION diff --git a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/sha256.py b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/sha256.py index 04dfef6730d..0a9f67e8441 100644 --- a/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/sha256.py +++ b/src/ethereum/forks/tangerine_whistle/vm/precompiled_contracts/sha256.py @@ -19,8 +19,7 @@ from ...vm import Evm from ...vm.gas import ( - GAS_PRECOMPILE_SHA256_BASE, - GAS_PRECOMPILE_SHA256_PER_WORD, + GasCosts, charge_gas, ) @@ -41,8 +40,8 @@ def sha256(evm: Evm) -> None: word_count = ceil32(Uint(len(data))) // Uint(32) charge_gas( evm, - GAS_PRECOMPILE_SHA256_BASE - + GAS_PRECOMPILE_SHA256_PER_WORD * word_count, + GasCosts.PRECOMPILE_SHA256_BASE + + GasCosts.PRECOMPILE_SHA256_PER_WORD * word_count, ) # OPERATION 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 87a8907b048..ba4fbd5f221 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 @@ -2670,7 +2670,7 @@ def test_bal_gas_limit_boundary( Test the BAL max items gas limit boundary for an empty block. The consensus rule requires - ``bal_items <= block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM``. + ``bal_items <= block_gas_limit // BLOCK_ACCESS_LIST_ITEM``. The boundary gas limit is derived from the fork's system-contract BAL footprint. At the boundary the check passes; one below it fails. """ @@ -2678,7 +2678,7 @@ def test_bal_gas_limit_boundary( # bal_items <= block_gas_limit // ITEM_COST min_gas_limit = ( fork.empty_block_bal_item_count() - * fork.gas_costs().GAS_BLOCK_ACCESS_LIST_ITEM + * fork.gas_costs().BLOCK_ACCESS_LIST_ITEM ) gas_limit = min_gas_limit + boundary_offset 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 68321d8e3b1..adcbba9b944 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 @@ -124,16 +124,16 @@ def test_bal_sstore_and_oog( intrinsic_gas_cost = fork.transaction_intrinsic_cost_calculator()() - # Full cost: PUSHes + SSTORE (GAS_COLD_STORAGE_ACCESS + GAS_STORAGE_SET) + # Full cost: PUSHes + SSTORE (COLD_STORAGE_ACCESS + STORAGE_SET) full_cost = storage_contract_code.gas_cost(fork) # Push cost for stipend boundary calculations push_code = Op.PUSH1(0x42) + Op.PUSH1(0x01) push_cost = push_code.gas_cost(fork) - # GAS_CALL_STIPEND is a threshold check, not a gas cost + # CALL_STIPEND is a threshold check, not a gas cost # Keep from gas_costs - stipend = fork.gas_costs().GAS_CALL_STIPEND + stipend = fork.gas_costs().CALL_STIPEND if out_of_gas_at == OutOfGasAt.EIP_2200_STIPEND: # 2300 after PUSHes (fails stipend check: 2300 <= 2300) @@ -561,7 +561,7 @@ def test_bal_call_no_delegation_oog_after_target_access( - target is always empty - required for create cost - value=1 (greater than 0) - required for create cost - The create_cost (GAS_NEW_ACCOUNT = 25000) is charged only for value + The create_cost (NEW_ACCOUNT = 25000) is charged only for value transfers to empty accounts, creating the gap tested here. """ diff --git a/tests/benchmark/compute/instruction/test_system.py b/tests/benchmark/compute/instruction/test_system.py index 4f9161ae213..551a1e242d0 100644 --- a/tests/benchmark/compute/instruction/test_system.py +++ b/tests/benchmark/compute/instruction/test_system.py @@ -73,7 +73,7 @@ def loop(threshold: int) -> Bytecode: intrinsic_cost_calc = fork.transaction_intrinsic_cost_calculator() intrinsic_cost = intrinsic_cost_calc() - access_list_addr_cost = fork.gas_costs().GAS_TX_ACCESS_LIST_ADDRESS + access_list_addr_cost = fork.gas_costs().TX_ACCESS_LIST_ADDRESS txs = [] remaining_gas = gas_benchmark_value diff --git a/tests/benchmark/compute/precompile/test_alt_bn128.py b/tests/benchmark/compute/precompile/test_alt_bn128.py index 6466f554e7e..3078f3a422c 100644 --- a/tests/benchmark/compute/precompile/test_alt_bn128.py +++ b/tests/benchmark/compute/precompile/test_alt_bn128.py @@ -457,8 +457,8 @@ def test_bn128_pairings_amortized( size_per_pairing = 192 gsc = fork.gas_costs() - base_cost = gsc.GAS_PRECOMPILE_ECPAIRING_BASE - pairing_cost = gsc.GAS_PRECOMPILE_ECPAIRING_PER_POINT + base_cost = gsc.PRECOMPILE_ECPAIRING_BASE + pairing_cost = gsc.PRECOMPILE_ECPAIRING_PER_POINT intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() mem_exp_gas_calculator = fork.memory_expansion_gas_calculator() warm_account_access_cost = Op.STATICCALL( @@ -571,8 +571,8 @@ def test_ec_pairing( intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() mem_exp = fork.memory_expansion_gas_calculator() precompile_cost = ( - gsc.GAS_PRECOMPILE_ECPAIRING_BASE - + gsc.GAS_PRECOMPILE_ECPAIRING_PER_POINT * num_pairs + gsc.PRECOMPILE_ECPAIRING_BASE + + gsc.PRECOMPILE_ECPAIRING_PER_POINT * num_pairs ) # Each iteration: STATICCALL ecpairing at advancing calldata offset, @@ -609,7 +609,7 @@ def test_ec_pairing( per_variant_gas = ( iteration_cost + pair_size * 16 - + words_per_variant * (gsc.GAS_COPY + gsc.GAS_MEMORY) + + words_per_variant * (gsc.OPCODE_COPY_PER_WORD + gsc.MEMORY_PER_WORD) ) empty_intrinsic = intrinsic_gas_calculator( calldata=[], return_cost_deducted_prior_execution=True @@ -640,7 +640,7 @@ def test_ec_pairing( per_tx_gas - execution_intrinsic - setup_cost - - math.ceil(len(calldata) / 32) * gsc.GAS_COPY + - math.ceil(len(calldata) / 32) * gsc.OPCODE_COPY_PER_WORD - mem_exp(new_bytes=len(calldata) + 32) ) diff --git a/tests/benchmark/compute/precompile/test_identity.py b/tests/benchmark/compute/precompile/test_identity.py index 56198ef1e14..206e813cf79 100644 --- a/tests/benchmark/compute/precompile/test_identity.py +++ b/tests/benchmark/compute/precompile/test_identity.py @@ -24,8 +24,8 @@ def test_identity( optimal_input_length = calculate_optimal_input_length( available_gas=gas_available, fork=fork, - static_cost=gas_costs.GAS_PRECOMPILE_IDENTITY_BASE, - per_word_dynamic_cost=gas_costs.GAS_PRECOMPILE_IDENTITY_PER_WORD, + static_cost=gas_costs.PRECOMPILE_IDENTITY_BASE, + per_word_dynamic_cost=gas_costs.PRECOMPILE_IDENTITY_PER_WORD, bytes_per_unit_of_work=1, ) diff --git a/tests/benchmark/compute/precompile/test_ripemd160.py b/tests/benchmark/compute/precompile/test_ripemd160.py index 75aef42266a..af415839082 100644 --- a/tests/benchmark/compute/precompile/test_ripemd160.py +++ b/tests/benchmark/compute/precompile/test_ripemd160.py @@ -24,8 +24,8 @@ def test_ripemd160( optimal_input_length = calculate_optimal_input_length( available_gas=gas_available, fork=fork, - static_cost=gas_costs.GAS_PRECOMPILE_RIPEMD160_BASE, - per_word_dynamic_cost=gas_costs.GAS_PRECOMPILE_RIPEMD160_PER_WORD, + static_cost=gas_costs.PRECOMPILE_RIPEMD160_BASE, + per_word_dynamic_cost=gas_costs.PRECOMPILE_RIPEMD160_PER_WORD, bytes_per_unit_of_work=64, ) diff --git a/tests/benchmark/compute/precompile/test_sha256.py b/tests/benchmark/compute/precompile/test_sha256.py index def1d35bdae..9cc8a4bec29 100644 --- a/tests/benchmark/compute/precompile/test_sha256.py +++ b/tests/benchmark/compute/precompile/test_sha256.py @@ -24,8 +24,8 @@ def test_sha256( optimal_input_length = calculate_optimal_input_length( available_gas=gas_available, fork=fork, - static_cost=gas_costs.GAS_PRECOMPILE_SHA256_BASE, - per_word_dynamic_cost=gas_costs.GAS_PRECOMPILE_SHA256_PER_WORD, + static_cost=gas_costs.PRECOMPILE_SHA256_BASE, + per_word_dynamic_cost=gas_costs.PRECOMPILE_SHA256_PER_WORD, bytes_per_unit_of_work=64, ) diff --git a/tests/benchmark/compute/scenario/test_transaction_types.py b/tests/benchmark/compute/scenario/test_transaction_types.py index 8ee1ed6546b..b23d3180d22 100644 --- a/tests/benchmark/compute/scenario/test_transaction_types.py +++ b/tests/benchmark/compute/scenario/test_transaction_types.py @@ -268,13 +268,13 @@ def test_ether_transfers_to_precompile( @pytest.fixture def total_cost_floor_per_token(fork: Fork) -> int: """Total cost floor per token (EIP-7623).""" - return fork.gas_costs().GAS_TX_DATA_TOKEN_FLOOR + return fork.gas_costs().TX_DATA_TOKEN_FLOOR @pytest.fixture def total_cost_standard_per_token(fork: Fork) -> int: """Standard cost per token (EIP-7623).""" - return fork.gas_costs().GAS_TX_DATA_TOKEN_STANDARD + return fork.gas_costs().TX_DATA_TOKEN_STANDARD def calldata_generator( @@ -286,11 +286,11 @@ def calldata_generator( # Gas cost calculation based on EIP-7683: (https://eips.ethereum.org/EIPS/eip-7683) # # tx.gasUsed = 21000 + max( - # GAS_TX_DATA_TOKEN_STANDARD * tokens_in_calldata + # TX_DATA_TOKEN_STANDARD * tokens_in_calldata # + execution_gas_used # + isContractCreation * (32000 + # INITCODE_WORD_COST * words(calldata)), - # GAS_TX_DATA_TOKEN_FLOOR * tokens_in_calldata) + # TX_DATA_TOKEN_FLOOR * tokens_in_calldata) # # Simplified in this test case: # - No execution gas used (no opcodes are executed) @@ -298,10 +298,10 @@ def calldata_generator( # # Therefore: # max_token_cost = - # max(GAS_TX_DATA_TOKEN_STANDARD, GAS_TX_DATA_TOKEN_FLOOR) + # max(TX_DATA_TOKEN_STANDARD, TX_DATA_TOKEN_FLOOR) # tx.gasUsed = 21000 + tokens_in_calldata * max_token_cost # - # Since max(GAS_TX_DATA_TOKEN_STANDARD, GAS_TX_DATA_TOKEN_FLOOR) = 10: + # Since max(TX_DATA_TOKEN_STANDARD, TX_DATA_TOKEN_FLOOR) = 10: # tx.gasUsed = 21000 + tokens_in_calldata * 10 # # Token accounting: @@ -421,8 +421,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.GAS_TX_ACCESS_LIST_ADDRESS - gas_per_storage_key = gas_costs.GAS_TX_ACCESS_LIST_STORAGE_KEY + gas_per_address = gas_costs.TX_ACCESS_LIST_ADDRESS + gas_per_storage_key = gas_costs.TX_ACCESS_LIST_STORAGE_KEY # Calculate number of storage keys we can fit gas_after_address = gas_for_access_list - gas_per_address @@ -594,7 +594,7 @@ def test_auth_transaction( total_refund += min( tx_gas_used // 5, ( - gas_costs.GAS_AUTH_PER_EMPTY_ACCOUNT + gas_costs.AUTH_PER_EMPTY_ACCOUNT - gas_costs.REFUND_AUTH_PER_EXISTING_ACCOUNT ) * auths_in_this_tx, diff --git a/tests/benchmark/stateful/bloatnet/test_multi_opcode.py b/tests/benchmark/stateful/bloatnet/test_multi_opcode.py index 050f3107eb8..4e38786bb37 100755 --- a/tests/benchmark/stateful/bloatnet/test_multi_opcode.py +++ b/tests/benchmark/stateful/bloatnet/test_multi_opcode.py @@ -208,7 +208,7 @@ def test_bloatnet_balance_opcode( # test_bloatnet_call_value_existing: # Same factory pattern as test_bloatnet_balance_opcode, but performs # CALL with value=1 wei to each factory contract. The subcall fails -# (insufficient gas for 24KB bytecode), but GAS_CALL_VALUE (9000 gas) +# (insufficient gas for 24KB bytecode), but CALL_VALUE (9000 gas) # is still charged on top of the cold account access cost. # # test_bloatnet_call_value_new_account: @@ -232,7 +232,7 @@ def test_bloatnet_call_value_existing( Benchmark CALL with value transfer to cold existing factory contracts. Unlike the existing CALL test which uses gas=1 and value=0, this test - passes value=1 wei per call, adding GAS_CALL_VALUE (9000 gas) to each + passes value=1 wei per call, adding CALL_VALUE (9000 gas) to each cold account access. The subcall fails (insufficient gas for bytecode execution), so value is not actually transferred, but the gas penalty is still charged. @@ -332,8 +332,8 @@ def test_bloatnet_call_value_new_account( (via the 2300 gas stipend), transferring value and creating a new account in the trie. Each iteration costs ~36,600 gas: - GAS_COLD_ACCOUNT_ACCESS: 2,600 - - GAS_CALL_VALUE: 9,000 - - GAS_NEW_ACCOUNT: 25,000 + - CALL_VALUE: 9,000 + - NEW_ACCOUNT: 25,000 This stresses trie expansion through massive new account creation. """ diff --git a/tests/berlin/eip2929_gas_cost_increases/test_create.py b/tests/berlin/eip2929_gas_cost_increases/test_create.py index d6bbb4570d8..3e73407f5d9 100644 --- a/tests/berlin/eip2929_gas_cost_increases/test_create.py +++ b/tests/berlin/eip2929_gas_cost_increases/test_create.py @@ -57,8 +57,8 @@ def test_create_insufficient_balance( A creator contract with zero balance attempts to create with value=1. The create aborts, and a subsequent BALANCE check on the would-be - contract address verifies it remains cold (costs G_COLD_ACCOUNT_ACCESS - instead of G_WARM_STORAGE_READ). + contract address verifies it remains cold (costs COLD_ACCOUNT_ACCESS + instead of WARM_STORAGE_READ). """ initcode = Op.STOP diff --git a/tests/byzantium/eip196_ec_add_mul/conftest.py b/tests/byzantium/eip196_ec_add_mul/conftest.py index 6fc5cae214d..42e0d29776f 100644 --- a/tests/byzantium/eip196_ec_add_mul/conftest.py +++ b/tests/byzantium/eip196_ec_add_mul/conftest.py @@ -27,9 +27,9 @@ def precompile_gas(precompile_address: Address, fork: Fork) -> int: gas_costs = fork.gas_costs() match precompile_address: case Spec.ECADD: - return gas_costs.GAS_PRECOMPILE_ECADD + return gas_costs.PRECOMPILE_ECADD case Spec.ECMUL: - return gas_costs.GAS_PRECOMPILE_ECMUL + return gas_costs.PRECOMPILE_ECMUL case _: raise ValueError( f"Unexpected precompile address: {precompile_address}" diff --git a/tests/byzantium/eip196_ec_add_mul/test_gas.py b/tests/byzantium/eip196_ec_add_mul/test_gas.py index b5fa091eb5f..bcf5012bc25 100644 --- a/tests/byzantium/eip196_ec_add_mul/test_gas.py +++ b/tests/byzantium/eip196_ec_add_mul/test_gas.py @@ -116,10 +116,10 @@ def test_invalid_gas_consumption( address_warm=False ).gas_cost(fork) - # Pre-EIP-2929: fixed G_call = 700; Berlin+: warm access cost. + # Pre-EIP-2929: fixed call = 700; Berlin+: warm access cost. gas_costs = fork.gas_costs() if fork >= Berlin: - staticcall_base = gas_costs.GAS_WARM_ACCESS + staticcall_base = gas_costs.WARM_ACCESS else: staticcall_base = 700 diff --git a/tests/byzantium/eip197_ec_pairing/conftest.py b/tests/byzantium/eip197_ec_pairing/conftest.py index 01bc4552191..8f3164caadf 100644 --- a/tests/byzantium/eip197_ec_pairing/conftest.py +++ b/tests/byzantium/eip197_ec_pairing/conftest.py @@ -23,6 +23,6 @@ def precompile_gas(input_data: bytes, fork: Fork) -> int: gas_costs = fork.gas_costs() k = len(input_data) // 192 return ( - gas_costs.GAS_PRECOMPILE_ECPAIRING_BASE - + gas_costs.GAS_PRECOMPILE_ECPAIRING_PER_POINT * k + gas_costs.PRECOMPILE_ECPAIRING_BASE + + gas_costs.PRECOMPILE_ECPAIRING_PER_POINT * k ) diff --git a/tests/byzantium/eip197_ec_pairing/test_gas.py b/tests/byzantium/eip197_ec_pairing/test_gas.py index a38b8d58431..1a1108c37f0 100644 --- a/tests/byzantium/eip197_ec_pairing/test_gas.py +++ b/tests/byzantium/eip197_ec_pairing/test_gas.py @@ -106,10 +106,10 @@ def test_invalid_gas_consumption( address_warm=False ).gas_cost(fork) - # Pre-EIP-2929: fixed G_call = 700; Berlin+: warm access cost. + # Pre-EIP-2929: fixed call = 700; Berlin+: warm access cost. gas_costs = fork.gas_costs() if fork >= Berlin: - staticcall_base = gas_costs.GAS_WARM_ACCESS + staticcall_base = gas_costs.WARM_ACCESS else: staticcall_base = 700 diff --git a/tests/cancun/eip4844_blobs/test_point_evaluation_precompile.py b/tests/cancun/eip4844_blobs/test_point_evaluation_precompile.py index 5e8e2cf1b54..952b41069ea 100644 --- a/tests/cancun/eip4844_blobs/test_point_evaluation_precompile.py +++ b/tests/cancun/eip4844_blobs/test_point_evaluation_precompile.py @@ -113,7 +113,7 @@ def call_gas(fork: Fork) -> int: Defaults to the point evaluation precompile gas cost, but can be parametrized to test different amounts. """ - return fork.gas_costs().GAS_PRECOMPILE_POINT_EVALUATION + return fork.gas_costs().PRECOMPILE_POINT_EVALUATION precompile_caller_storage_keys = count() @@ -202,9 +202,7 @@ def tx( sender=sender, data=precompile_input, to=precompile_caller_address, - gas_limit=fork.transitions_to() - .gas_costs() - .GAS_PRECOMPILE_POINT_EVALUATION + gas_limit=fork.transitions_to().gas_costs().PRECOMPILE_POINT_EVALUATION * 100, ) @@ -589,7 +587,7 @@ def test_tx_entry_point( # Consumed gas will only be the precompile gas if the proof is correct and # the call gas is sufficient. # Otherwise, the call gas will be consumed in full. - precompile_gas = fork.gas_costs().GAS_PRECOMPILE_POINT_EVALUATION + precompile_gas = fork.gas_costs().PRECOMPILE_POINT_EVALUATION consumed_gas = ( precompile_gas if call_gas >= precompile_gas and proof_correct @@ -714,7 +712,7 @@ def test_precompile_during_fork( Test calling the Point Evaluation Precompile during the appropriate fork. """ precompile_gas = ( - fork.transitions_to().gas_costs().GAS_PRECOMPILE_POINT_EVALUATION + fork.transitions_to().gas_costs().PRECOMPILE_POINT_EVALUATION ) # Blocks before fork blocks = [ diff --git a/tests/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py b/tests/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py index 1f313594db4..231f084a7f9 100644 --- a/tests/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py +++ b/tests/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py @@ -66,7 +66,7 @@ def call_gas(fork: Fork) -> int: Defaults to the point evaluation precompile gas cost, but can be parametrized to test different amounts. """ - return fork.gas_costs().GAS_PRECOMPILE_POINT_EVALUATION + return fork.gas_costs().PRECOMPILE_POINT_EVALUATION def copy_opcode_cost(fork: Fork, length: int) -> int: @@ -157,7 +157,7 @@ def tx( data=precompile_input, to=precompile_caller_address, value=0, - gas_limit=fork.gas_costs().GAS_PRECOMPILE_POINT_EVALUATION * 20, + gas_limit=fork.gas_costs().PRECOMPILE_POINT_EVALUATION * 20, ) @@ -172,7 +172,7 @@ def post( Prepare expected post for each test, depending on the success or failure of the precompile call and the gas usage. """ - precompile_gas = fork.gas_costs().GAS_PRECOMPILE_POINT_EVALUATION + precompile_gas = fork.gas_costs().PRECOMPILE_POINT_EVALUATION if proof == "correct": expected_gas_usage = ( call_gas if call_gas < precompile_gas else precompile_gas diff --git a/tests/frontier/opcodes/test_call.py b/tests/frontier/opcodes/test_call.py index e8345e9d5bb..95ad749a868 100644 --- a/tests/frontier/opcodes/test_call.py +++ b/tests/frontier/opcodes/test_call.py @@ -33,7 +33,7 @@ def test_call_large_offset_mstore( mem_offset = 128 # arbitrary number - # Cost of pushing args onto the stack (each PUSH costs G_VERY_LOW) + # Cost of pushing args onto the stack (each PUSH costs VERY_LOW) call_push_cost = (Op.PUSH1(0) * len(Op.CALL.kwargs)).gas_cost(fork) mstore_push_cost = (Op.PUSH1(0) * len(Op.MSTORE.kwargs)).gas_cost(fork) @@ -101,7 +101,7 @@ def test_call_memory_expands_on_early_revert( # arbitrary number, greater than memory size to trigger an expansion ret_size = 128 - # Cost of pushing args onto the stack (each PUSH costs G_VERY_LOW) + # Cost of pushing args onto the stack (each PUSH costs VERY_LOW) call_push_cost = (Op.PUSH1(0) * len(Op.CALL.kwargs)).gas_cost(fork) mstore_push_cost = (Op.PUSH1(0) * len(Op.MSTORE.kwargs)).gas_cost(fork) @@ -137,7 +137,7 @@ def test_call_memory_expands_on_early_revert( # call cost: # address_access_cost+new_acc_cost+memory_expansion_cost+value-stipend - # G_CALL_STIPEND is a threshold check, not a gas cost — keep from gas_costs + # CALL_STIPEND is a threshold check, not a gas cost — keep from gas_costs gsc = fork.gas_costs() call_cost = ( Op.CALL( @@ -146,7 +146,7 @@ def test_call_memory_expands_on_early_revert( account_new=True, new_memory_size=ret_size, ).gas_cost(fork) - - gsc.GAS_CALL_STIPEND + - gsc.CALL_STIPEND ) # mstore cost: base cost. No memory expansion cost needed, it was expanded @@ -186,7 +186,7 @@ def test_call_large_args_offset_size_zero( very_large_offset = 2**100 - # Cost of pushing args onto the stack (each PUSH costs G_VERY_LOW) + # Cost of pushing args onto the stack (each PUSH costs VERY_LOW) push_cost = (Op.PUSH1(0) * len(call_opcode.kwargs)).gas_cost(fork) call_measure = CodeGasMeasure( diff --git a/tests/frontier/opcodes/test_call_and_callcode_gas_calculation.py b/tests/frontier/opcodes/test_call_and_callcode_gas_calculation.py index 0c76bd57947..198045b3e3d 100644 --- a/tests/frontier/opcodes/test_call_and_callcode_gas_calculation.py +++ b/tests/frontier/opcodes/test_call_and_callcode_gas_calculation.py @@ -94,17 +94,17 @@ def sufficient_gas( cost = 700 # Pre-Berlin call cost gas_costs = fork.gas_costs() if is_value_call: - cost += gas_costs.GAS_CALL_VALUE + cost += gas_costs.CALL_VALUE if callee_opcode == Op.CALL: - cost += gas_costs.GAS_NEW_ACCOUNT + cost += gas_costs.NEW_ACCOUNT elif fork == Homestead: cost = 40 # Homestead call cost cost += 1 # mandatory callee gas allowance gas_costs = fork.gas_costs() if is_value_call: - cost += gas_costs.GAS_CALL_VALUE + cost += gas_costs.CALL_VALUE if callee_opcode == Op.CALL: - cost += gas_costs.GAS_NEW_ACCOUNT + cost += gas_costs.NEW_ACCOUNT else: raise Exception("Only forks Homestead and >=Byzantium supported") 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 8ef1d237eb1..62ec21497af 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 @@ -328,7 +328,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.GAS_TX_DATA_TOKEN_FLOOR + return gas_costs.TX_DATA_TOKEN_FLOOR @pytest.mark.xdist_group(name="bigmem") @@ -678,7 +678,7 @@ def intrinsic_cost_for_auth_list_length(auth_count: int) -> int: # EIP-7702 authorization transaction cost: # 21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * # access list storage key count + 2400 * access list address count + access - # list data cost + GAS_AUTH_PER_EMPTY_ACCOUNT_COST * authorization list + # list data cost + AUTH_PER_EMPTY_ACCOUNT_COST * authorization list # length # # There is no calldata and no storage keys in this test case. diff --git a/tests/osaka/eip7951_p256verify_precompiles/conftest.py b/tests/osaka/eip7951_p256verify_precompiles/conftest.py index 2c313fda41b..af45811a5ba 100644 --- a/tests/osaka/eip7951_p256verify_precompiles/conftest.py +++ b/tests/osaka/eip7951_p256verify_precompiles/conftest.py @@ -33,7 +33,7 @@ def vector_gas_value() -> int | None: @pytest.fixture def precompile_gas(vector_gas_value: int | None, fork: Fork) -> int: """Gas cost for the precompile.""" - gas = fork.gas_costs().GAS_PRECOMPILE_P256VERIFY + gas = fork.gas_costs().PRECOMPILE_P256VERIFY if vector_gas_value is not None: assert vector_gas_value == gas, ( f"Calculated gas {vector_gas_value} != Vector gas {gas}" diff --git a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py index b826fcd7389..183ba71686c 100644 --- a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -1101,7 +1101,7 @@ def test_precompile_will_return_success_with_tx_value( call_256verify_bytecode = ( Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) + Op.CALL( - gas=fork.gas_costs().GAS_PRECOMPILE_P256VERIFY, + gas=fork.gas_costs().PRECOMPILE_P256VERIFY, address=Spec.P256VERIFY, value=Op.CALLVALUE(), args_offset=0, @@ -1244,7 +1244,7 @@ def test_contract_creation_transaction( contract_bytecode = ( Op.CODECOPY(0, Op.SUB(Op.CODESIZE, len(input_data)), len(input_data)) + Op.CALL( - gas=fork.gas_costs().GAS_PRECOMPILE_P256VERIFY, + gas=fork.gas_costs().PRECOMPILE_P256VERIFY, address=Spec.P256VERIFY, value=0, args_offset=0, @@ -1311,7 +1311,7 @@ def test_contract_initcode( call_256verify_bytecode = ( Op.CODECOPY(0, Op.SUB(Op.CODESIZE, len(input_data)), len(input_data)) + Op.CALL( - gas=fork.gas_costs().GAS_PRECOMPILE_P256VERIFY, + gas=fork.gas_costs().PRECOMPILE_P256VERIFY, address=Spec.P256VERIFY, value=0, args_offset=0, diff --git a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py index 9bcca0ac450..1c8b5f141b8 100644 --- a/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py +++ b/tests/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py @@ -29,7 +29,7 @@ @pytest.fixture def precompile_gas(vector_gas_value: int | None, fork: TransitionFork) -> int: """Gas cost for the precompile.""" - gas = fork.transitions_to().gas_costs().GAS_PRECOMPILE_P256VERIFY + gas = fork.transitions_to().gas_costs().PRECOMPILE_P256VERIFY if vector_gas_value is not None: assert vector_gas_value == gas, ( f"Calculated gas {vector_gas_value} != Vector gas {gas}" diff --git a/tests/prague/eip2537_bls_12_381_precompiles/spec.py b/tests/prague/eip2537_bls_12_381_precompiles/spec.py index 053b4ad743e..a8bb7a3431c 100644 --- a/tests/prague/eip2537_bls_12_381_precompiles/spec.py +++ b/tests/prague/eip2537_bls_12_381_precompiles/spec.py @@ -299,8 +299,8 @@ def _pairing_gas_from_costs( def calc(input_length: int) -> int: k = input_length // Spec.LEN_PER_PAIR return ( - gas_costs.GAS_PRECOMPILE_BLS_PAIRING_PER_PAIR * k - + gas_costs.GAS_PRECOMPILE_BLS_PAIRING_BASE + gas_costs.PRECOMPILE_BLS_PAIRING_PER_PAIR * k + + gas_costs.PRECOMPILE_BLS_PAIRING_BASE ) return calc @@ -311,19 +311,19 @@ def build_gas_calculation_function_map( ) -> Dict[int, Callable[[int], int]]: """Build a gas calculation function map from fork gas costs.""" return { - Spec.G1ADD: lambda _: gas_costs.GAS_PRECOMPILE_BLS_G1ADD, + Spec.G1ADD: lambda _: gas_costs.PRECOMPILE_BLS_G1ADD, Spec.G1MSM: msm_gas_func_gen( BLS12Group.G1, len(PointG1() + Scalar()), - gas_costs.GAS_PRECOMPILE_BLS_G1MUL, + gas_costs.PRECOMPILE_BLS_G1MUL, ), - Spec.G2ADD: lambda _: gas_costs.GAS_PRECOMPILE_BLS_G2ADD, + Spec.G2ADD: lambda _: gas_costs.PRECOMPILE_BLS_G2ADD, Spec.G2MSM: msm_gas_func_gen( BLS12Group.G2, len(PointG2() + Scalar()), - gas_costs.GAS_PRECOMPILE_BLS_G2MUL, + gas_costs.PRECOMPILE_BLS_G2MUL, ), Spec.PAIRING: _pairing_gas_from_costs(gas_costs), - Spec.MAP_FP_TO_G1: lambda _: gas_costs.GAS_PRECOMPILE_BLS_G1MAP, - Spec.MAP_FP2_TO_G2: lambda _: gas_costs.GAS_PRECOMPILE_BLS_G2MAP, + Spec.MAP_FP_TO_G1: lambda _: gas_costs.PRECOMPILE_BLS_G1MAP, + Spec.MAP_FP2_TO_G2: lambda _: gas_costs.PRECOMPILE_BLS_G2MAP, } diff --git a/tests/prague/eip7623_increase_calldata_cost/spec.py b/tests/prague/eip7623_increase_calldata_cost/spec.py index ebca1ee7041..6527e5c69c5 100644 --- a/tests/prague/eip7623_increase_calldata_cost/spec.py +++ b/tests/prague/eip7623_increase_calldata_cost/spec.py @@ -24,5 +24,5 @@ class Spec: https://eips.ethereum.org/EIPS/eip-7623. """ - GAS_TX_DATA_TOKEN_STANDARD = 4 - GAS_TX_DATA_TOKEN_FLOOR = 10 + TX_DATA_TOKEN_STANDARD = 4 + TX_DATA_TOKEN_FLOOR = 10 diff --git a/tests/prague/eip7702_set_code_tx/spec.py b/tests/prague/eip7702_set_code_tx/spec.py index 2be51b6c99c..8f1eaac1fab 100644 --- a/tests/prague/eip7702_set_code_tx/spec.py +++ b/tests/prague/eip7702_set_code_tx/spec.py @@ -28,7 +28,7 @@ class Spec: SET_CODE_TX_TYPE = 0x04 MAGIC = 0x05 REFUND_AUTH_PER_EXISTING_ACCOUNT = 12_500 - GAS_AUTH_PER_EMPTY_ACCOUNT = 25_000 + AUTH_PER_EMPTY_ACCOUNT = 25_000 DELEGATION_DESIGNATION = Bytes("ef0100") RESET_DELEGATION_ADDRESS = Address(0) diff --git a/tests/prague/eip7702_set_code_tx/test_gas.py b/tests/prague/eip7702_set_code_tx/test_gas.py index b2b8233d1b4..7aea82b335a 100644 --- a/tests/prague/eip7702_set_code_tx/test_gas.py +++ b/tests/prague/eip7702_set_code_tx/test_gas.py @@ -800,7 +800,7 @@ def gas_test_parameter_args( if execution_gas_allowance: # Leave some gas for the execution of the test code. max_gas -= 1_000_000 - many_authorizations_count = max_gas // Spec.GAS_AUTH_PER_EMPTY_ACCOUNT + many_authorizations_count = max_gas // Spec.AUTH_PER_EMPTY_ACCOUNT cases += [ pytest.param( { @@ -876,7 +876,7 @@ def test_gas_cost( seen_authority.add(authority) discount_gas = ( - Spec.GAS_AUTH_PER_EMPTY_ACCOUNT - Spec.REFUND_AUTH_PER_EXISTING_ACCOUNT + Spec.AUTH_PER_EMPTY_ACCOUNT - Spec.REFUND_AUTH_PER_EXISTING_ACCOUNT ) * discounted_authorizations # We calculate the exact gas required to execute the test code. We add diff --git a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py index eeca854e337..fe48936c1d5 100644 --- a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -773,8 +773,9 @@ def test_set_code_to_contract_creator( ) @pytest.mark.with_all_call_opcodes @pytest.mark.filter_combinations( - lambda call_opcode, value, **_: "value" in call_opcode.kwargs - or value == 0, + lambda call_opcode, value, **_: ( + "value" in call_opcode.kwargs or value == 0 + ), reason="opcode does not support value argument", ) def test_set_code_to_self_caller( @@ -908,8 +909,9 @@ def test_set_code_max_depth_call_stack( [0, 1], ) @pytest.mark.filter_combinations( - lambda call_opcode, value, **_: "value" in call_opcode.kwargs - or value == 0, + lambda call_opcode, value, **_: ( + "value" in call_opcode.kwargs or value == 0 + ), reason="opcode does not support value argument", ) @pytest.mark.eels_base_coverage @@ -2916,8 +2918,7 @@ def test_set_code_to_precompile_not_enough_gas_for_precompile_execution( authorization_list_or_count=[auth], ) discount = min( - Spec.GAS_AUTH_PER_EMPTY_ACCOUNT - - Spec.REFUND_AUTH_PER_EXISTING_ACCOUNT, + Spec.AUTH_PER_EMPTY_ACCOUNT - Spec.REFUND_AUTH_PER_EXISTING_ACCOUNT, intrinsic_gas // 5, # max discount EIP-3529 ) @@ -3845,7 +3846,7 @@ def test_many_delegations( max_gas = env.gas_limit gas_for_delegations = max_gas - 21_000 - 20_000 - (3 * 2) - delegation_count = gas_for_delegations // Spec.GAS_AUTH_PER_EMPTY_ACCOUNT + delegation_count = gas_for_delegations // Spec.AUTH_PER_EMPTY_ACCOUNT success_slot = 1 entry_code = Op.SSTORE(success_slot, 1) + Op.STOP diff --git a/tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py b/tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py index 9bd855017f7..c81aff2a27b 100644 --- a/tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py +++ b/tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py @@ -1,7 +1,7 @@ """ Tests for EIP-150 SELFDESTRUCT operation gas costs. -EIP-150 introduced G_SELF_DESTRUCT for SELFDESTRUCT and precise gas +EIP-150 introduced a gas cost for the SELFDESTRUCT opcode and precise gas boundaries for state access during the operation. """ @@ -52,7 +52,7 @@ def calculate_selfdestruct_gas( originator_balance: int, ) -> int: """Calculate exact gas needed for SELFDESTRUCT.""" - # G_NEW_ACCOUNT: + # NEW_ACCOUNT: # - Pre-EIP-161 (TangerineWhistle): charged when beneficiary is dead # - Post-EIP-161 (>=SpuriousDragon): charged when beneficiary is dead # AND originator has balance > 0 @@ -351,13 +351,13 @@ def test_selfdestruct_to_account( code=Op.STOP, balance=beneficiary_initial_balance ) - # Determine if beneficiary is dead (for G_NEW_ACCOUNT calculation) + # Determine if beneficiary is dead (for NEW_ACCOUNT calculation) # Contract with code is NOT dead even with balance=0 beneficiary_dead = ( beneficiary_initial_balance == 0 and beneficiary == "eoa" ) - # Calculate exact gas for success (includes G_NEW_ACCOUNT if applicable) + # Calculate exact gas for success (includes NEW_ACCOUNT if applicable) inner_call_gas = calculate_selfdestruct_gas( fork, beneficiary_warm=warm, @@ -367,7 +367,7 @@ def test_selfdestruct_to_account( if not is_success: inner_call_gas -= 1 - # In BAL if: success OR G_NEW_ACCOUNT charged (OOG after access) + # In BAL if: success OR NEW_ACCOUNT charged (OOG after access) needs_new_account = False if beneficiary_dead: if fork >= SpuriousDragon: @@ -463,7 +463,7 @@ def test_selfdestruct_state_access_boundary( Test state access boundary for account beneficiaries. Consensus check: beneficiary must be accessed at base cost boundary, - before G_NEW_ACCOUNT is evaluated. + before NEW_ACCOUNT is evaluated. - exact_gas: beneficiary IS accessed (in BAL) - exact_gas_minus_1: beneficiary NOT accessed (not in BAL) @@ -478,14 +478,14 @@ def test_selfdestruct_state_access_boundary( code=Op.STOP, balance=beneficiary_initial_balance ) - # Determine if beneficiary is dead (for G_NEW_ACCOUNT calculation) + # Determine if beneficiary is dead (for NEW_ACCOUNT calculation) # Contract with code is NOT dead even with balance=0 beneficiary_dead = ( beneficiary_initial_balance == 0 and beneficiary == "eoa" ) # Calculate gas for state access boundary only (base + cold access) - # Does NOT include G_NEW_ACCOUNT + # Does NOT include NEW_ACCOUNT inner_call_gas = Op.SELFDESTRUCT( 0, # beneficiary address (generates a PUSH) address_warm=warm or fork < Berlin, @@ -497,7 +497,7 @@ def test_selfdestruct_state_access_boundary( # Determine if operation succeeds at this gas level # At state access boundary, we have enough gas for base + cold access - # Operation succeeds if NO G_NEW_ACCOUNT is needed: + # Operation succeeds if NO NEW_ACCOUNT is needed: # - Beneficiary is alive (has balance or has code) # - OR beneficiary is dead but originator_balance=0 (>=SpuriousDragon) needs_new_account = False @@ -507,7 +507,7 @@ def test_selfdestruct_state_access_boundary( else: needs_new_account = True - # At exact_gas: success if no G_NEW_ACCOUNT needed + # At exact_gas: success if no NEW_ACCOUNT needed # At exact_gas_minus_1: always OOG (before state access) operation_success = is_success and not needs_new_account @@ -602,7 +602,7 @@ def test_selfdestruct_to_precompile( # Precompiles are dead when they have no balance beneficiary_dead = beneficiary_initial_balance == 0 - # Calculate exact gas for success (includes G_NEW_ACCOUNT if applicable) + # Calculate exact gas for success (includes NEW_ACCOUNT if applicable) # Precompiles are always warm inner_call_gas = calculate_selfdestruct_gas( fork, @@ -613,7 +613,7 @@ def test_selfdestruct_to_precompile( if not is_success: inner_call_gas -= 1 - # In BAL if: success OR G_NEW_ACCOUNT charged (OOG after access) + # In BAL if: success OR NEW_ACCOUNT charged (OOG after access) needs_new_account = False if beneficiary_dead: if fork >= SpuriousDragon: @@ -700,7 +700,7 @@ def test_selfdestruct_to_precompile_state_access_boundary( Test state access boundary for precompile beneficiaries. Consensus check: precompile must be accessed at base cost boundary, - before G_NEW_ACCOUNT is evaluated. Precompiles are always warm. + before NEW_ACCOUNT is evaluated. Precompiles are always warm. - exact_gas: precompile IS accessed (in BAL) - exact_gas_minus_1: precompile NOT accessed (not in BAL) @@ -711,7 +711,7 @@ def test_selfdestruct_to_precompile_state_access_boundary( beneficiary_dead = beneficiary_initial_balance == 0 - # State access boundary: base cost only (no G_NEW_ACCOUNT) + # State access boundary: base cost only (no NEW_ACCOUNT) # Precompiles are always warm inner_call_gas = Op.SELFDESTRUCT( 0, address_warm=True, account_new=False @@ -720,7 +720,7 @@ def test_selfdestruct_to_precompile_state_access_boundary( if not is_success: inner_call_gas -= 1 - # Success at base cost if no G_NEW_ACCOUNT needed + # Success at base cost if no NEW_ACCOUNT needed needs_new_account = False if beneficiary_dead: if fork >= SpuriousDragon: @@ -802,7 +802,7 @@ def test_selfdestruct_to_system_contract( Test SELFDESTRUCT success boundary for system contract beneficiaries. System contracts are always warm (no cold access charge) and always have - code (so beneficiary is never dead, no G_NEW_ACCOUNT charge). + code (so beneficiary is never dead, no NEW_ACCOUNT charge). - exact_gas: succeeds, balance transferred - exact_gas_minus_1: OOG, operation fails @@ -952,7 +952,7 @@ def test_selfdestruct_to_self( Key characteristics: - Beneficiary is always warm (it's the executing contract) - Beneficiary is always alive (EIP-161 nonce=1) - - No G_NEW_ACCOUNT charge + - No NEW_ACCOUNT charge - No cold access charge (>=Berlin) - Balance is "transferred" to self (no net change until destruction) @@ -967,7 +967,7 @@ def test_selfdestruct_to_self( alice = pre.fund_eoa() victim_code = Op.SELFDESTRUCT(Op.ADDRESS) - # Gas: ADDRESS + SELFDESTRUCT (no cold access, no G_NEW_ACCOUNT) + # Gas: ADDRESS + SELFDESTRUCT (no cold access, no NEW_ACCOUNT) base_gas = Op.SELFDESTRUCT( Op.ADDRESS, address_warm=True, account_new=False ).gas_cost(fork) @@ -1135,7 +1135,7 @@ def test_initcode_selfdestruct_to_self( - During initcode, the contract has no code yet - Contract has nonce=1 (post-EIP-161) making it non-empty - Beneficiary is always warm (it's the executing contract) - - No G_NEW_ACCOUNT charge (contract has nonce > 0) + - No NEW_ACCOUNT charge (contract has nonce > 0) - No cold access charge (>=Berlin) Note: Gas boundary testing not possible for initcode since CREATE