|
22 | 22 | Initcode, |
23 | 23 | Op, |
24 | 24 | RecipientType, |
| 25 | + StateTestFiller, |
25 | 26 | Transaction, |
26 | 27 | Withdrawal, |
27 | 28 | compute_create_address, |
|
31 | 32 | ) |
32 | 33 |
|
33 | 34 | from ...prague.eip7702_set_code_tx.spec import Spec as Spec7702 |
| 35 | +from ..eip2780_reduce_intrinsic_tx_gas.helpers import ( |
| 36 | + AuthorizationAction, |
| 37 | + build_authorization, |
| 38 | +) |
34 | 39 | from .spec import ref_spec_7928 |
35 | 40 |
|
36 | 41 | REFERENCE_SPEC_GIT_PATH = ref_spec_7928.git_path |
@@ -547,6 +552,92 @@ def test_bal_7702_top_frame_delegation_oog( |
547 | 552 | ) |
548 | 553 |
|
549 | 554 |
|
| 555 | +@pytest.mark.parametrize( |
| 556 | + "outcome", |
| 557 | + [ |
| 558 | + pytest.param("oog", id="oog_at_authorization_charge"), |
| 559 | + pytest.param("success", id="success"), |
| 560 | + ], |
| 561 | +) |
| 562 | +def test_bal_7702_recipient_excluded_on_authorization_oog( |
| 563 | + fork: Fork, |
| 564 | + pre: Alloc, |
| 565 | + state_test: StateTestFiller, |
| 566 | + outcome: str, |
| 567 | +) -> None: |
| 568 | + """ |
| 569 | + Ensure ``tx.to`` enters the BAL only when authorization processing |
| 570 | + completes. |
| 571 | +
|
| 572 | + The single authorization is starved at its opening ``NEW_ACCOUNT`` |
| 573 | + charge, halting the transaction before the top-frame dispatch loads |
| 574 | + the recipient: the recipient must be absent from the BAL, while the |
| 575 | + authority -- read during authorization validation -- stays in it |
| 576 | + with no recorded changes. |
| 577 | + """ |
| 578 | + sender = pre.fund_eoa() |
| 579 | + recipient = pre.deploy_contract(code=Op.STOP) |
| 580 | + |
| 581 | + auth = build_authorization(pre, AuthorizationAction.CREATES_ACCOUNT) |
| 582 | + authorization_list = [auth.authorization] |
| 583 | + |
| 584 | + intrinsic_regular = fork.transaction_intrinsic_cost_calculator()( |
| 585 | + recipient_type=RecipientType.CONTRACT, |
| 586 | + authorization_list_or_count=authorization_list, |
| 587 | + return_cost_deducted_prior_execution=True, |
| 588 | + ) |
| 589 | + |
| 590 | + recipient_expectation: BalAccountExpectation | None |
| 591 | + expected_authority: Account | None |
| 592 | + if outcome == "oog": |
| 593 | + # The authorization runs out at its opening NEW_ACCOUNT state |
| 594 | + # charge, drawn from gas_left under the zero state reservoir. |
| 595 | + gas_limit = intrinsic_regular + fork.gas_costs().NEW_ACCOUNT - 1 |
| 596 | + recipient_expectation = None |
| 597 | + authority_expectation = BalAccountExpectation.empty() |
| 598 | + expected_authority = auth.original_account |
| 599 | + else: |
| 600 | + top_frame_regular = fork.transaction_top_frame_gas_calculator()( |
| 601 | + recipient_type=RecipientType.CONTRACT, |
| 602 | + authorizations=authorization_list, |
| 603 | + ) |
| 604 | + top_frame_state = fork.transaction_top_frame_state_gas( |
| 605 | + recipient_type=RecipientType.CONTRACT, |
| 606 | + authorizations=authorization_list, |
| 607 | + ) |
| 608 | + gas_limit = intrinsic_regular + top_frame_regular + top_frame_state |
| 609 | + recipient_expectation = BalAccountExpectation.empty() |
| 610 | + authority_expectation = BalAccountExpectation( |
| 611 | + nonce_changes=[BalNonceChange(block_access_index=1, post_nonce=1)], |
| 612 | + code_changes=[ |
| 613 | + BalCodeChange( |
| 614 | + block_access_index=1, |
| 615 | + new_code=auth.applied_account.code, |
| 616 | + ) |
| 617 | + ], |
| 618 | + ) |
| 619 | + expected_authority = auth.applied_account |
| 620 | + |
| 621 | + tx = Transaction( |
| 622 | + sender=sender, |
| 623 | + to=recipient, |
| 624 | + authorization_list=authorization_list, |
| 625 | + gas_limit=gas_limit, |
| 626 | + ) |
| 627 | + |
| 628 | + state_test( |
| 629 | + pre=pre, |
| 630 | + tx=tx, |
| 631 | + post={sender: Account(nonce=1), auth.authority: expected_authority}, |
| 632 | + expected_block_access_list=BlockAccessListExpectation( |
| 633 | + account_expectations={ |
| 634 | + recipient: recipient_expectation, |
| 635 | + auth.authority: authority_expectation, |
| 636 | + } |
| 637 | + ), |
| 638 | + ) |
| 639 | + |
| 640 | + |
550 | 641 | def test_bal_7702_invalid_nonce_authorization( |
551 | 642 | pre: Alloc, |
552 | 643 | blockchain_test: BlockchainTestFiller, |
|
0 commit comments