Skip to content

Commit fed1f65

Browse files
jsignmarioevz
andauthored
feat(benchmark): add RETURN and REVERT coverage (#1841)
* benchmark: add RETURN and REVERT coverage Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * lints Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * improve comment Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * nit Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * lints Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * Apply suggestions from code review Co-authored-by: Mario Vega <marioevz@gmail.com> * fix lints Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> --------- Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> Co-authored-by: Mario Vega <marioevz@gmail.com>
1 parent 60c7ce5 commit fed1f65

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

tests/benchmark/test_worst_compute.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,3 +2255,65 @@ def test_worst_push(
22552255
post={},
22562256
tx=tx,
22572257
)
2258+
2259+
2260+
@pytest.mark.parametrize(
2261+
"opcode",
2262+
[Op.RETURN, Op.REVERT],
2263+
)
2264+
@pytest.mark.parametrize(
2265+
"return_size, return_non_zero_data",
2266+
[
2267+
pytest.param(0, False, id="empty"),
2268+
pytest.param(1024, True, id="1KiB of non-zero data"),
2269+
pytest.param(1024, False, id="1KiB of zero data"),
2270+
pytest.param(1024 * 1024, True, id="1MiB of non-zero data"),
2271+
pytest.param(1024 * 1024, False, id="1MiB of zero data"),
2272+
],
2273+
)
2274+
def test_worst_return_revert(
2275+
state_test: StateTestFiller,
2276+
pre: Alloc,
2277+
fork: Fork,
2278+
opcode: Op,
2279+
return_size: int,
2280+
return_non_zero_data: bool,
2281+
):
2282+
"""Test running a block with as many RETURN or REVERT as possible."""
2283+
env = Environment()
2284+
max_code_size = fork.max_code_size()
2285+
2286+
# Create the contract that will be called repeatedly.
2287+
# The bytecode of the contract is:
2288+
# ```
2289+
# [CODECOPY(returned_size) -- Conditional if return_non_zero_data]
2290+
# opcode(returned_size)
2291+
# <Fill with INVALID opcodes up to the max contract size>
2292+
# ```
2293+
# Filling the contract up to the max size is a cheap way of leveraging CODECOPY to return
2294+
# non-zero bytes if requested. Note that since this is a pre-deploy this cost isn't
2295+
# relevant for the benchmark.
2296+
mem_preparation = Op.CODECOPY(size=return_size) if return_non_zero_data else Bytecode()
2297+
executable_code = mem_preparation + opcode(size=return_size)
2298+
code = executable_code
2299+
if return_non_zero_data:
2300+
code += Op.INVALID * (max_code_size - len(executable_code))
2301+
target_contract_address = pre.deploy_contract(code=code)
2302+
2303+
calldata = Bytecode()
2304+
attack_block = Op.POP(Op.STATICCALL(address=target_contract_address))
2305+
code = code_loop_precompile_call(calldata, attack_block, fork)
2306+
code_address = pre.deploy_contract(code=code)
2307+
2308+
tx = Transaction(
2309+
to=code_address,
2310+
gas_limit=env.gas_limit,
2311+
sender=pre.fund_eoa(),
2312+
)
2313+
2314+
state_test(
2315+
env=env,
2316+
pre=pre,
2317+
post={},
2318+
tx=tx,
2319+
)

0 commit comments

Comments
 (0)