forked from ethereum/execution-spec-tests
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new(tests) Call Gas Testing for EXT*CALL
Test call gas for EXT*CALL, using a legacy harness. Signed-off-by: Danno Ferrin <[email protected]>
- Loading branch information
Showing
2 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
tests/prague/eip7692_eof_v1/eip7069_extcall/test_gas.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
""" | ||
abstract: Tests [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069) | ||
Tests gas comsumption | ||
""" # noqa: E501 | ||
|
||
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.vm.opcode import Opcodes as Op | ||
from ethereum_test_vm import Opcodes, Bytecode | ||
|
||
from .. import EOF_FORK_NAME | ||
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION | ||
from .helpers import ( | ||
slot_cold_gas, | ||
slot_warm_gas, | ||
) | ||
|
||
REFERENCE_SPEC_GIT_PATH = REFERENCE_SPEC_GIT_PATH | ||
REFERENCE_SPEC_VERSION = REFERENCE_SPEC_VERSION | ||
|
||
pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) | ||
|
||
|
||
def gas_test( | ||
state_test: StateTestFiller, | ||
pre: Alloc, | ||
setup_code: Bytecode, | ||
subject_code: Bytecode, | ||
tear_down_code: Bytecode, | ||
cold_gas: int, | ||
warm_gas: int | None = None, | ||
): | ||
if cold_gas <= 0: | ||
raise ValueError(f"Target gas allocations (warm_gas) must be > 0, got {cold_gas}") | ||
if warm_gas is None: | ||
warm_gas = cold_gas | ||
|
||
env = Environment() | ||
|
||
sender = pre.fund_eoa(10**18) | ||
|
||
address_baseline = pre.deploy_contract( | ||
Container(sections=[Section.Code(code=setup_code + tear_down_code)]) | ||
) | ||
address_subject = pre.deploy_contract( | ||
Container(sections=[Section.Code(code=setup_code + subject_code + tear_down_code)]) | ||
) | ||
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 | ||
+ ( | ||
Op.GAS | ||
+ Op.CALL(address=address_subject, gas=500_000) | ||
+ Op.POP | ||
+ Op.GAS | ||
+ Op.SWAP1 | ||
+ Op.SUB | ||
) | ||
# Baseline gas run | ||
+ ( | ||
Op.GAS | ||
+ Op.CALL(address=address_baseline, gas=500_000) | ||
+ Op.POP | ||
+ Op.GAS | ||
+ Op.SWAP1 | ||
+ Op.SUB | ||
) | ||
# warm gas run | ||
+ ( | ||
Op.GAS | ||
+ Op.CALL(address=address_subject, gas=500_000) | ||
+ Op.POP | ||
+ Op.GAS | ||
+ 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) | ||
+ Op.STOP | ||
) | ||
|
||
post = { | ||
address_legacy_harness: Account( | ||
storage={ | ||
slot_warm_gas: cold_gas if warm_gas is None else warm_gas, | ||
slot_cold_gas: cold_gas, | ||
}, | ||
), | ||
} | ||
|
||
tx = Transaction(to=address_legacy_harness, gas_limit=2_000_000, sender=sender) | ||
|
||
state_test(env=env, pre=pre, tx=tx, post=post) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
["opcode", "pre_setup", "cold_gas", "warm_gas"], | ||
[ | ||
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"), | ||
], | ||
) | ||
def test_ext_calls_gas( | ||
state_test: StateTestFiller, | ||
pre: Alloc, | ||
opcode: Op, | ||
pre_setup: Op, | ||
cold_gas: int, | ||
warm_gas: int | None, | ||
): | ||
address_target = pre.deploy_contract(Container(sections=[Section.Code(code=Op.STOP)])) | ||
|
||
gas_test( | ||
state_test, | ||
pre, | ||
setup_code=pre_setup + Op.PUSH0 + Op.PUSH0 + Op.PUSH20(address_target), | ||
subject_code=opcode, | ||
tear_down_code=Op.STOP, | ||
cold_gas=cold_gas, | ||
warm_gas=warm_gas, | ||
) |