Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions tests/cancun/eip1153_tstore/test_basic_tload.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
Address,
Alloc,
Environment,
Fork,
Op,
StateTestFiller,
Transaction,
)

from .spec import Spec, ref_spec_1153
from .spec import ref_spec_1153

REFERENCE_SPEC_GIT_PATH = ref_spec_1153.git_path
REFERENCE_SPEC_VERSION = ref_spec_1153.version
Expand Down Expand Up @@ -195,6 +196,7 @@ def test_basic_tload_other_after_tstore(
def test_basic_tload_gasprice(
state_test: StateTestFiller,
pre: Alloc,
fork: Fork,
) -> None:
"""
Ported .json vectors.
Expand Down Expand Up @@ -261,8 +263,8 @@ def test_basic_tload_gasprice(
post = {
address_to: Account(
storage={
slot_tload_nonzero_gas_price_result: Spec.TLOAD_GAS_COST,
slot_tload_zero_gas_price_result: Spec.TLOAD_GAS_COST,
slot_tload_nonzero_gas_price_result: Op.TLOAD.gas_cost(fork),
slot_tload_zero_gas_price_result: Op.TLOAD.gas_cost(fork),
slot_code_worked: 0x01,
}
)
Expand Down
15 changes: 3 additions & 12 deletions tests/cancun/eip1153_tstore/test_tstorage.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
)

from . import PytestParameterEnum
from .spec import Spec, ref_spec_1153
from .spec import ref_spec_1153

REFERENCE_SPEC_GIT_PATH = ref_spec_1153.git_path
REFERENCE_SPEC_VERSION = ref_spec_1153.version
Expand Down Expand Up @@ -217,49 +217,40 @@ class GasMeasureTestCases(PytestParameterEnum):
"description": "Test that tload() of an empty slot consumes "
"the expected gas.",
"bytecode": Op.TLOAD(10),
"overhead_cost": 3, # 1 x PUSH1
"extra_stack_items": 1,
"expected_gas": Spec.TLOAD_GAS_COST,
}
TSTORE_TLOAD = {
"description": "Test that tload() of a used slot consumes "
"the expected gas.",
"bytecode": Op.TSTORE(10, 10) + Op.TLOAD(10),
"overhead_cost": 3 * 3, # 3 x PUSH1
"extra_stack_items": 1,
"expected_gas": Spec.TSTORE_GAS_COST + Spec.TLOAD_GAS_COST,
}
TSTORE_COLD = {
"description": "Test that tstore() of a previously unused "
"slot consumes the expected gas.",
"bytecode": Op.TSTORE(10, 10),
"overhead_cost": 2 * 3, # 2 x PUSH1
"extra_stack_items": 0,
"expected_gas": Spec.TSTORE_GAS_COST,
}
TSTORE_WARM = {
"description": "Test that tstore() of a previously used slot "
"consumes the expected gas.",
"bytecode": Op.TSTORE(10, 10) + Op.TSTORE(10, 11),
"overhead_cost": 4 * 3, # 4 x PUSH1
"extra_stack_items": 0,
"expected_gas": 2 * Spec.TSTORE_GAS_COST,
}


@GasMeasureTestCases.parametrize()
def test_gas_usage(
state_test: StateTestFiller,
pre: Alloc,
fork: Fork,
bytecode: Bytecode,
expected_gas: int,
overhead_cost: int,
extra_stack_items: int,
) -> None:
"""Test that tstore and tload consume the expected gas."""
expected_gas = bytecode.gas_cost(fork)
gas_measure_bytecode = CodeGasMeasure(
code=bytecode,
overhead_cost=overhead_cost,
extra_stack_items=extra_stack_items,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@
StateTestFiller,
Transaction,
)
from execution_testing.forks import Cancun

from . import PytestParameterEnum
from .spec import Spec, ref_spec_1153
from .spec import ref_spec_1153

REFERENCE_SPEC_GIT_PATH = ref_spec_1153.git_path
REFERENCE_SPEC_VERSION = ref_spec_1153.version

pytestmark = [pytest.mark.valid_from("Cancun")]

PUSH_OPCODE_COST = 3
TSTORE_BYTECODE_GAS = Op.TSTORE(1, 69).gas_cost(Cancun)
Comment thread
marioevz marked this conversation as resolved.
Outdated


class DynamicCallContextTestCases(EnumMeta):
Expand Down Expand Up @@ -186,7 +187,7 @@ def __new__( # noqa: D102
"expected_callee_storage": {},
}

gas_limit = Spec.TSTORE_GAS_COST + (PUSH_OPCODE_COST * 2) - 1
gas_limit = TSTORE_BYTECODE_GAS - 1
contract_call = call_opcode(
gas=gas_limit, address=Op.CALLDATALOAD(0)
)
Expand Down
6 changes: 3 additions & 3 deletions tests/cancun/eip4844_blobs/test_blobhash_opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ def test_blobhash_gas_cost(
ensuring it matches `HASH_OPCODE_GAS = 3`. Includes both valid and invalid
random index sizes from the range `[0, 2**256-1]`, for tx types 2 and 3.
"""
blobhash_code = Op.BLOBHASH(blobhash_index)
gas_measure_code = CodeGasMeasure(
code=Op.BLOBHASH(blobhash_index),
overhead_cost=3,
code=blobhash_code,
extra_stack_items=1,
)

Expand Down Expand Up @@ -223,7 +223,7 @@ def test_blobhash_gas_cost(
]

tx = Transaction(**tx_kwargs)
post = {address: Account(storage={0: Spec.HASH_GAS_COST})}
post = {address: Account(storage={0: blobhash_code.gas_cost(fork)})}

state_test(
env=Environment(),
Expand Down
32 changes: 24 additions & 8 deletions tests/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
BlockchainTestFiller,
Bytecode,
Environment,
Fork,
Op,
StateTestFiller,
Storage,
Expand All @@ -24,8 +25,6 @@
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7516.md"
REFERENCE_SPEC_VERSION = "dcd2f4ede58a6ed908acd3cc2c198e9f605cbf3b"

BLOBBASEFEE_GAS = 2


@pytest.fixture
def call_gas() -> int:
Expand Down Expand Up @@ -127,22 +126,39 @@ def test_blobbasefee_stack_overflow(


@pytest.mark.parametrize(
"call_gas,call_fails",
"call_fails",
[
pytest.param(BLOBBASEFEE_GAS, False, id="enough_gas"),
pytest.param(BLOBBASEFEE_GAS - 1, True, id="out_of_gas"),
pytest.param(False, id="enough_gas"),
pytest.param(True, id="out_of_gas"),
],
)
@pytest.mark.valid_from("Cancun")
def test_blobbasefee_out_of_gas(
state_test: StateTestFiller,
pre: Alloc,
caller_address: Address,
callee_address: Address,
tx: Transaction,
fork: Fork,
call_fails: bool,
) -> None:
"""Tests that the BLOBBASEFEE opcode fails with insufficient gas."""
blobbasefee_gas = Op.BLOBBASEFEE.gas_cost(fork)
call_gas = blobbasefee_gas - 1 if call_fails else blobbasefee_gas

callee_code = Op.BLOBBASEFEE + Op.STOP
callee_address = pre.deploy_contract(callee_code)

caller_code = Op.SSTORE(
Op.SELFBALANCE,
Op.CALL(gas=call_gas, address=callee_address),
)
caller_address = pre.deploy_contract(caller_code)

tx = Transaction(
sender=pre.fund_eoa(),
gas_limit=1_000_000,
to=caller_address,
value=1,
)

post = {
caller_address: Account(
storage={1: 0 if call_fails else 1},
Expand Down
16 changes: 11 additions & 5 deletions tests/osaka/eip7823_modexp_upper_bounds/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,18 @@ def gas_measure_contract(
0,
)

gas_costs = fork.gas_costs()
extra_gas = (
gas_costs.G_WARM_ACCOUNT_ACCESS
+ (gas_costs.G_VERY_LOW * (len(Op.CALL.kwargs) - 1))
+ gas_costs.G_BASE # CALLDATASIZE
+ gas_costs.G_BASE # GAS
Op.CALL(
precompile_gas,
Spec.MODEXP_ADDRESS,
0,
0,
Op.CALLDATASIZE(),
0,
0,
address_warm=True,
).gas_cost(fork)
+ Op.GAS.gas_cost(fork) # second GAS in measurement
)

# Build the gas measurement contract code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,11 @@ def test_maximum_gas_refund(
storage = Storage()

# Base Operation: SSTORE(slot, 0)
iteration_cost = (
gas_costs.G_STORAGE_RESET + gas_costs.G_BASE + gas_costs.G_VERY_LOW
)
iteration_cost = Bytecode(
Comment thread
marioevz marked this conversation as resolved.
Outdated
Op.SSTORE(key_warm=True, original_value=1, new_value=0)
+ Op.PUSH0
+ Op.PUSH1(0)
).gas_cost(fork)
gas_refund = gas_costs.R_STORAGE_CLEAR

# EIP-3529: Reduction in refunds
Expand Down
20 changes: 12 additions & 8 deletions tests/osaka/eip7883_modexp_gas_increase/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ def total_tx_gas_needed(
)
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
# `gas_measure_contract` does at most 4 SSTOREs to cold slots.
sstore_gas = (
fork.gas_costs().G_STORAGE_SET + fork.gas_costs().G_COLD_SLOAD
) * 4
sstore_gas = Op.SSTORE(key_warm=False).gas_cost(fork) * 4
# Ensures that the precompile call is not starved by the 63/64 rule.
precompile_gas_with_margin = precompile_gas * 64 // 63
extra_gas = 100_000
Expand Down Expand Up @@ -157,12 +155,18 @@ def gas_measure_contract(
0,
)

gas_costs = fork.gas_costs()
extra_gas = (
gas_costs.G_WARM_ACCOUNT_ACCESS
+ (gas_costs.G_VERY_LOW * (len(call_opcode.kwargs) - 1))
+ gas_costs.G_BASE # CALLDATASIZE
+ gas_costs.G_BASE # GAS
call_opcode(
gas_used,
Spec.MODEXP_ADDRESS,
*value,
0,
Op.CALLDATASIZE(),
0,
0,
address_warm=True,
).gas_cost(fork)
+ Op.GAS.gas_cost(fork) # second GAS in measurement
)

# Build the gas measurement contract code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ def test_modexp_fork_transition(
args_size=Op.CALLDATASIZE,
)

gas_costs = fork.gas_costs()
extra_gas = (
gas_costs.G_WARM_ACCOUNT_ACCESS
+ (gas_costs.G_VERY_LOW * (len(Op.CALL.kwargs) - 2))
+ (gas_costs.G_BASE * 3)
Op.CALL(
address=Spec.MODEXP_ADDRESS,
args_size=Op.CALLDATASIZE,
address_warm=True,
).gas_cost(fork)
+ Op.GAS.gas_cost(fork) # second GAS in measurement
)
code = (
Op.CALLDATACOPY(dest_offset=0, offset=0, size=Op.CALLDATASIZE)
Expand Down
12 changes: 7 additions & 5 deletions tests/prague/eip7623_increase_calldata_cost/test_refunds.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,14 @@ def prefix_code_gas(fork: Fork, refund_type: RefundType) -> int:
"""Return the minimum execution gas cost due to the refund type."""
if RefundType.STORAGE_CLEAR in refund_type:
# Minimum code to generate a storage clear is Op.SSTORE(0, 0).
gas_costs = fork.gas_costs()
return (
gas_costs.G_COLD_SLOAD
+ gas_costs.G_STORAGE_RESET
+ (gas_costs.G_VERY_LOW * 2)
)
Op.SSTORE(
key_warm=False,
original_value=1,
new_value=0,
)
+ Op.PUSH1(0) * 2
).gas_cost(fork)
return 0


Expand Down
11 changes: 6 additions & 5 deletions tests/prague/eip7702_set_code_tx/test_eip_mainnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,18 @@ def test_eip_7702(
signer=auth_signer,
),
]
gas_costs = fork.gas_costs()
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
intrinsic_gas_cost = intrinsic_gas_cost_calc(
access_list=[],
authorization_list_or_count=authorization_list,
)
execution_cost = (
(gas_costs.G_COLD_SLOAD + gas_costs.G_STORAGE_SET) * 3
+ (gas_costs.G_VERY_LOW * 3)
+ (gas_costs.G_BASE * 3)
)
Op.SSTORE(key_warm=False) * 3
+ Op.PUSH1(0) * 3
+ Op.ORIGIN
+ Op.CALLER
+ Op.CALLVALUE
).gas_cost(fork)

tx = Transaction(
gas_limit=intrinsic_gas_cost + execution_cost,
Expand Down
27 changes: 10 additions & 17 deletions tests/prague/eip7702_set_code_tx/test_gas.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,20 +883,14 @@ def test_gas_cost(
# SSTORE opcodes in order to make sure that the refund is less than one
# fifth (EIP-3529) of the total gas used, so we can see the full discount
# being reflected in most of the tests.
gas_costs = fork.gas_costs()
gas_opcode_cost = gas_costs.G_BASE
gas_opcode_cost = Op.GAS.gas_cost(fork)
sstore_opcode_count = 10
push_opcode_count = (2 * (sstore_opcode_count)) - 1
push_opcode_cost = gas_costs.G_VERY_LOW * push_opcode_count
sstore_opcode_cost = gas_costs.G_STORAGE_SET * sstore_opcode_count
cold_storage_cost = gas_costs.G_COLD_SLOAD * sstore_opcode_count

execution_gas = (
gas_opcode_cost
+ push_opcode_cost
+ sstore_opcode_cost
+ cold_storage_cost
)
Op.GAS
+ Op.PUSH1(0) * push_opcode_count
+ Op.SSTORE(key_warm=False) * sstore_opcode_count
).gas_cost(fork)

# The first opcode that executes in the code is the GAS opcode, which costs
# 2 gas, so we subtract that from the expected gas measure.
Expand Down Expand Up @@ -1245,21 +1239,20 @@ def test_call_to_pre_authorized_oog(
# Callee tries to call the auth_signer which delegates
# to the delegation contract. The call instruction should out-of-gas
# because of the addition cost of the delegation account access.
callee_code = Bytecode(
Op.SSTORE(0, call_opcode(gas=0, address=auth_signer)),
)
callee_code = Op.SSTORE(0, call_opcode(gas=0, address=auth_signer))
callee_storage = Storage()
callee_storage[0] = 0xFF # Value other than 0 or 1. Should not be changed.
callee_address = pre.deploy_contract(callee_code, storage=callee_storage)

gas_costs = fork.gas_costs()
intrinsic_gas_cost_calculator = (
fork.transaction_intrinsic_cost_calculator()
)
tx_gas_limit = (
intrinsic_gas_cost_calculator()
+ len(call_opcode.kwargs) * gas_costs.G_VERY_LOW
+ (gas_costs.G_COLD_ACCOUNT_ACCESS * 2)
+ (
Op.PUSH1(0) * len(call_opcode.kwargs)
+ call_opcode(address_warm=False, delegated_address=True)
).gas_cost(fork)
- 1
)
tx = Transaction(
Expand Down
Loading
Loading