Skip to content

Commit

Permalink
new(tests): EOF - EIP-7069 - expand ext*call gas testing
Browse files Browse the repository at this point in the history
  • Loading branch information
pdobacz committed Aug 28, 2024
1 parent d3d3219 commit 6431581
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 33 deletions.
4 changes: 4 additions & 0 deletions tests/prague/eip7692_eof_v1/eip7069_extcall/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
slot_calldata_2 = next(_slot)
slot_cold_gas = next(_slot)
slot_warm_gas = next(_slot)
slot_oog_call_result = next(_slot)
slot_sanity_call_result = next(_slot)

slot_last_slot = next(_slot)

Expand All @@ -26,6 +28,8 @@

"""Storage values for common testing fields"""
value_code_worked = 0x2015
value_call_legacy_abort = 0
value_call_legacy_success = 1

"""Memory and storage value for calldata"""
value_calldata_1 = 0xC1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1
Expand Down
108 changes: 84 additions & 24 deletions tests/prague/eip7692_eof_v1/eip7069_extcall/test_gas.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@
import pytest

from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
from ethereum_test_tools.eof.v1 import Container, Section
from ethereum_test_tools.eof.v1 import Container
from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_vm import Bytecode, EVMCodeType

from .. import EOF_FORK_NAME
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION
from .helpers import slot_cold_gas, slot_warm_gas
from .helpers import (
slot_cold_gas,
slot_oog_call_result,
slot_sanity_call_result,
slot_warm_gas,
value_call_legacy_abort,
value_call_legacy_success,
)

