|
7 | 7 | import pytest
|
8 | 8 |
|
9 | 9 | from ethereum_test_exceptions.exceptions import EOFException
|
10 |
| -from ethereum_test_tools import EOFTestFiller |
| 10 | +from ethereum_test_tools import Account, EOFStateTestFiller, EOFTestFiller |
11 | 11 | from ethereum_test_tools.eof.v1 import Container, Section
|
12 | 12 | from ethereum_test_tools.vm.opcode import Opcodes as Op
|
13 | 13 | from ethereum_test_types.eof.v1.constants import MAX_OPERAND_STACK_HEIGHT, NON_RETURNING_SECTION
|
@@ -561,9 +561,68 @@ def test_all_opcodes_stack_underflow(
|
561 | 561 | ),
|
562 | 562 | ],
|
563 | 563 | ),
|
| 564 | + Container( |
| 565 | + name="underflow_variable_stack_3", |
| 566 | + sections=[ |
| 567 | + Section.Code( |
| 568 | + Op.RJUMPI[8](0) |
| 569 | + + Op.PUSH0 * 2 |
| 570 | + + Op.RJUMPI[1](0) |
| 571 | + + Op.POP * 2 |
| 572 | + + Op.PUSH0 * 2 |
| 573 | + + Op.REVERT, |
| 574 | + max_stack_height=3, |
| 575 | + ), |
| 576 | + ], |
| 577 | + ), |
564 | 578 | ],
|
565 | 579 | ids=lambda x: x.name,
|
566 | 580 | )
|
567 | 581 | def test_stack_underflow_examples(eof_test, container):
|
568 | 582 | """Test EOF validation failing due to stack underflow at basic instructions."""
|
569 | 583 | eof_test(container=container, expect_exception=EOFException.STACK_UNDERFLOW)
|
| 584 | + |
| 585 | + |
| 586 | +@pytest.mark.parametrize("initial_stack", [0, 1, 2]) |
| 587 | +@pytest.mark.parametrize("calldata_1", [0, 1]) |
| 588 | +@pytest.mark.parametrize("calldata_2", [0, 1]) |
| 589 | +def test_valid_non_constant_stack_examples( |
| 590 | + eof_state_test: EOFStateTestFiller, initial_stack: int, calldata_1: int, calldata_2: int |
| 591 | +): |
| 592 | + """Test valid containers with non constant stack items.""" |
| 593 | + # Stores the number of added items to the stack in storage slot 0 |
| 594 | + # calldata_1 == 1: number of items = 2 |
| 595 | + # calldata_1 == 0: |
| 596 | + # calldata_2 == 0: number of items: 3 |
| 597 | + # calldata_2 == 1: number of items: 4 |
| 598 | + expected_storage = {0: 2} if calldata_1 == 1 else ({0: 3} if calldata_2 == 0 else {0: 4}) |
| 599 | + data = calldata_1.to_bytes(32, "big") + calldata_2.to_bytes(32, "big") |
| 600 | + container = Container( |
| 601 | + sections=[ |
| 602 | + Section.Code( |
| 603 | + code=Op.PUSH0 * initial_stack |
| 604 | + + Op.CALLDATALOAD(0) |
| 605 | + + Op.RJUMPI[19] |
| 606 | + + Op.PUSH0 * 2 |
| 607 | + + Op.SSTORE(0, 2) # Stores added items (2) |
| 608 | + + Op.CALLDATALOAD(32) |
| 609 | + + Op.RJUMPI[6] |
| 610 | + + Op.POP |
| 611 | + + Op.SSTORE(0, 1) # Updates number of added items to 1 |
| 612 | + + Op.PUSH0 * 2 # <-- RJUMPI[19]/RJUMPI[6] target |
| 613 | + + Op.SLOAD(0) |
| 614 | + + Op.PUSH1(2) |
| 615 | + + Op.ADD # Add latest added items (+2) |
| 616 | + + Op.PUSH1(0) |
| 617 | + + Op.SSTORE |
| 618 | + + Op.STOP, |
| 619 | + max_stack_height=6 + initial_stack, |
| 620 | + ), |
| 621 | + ], |
| 622 | + ) |
| 623 | + eof_state_test( |
| 624 | + container=container, |
| 625 | + expect_exception=None, |
| 626 | + data=data, |
| 627 | + container_post=Account(storage=expected_storage), |
| 628 | + ) |
0 commit comments