REFERENCE_SPEC_GIT_PATH = REFERENCE_SPEC_GIT_PATH
REFERENCE_SPEC_VERSION = REFERENCE_SPEC_VERSION
Expand Down Expand Up @@ -50,25 +57,29 @@ def gas_test(

sender = pre.fund_eoa(10**18)

address_baseline = pre.deploy_contract(setup_code + tear_down_code)
address_subject = pre.deploy_contract(setup_code + subject_code + tear_down_code)
address_baseline = pre.deploy_contract(Container.Code(setup_code + tear_down_code))
address_subject = pre.deploy_contract(
Container.Code(setup_code + subject_code + tear_down_code)
)
# GAS, POP, CALL, 7 times PUSH1 - instructions charged for at every gas run
gas_single_gas_run = 2 + 2 + 100 + 7 * 3
address_legacy_harness = pre.deploy_contract(
code=(
# warm subject and baseline without executing
(Op.BALANCE(address_subject) + Op.POP + Op.BALANCE(address_baseline) + Op.POP)
# cold gas run
# Baseline gas run
+ (
Op.GAS
+ Op.CALL(address=address_subject, gas=500_000)
+ Op.CALL(address=address_baseline, gas=500_000)
+ Op.POP
+ Op.GAS
+ Op.SWAP1
+ Op.SUB
)
# Baseline gas run
# cold gas run
+ (
Op.GAS
+ Op.CALL(address=address_baseline, gas=500_000)
+ Op.CALL(address=address_subject, gas=500_000)
+ Op.POP
+ Op.GAS
+ Op.SWAP1
Expand All @@ -83,10 +94,30 @@ def gas_test(
+ Op.SWAP1
+ Op.SUB
)
# Store warm gas
+ (Op.DUP2 + Op.SWAP1 + Op.SUB + Op.PUSH2(slot_warm_gas) + Op.SSTORE)
# store cold gas
+ (Op.SWAP1 + Op.SUB + Op.PUSH2(slot_cold_gas) + Op.SSTORE)
# Store warm gas: DUP3 is the gas of the baseline gas run
+ (Op.DUP3 + Op.SWAP1 + Op.SUB + Op.PUSH2(slot_warm_gas) + Op.SSTORE)
# store cold gas: DUP2 is the gas of the baseline gas run
+ (Op.DUP2 + Op.SWAP1 + Op.SUB + Op.PUSH2(slot_cold_gas) + Op.SSTORE)
# oog gas run:
# - DUP7 is the gas of the baseline gas run, after other CALL args were pushed
# - subtract the gas charged by the harness
# - add warm gas charged by the subject
# - subtract 1 to cause OOG exception
+ Op.SSTORE(
slot_oog_call_result,
Op.CALL(
gas=Op.ADD(warm_gas - gas_single_gas_run - 1, Op.DUP7),
address=address_subject,
),
)
# sanity gas run: not subtracting 1 to see if enough gas makes the call succeed
+ Op.SSTORE(
slot_sanity_call_result,
Op.CALL(
gas=Op.ADD(warm_gas - gas_single_gas_run, Op.DUP7),
address=address_subject,
),
)
+ Op.STOP
),
evm_code_type=EVMCodeType.LEGACY, # Needs to be legacy to use GAS opcode
Expand All @@ -97,22 +128,46 @@ def gas_test(
storage={
slot_warm_gas: warm_gas,
slot_cold_gas: cold_gas,
slot_oog_call_result: value_call_legacy_abort,
slot_sanity_call_result: value_call_legacy_success,
},
),
}

tx = Transaction(to=address_legacy_harness, gas_limit=2_000_000, sender=sender)
tx = Transaction(to=address_legacy_harness, gas_limit=20_000_000, sender=sender)

state_test(env=env, pre=pre, tx=tx, post=post)


@pytest.mark.parametrize(
["opcode", "pre_setup", "cold_gas", "warm_gas"],
["opcode", "pre_setup", "cold_gas", "warm_gas", "new_account"],
[
pytest.param(Op.EXTCALL, Op.PUSH0, 2600, 100, id="EXTCALL"),
pytest.param(Op.EXTCALL, Op.PUSH1(1), 2600 + 9000, 100 + 9000, id="EXTCALL_with_value"),
pytest.param(Op.EXTDELEGATECALL, Op.NOOP, 2600, 100, id="EXTSTATICCALL"),
pytest.param(Op.EXTSTATICCALL, Op.NOOP, 2600, 100, id="EXTDELEGATECALL"),
pytest.param(Op.EXTCALL, Op.PUSH0, 2600, 100, False, id="EXTCALL"),
pytest.param(
Op.EXTCALL, Op.PUSH1(1), 2600 + 9000, 100 + 9000, False, id="EXTCALL_with_value"
),
pytest.param(Op.EXTDELEGATECALL, Op.NOOP, 2600, 100, False, id="EXTSTATICCALL"),
pytest.param(Op.EXTSTATICCALL, Op.NOOP, 2600, 100, False, id="EXTDELEGATECALL"),
pytest.param(Op.EXTCALL, Op.PUSH0, 2600, 100, True, id="EXTCALL_new_acc"),
pytest.param(
Op.EXTCALL,
Op.PUSH1(1),
2600 + 25000 + 9000,
100 + 25000 + 9000,
True,
id="EXTCALL_with_value_new_acc",
),
pytest.param(Op.EXTDELEGATECALL, Op.NOOP, 2600, 100, True, id="EXTSTATICCALL_new_acc"),
pytest.param(Op.EXTSTATICCALL, Op.NOOP, 2600, 100, True, id="EXTDELEGATECALL_new_acc"),
],
)
@pytest.mark.parametrize(
["mem_expansion_size", "mem_expansion_extra_gas"],
[
pytest.param(0, 0, id="no_mem_expansion"),
pytest.param(1, 3, id="1byte_mem_expansion"),
pytest.param(32, 3, id="1word_mem_expansion"),
pytest.param(33, 6, id="33bytes_mem_expansion"),
],
)
def test_ext_calls_gas(
Expand All @@ -122,18 +177,23 @@ def test_ext_calls_gas(
opcode: Op,
pre_setup: Op,
cold_gas: int,
warm_gas: int | None,
warm_gas: int,
new_account: bool,
mem_expansion_size: int,
mem_expansion_extra_gas: int,
):
"""Tests 4 variations of EXT*CALL gas, both warm and cold"""
address_target = pre.deploy_contract(Container(sections=[Section.Code(code=Op.STOP)]))
"""Tests variations of EXT*CALL gas, both warm and cold"""
address_target = (
pre.fund_eoa(0) if new_account else pre.deploy_contract(Container.Code(Op.STOP))
)

gas_test(
state_test,
state_env,
pre,
setup_code=pre_setup + Op.PUSH0 + Op.PUSH0 + Op.PUSH20(address_target),
setup_code=pre_setup + Op.PUSH1(mem_expansion_size) + Op.PUSH0 + Op.PUSH20(address_target),
subject_code=opcode,
tear_down_code=Op.STOP,
cold_gas=cold_gas,
warm_gas=warm_gas,
cold_gas=cold_gas + mem_expansion_extra_gas,
warm_gas=warm_gas + mem_expansion_extra_gas,
)
18 changes: 9 additions & 9 deletions tests/prague/eip7692_eof_v1/tracker.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,25 +379,25 @@
- [x] EXTDELEGATECALL from EOF to legacy fails (evmone-tests: state_tests/state_transition/eof_calls/eof1_extdelegatecall_legacy.json)
- [ ] EXTSTATICCALL forwards static mode (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_static.json)
- [x] EXTCALL with value success (evmone-tests: state_tests/state_transition/eof_calls/extcall_with_value.json)
- [ ] EXTCALL with value from EXTSTATICCALL (evmone-tests: state_tests/state_transition/eof_calls/extcall_static_with_value.json)
- [x] EXTCALL with value from EXTSTATICCALL (evmone-tests: state_tests/state_transition/eof_calls/extcall_static_with_value.json)
- [x] EXTCALL with value, not enough balance (evmone-tests: state_tests/state_transition/eof_calls/extcall_failing_with_value_balance_check.json)
- [ ] EXTCALL with value, check additional charge for value (evmone-tests: state_tests/state_transition/eof_calls/extcall_failing_with_value_additional_cost.json)
- [x] EXTCALL with value, check additional charge for value (evmone-tests: state_tests/state_transition/eof_calls/extcall_failing_with_value_additional_cost.json)
- [x] EXTCALL with gas not enough for callee to get 5000 gas (evmone-tests: state_tests/state_transition/eof_calls/extcall_min_callee_gas_failure_mode.json)
- [x] RETURNDATA* after EXTCALL (evmone-tests: state_tests/state_transition/eof_calls/extcall_output.json)
- [x] RETURNDATA* after EXTDELEGATECALL (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_output.json state_tests/state_transition/eof_calls/extdelegatecall_returndatasize.json state_tests/state_transition/eof_calls/returndatacopy.json state_tests/state_transition/eof_calls/returndataload.json)
- [x] RETURNDATA* after EXTSTATICCALL (evmone-tests: state_tests/state_transition/eof_calls/extstaticcall_output.json)
- [x] RETURNDATA* after aborted EXT*CALL (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_returndatasize_abort.json)
- [x] Failed EXTCALL clears returndata from previous EXTCALL (evmone-tests: state_tests/state_transition/eof_calls/extcall_clears_returndata.json)
- [ ] EXTCALL not enough gas for input memory charge (evmone-tests: state_tests/state_transition/eof_calls/extcall_memory.json)
- [ ] EXTDELEGATECALL not enough gas for input memory charge (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_memory.json)
- [ ] EXTSTATICCALL not enough gas for input memory charge (evmone-tests: state_tests/state_transition/eof_calls/extstaticcall_memory.json)
- [x] EXTCALL not enough gas for input memory charge (evmone-tests: state_tests/state_transition/eof_calls/extcall_memory.json)
- [x] EXTDELEGATECALL not enough gas for input memory charge (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_memory.json)
- [x] EXTSTATICCALL not enough gas for input memory charge (evmone-tests: state_tests/state_transition/eof_calls/extstaticcall_memory.json)
- [x] EXTCALL exception due to target address overflow (bits set in high 12 bytes) (evmone-tests: state_tests/state_transition/eof_calls/extcall_ase_ready_violation.json)
- [x] EXTDELEGATECALL exception due to target address overflow (bits set in high 12 bytes) (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_ase_ready_violation.json)
- [x] EXTSTATICCALL exception due to target address overflow (bits set in high 12 bytes) (evmone-tests: state_tests/state_transition/eof_calls/extstaticcall_ase_ready_violation.json)
- [ ] EXTCALL not enough gas for warming up target address (evmone-tests: state_tests/state_transition/eof_calls/extcall_cold_oog.json)
- [ ] EXTDELEGATECALL not enough gas for warming up target address (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_cold_oog.json)
- [ ] EXTSTATICCALL not enough gas for warming up target address (evmone-tests: state_tests/state_transition/eof_calls/extstaticcall_cold_oog.json)
- [ ] EXTCALL not enough gas for account creation cost (transfer value to non-existing account) (evmone-tests: state_tests/state_transition/eof_calls/extcall_value_zero_to_nonexistent_account.json)
- [x] EXTCALL not enough gas for warming up target address (evmone-tests: state_tests/state_transition/eof_calls/extcall_cold_oog.json)
- [x] EXTDELEGATECALL not enough gas for warming up target address (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_cold_oog.json)
- [x] EXTSTATICCALL not enough gas for warming up target address (evmone-tests: state_tests/state_transition/eof_calls/extstaticcall_cold_oog.json)
- [x] EXTCALL not enough gas for account creation cost (transfer value to non-existing account) (evmone-tests: state_tests/state_transition/eof_calls/extcall_value_zero_to_nonexistent_account.json)
- [x] OOG after EXTCALL (evmone-tests: state_tests/state_transition/eof_calls/extcall_then_oog.json)
- [x] OOG after EXTDELEGATECALL (evmone-tests: state_tests/state_transition/eof_calls/extdelegatecall_then_oog.json)
- [x] OOG after EXTSTATICCALL (evmone-tests: state_tests/state_transition/eof_calls/extstaticcall_then_oog.json)
Expand Down
1 change: 1 addition & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ makereport
marioevz
markdownlint
md
mem
metaclass
mixhash
mkdocs
Expand Down

0 comments on commit 6431581

Please sign in to comment.