|
4 | 4 |
|
5 | 5 | import pytest
|
6 | 6 |
|
7 |
| -from ethereum_test_base_types import Address |
| 7 | +from ethereum_test_base_types import AccessList, Address, Hash |
8 | 8 | from ethereum_test_tools import (
|
9 | 9 | Account,
|
10 | 10 | Alloc,
|
@@ -345,7 +345,7 @@ def test_bal_self_destruct(
|
345 | 345 | pytest.param(lambda target_addr: Op.EXTCODESIZE(target_addr), id="extcodesize"),
|
346 | 346 | pytest.param(lambda target_addr: Op.EXTCODECOPY(target_addr, 0, 0, 32), id="extcodecopy"),
|
347 | 347 | pytest.param(lambda target_addr: Op.EXTCODEHASH(target_addr), id="extcodehash"),
|
348 |
| - pytest.param(lambda target_addr: Op.CALL(0, target_addr, 50, 0, 0, 0, 0), id="call"), |
| 348 | + pytest.param(lambda target_addr: Op.CALL(0, target_addr, 0, 0, 0, 0, 0), id="call"), |
349 | 349 | pytest.param(
|
350 | 350 | lambda target_addr: Op.CALLCODE(0, target_addr, 0, 0, 0, 0, 0), id="callcode"
|
351 | 351 | ),
|
@@ -647,3 +647,218 @@ def test_bal_block_rewards(
|
647 | 647 | blocks=[block],
|
648 | 648 | post={},
|
649 | 649 | )
|
| 650 | + |
| 651 | + |
| 652 | +def test_bal_2930_account_listed_but_untouched( |
| 653 | + pre: Alloc, |
| 654 | + blockchain_test: BlockchainTestFiller, |
| 655 | +): |
| 656 | + """Ensure BAL excludes untouched access list accounts.""" |
| 657 | + alice = pre.fund_eoa() |
| 658 | + bob = pre.fund_eoa() |
| 659 | + oracle = pre.deploy_contract(code=Op.STOP) |
| 660 | + |
| 661 | + access_list = AccessList( |
| 662 | + address=oracle, |
| 663 | + storage_keys=[Hash(0x1)], |
| 664 | + ) |
| 665 | + |
| 666 | + gas_limit = 1_000_000 |
| 667 | + |
| 668 | + tx = Transaction(ty=1, sender=alice, to=bob, gas_limit=gas_limit, access_list=[access_list]) |
| 669 | + |
| 670 | + block = Block( |
| 671 | + txs=[tx], |
| 672 | + expected_block_access_list=BlockAccessListExpectation( |
| 673 | + account_expectations={ |
| 674 | + alice: BalAccountExpectation( |
| 675 | + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], |
| 676 | + ), |
| 677 | + # The address excluded from BAL since state is not accessed |
| 678 | + oracle: None, |
| 679 | + } |
| 680 | + ), |
| 681 | + ) |
| 682 | + |
| 683 | + blockchain_test( |
| 684 | + pre=pre, |
| 685 | + blocks=[block], |
| 686 | + post={ |
| 687 | + alice: Account(nonce=1), |
| 688 | + }, |
| 689 | + ) |
| 690 | + |
| 691 | + |
| 692 | +def test_bal_2930_slot_listed_but_untouched( |
| 693 | + pre: Alloc, |
| 694 | + blockchain_test: BlockchainTestFiller, |
| 695 | + fork, |
| 696 | +): |
| 697 | + """Ensure BAL excludes untouched access list storage slots.""" |
| 698 | + alice = pre.fund_eoa() |
| 699 | + pure_calculator = pre.deploy_contract( |
| 700 | + # Pure add operation |
| 701 | + Op.ADD(35, 7) |
| 702 | + ) |
| 703 | + |
| 704 | + access_list = AccessList( |
| 705 | + address=pure_calculator, |
| 706 | + storage_keys=[Hash(0x1)], |
| 707 | + ) |
| 708 | + |
| 709 | + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() |
| 710 | + gas_limit = ( |
| 711 | + intrinsic_gas_calculator( |
| 712 | + calldata=b"", |
| 713 | + contract_creation=False, |
| 714 | + access_list=[access_list], |
| 715 | + ) |
| 716 | + + 1000 |
| 717 | + ) # intrinsic + buffer |
| 718 | + |
| 719 | + tx = Transaction( |
| 720 | + ty=1, sender=alice, to=pure_calculator, gas_limit=gas_limit, access_list=[access_list] |
| 721 | + ) |
| 722 | + |
| 723 | + block = Block( |
| 724 | + txs=[tx], |
| 725 | + expected_block_access_list=BlockAccessListExpectation( |
| 726 | + account_expectations={ |
| 727 | + alice: BalAccountExpectation( |
| 728 | + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], |
| 729 | + ), |
| 730 | + # The account was loaded. |
| 731 | + pure_calculator: BalAccountExpectation(), |
| 732 | + } |
| 733 | + ), |
| 734 | + ) |
| 735 | + |
| 736 | + blockchain_test( |
| 737 | + pre=pre, |
| 738 | + blocks=[block], |
| 739 | + post={ |
| 740 | + alice: Account(nonce=1), |
| 741 | + }, |
| 742 | + ) |
| 743 | + |
| 744 | + |
| 745 | +def test_bal_2930_slot_listed_and_unlisted_writes( |
| 746 | + pre: Alloc, |
| 747 | + blockchain_test: BlockchainTestFiller, |
| 748 | + fork, |
| 749 | +): |
| 750 | + """ |
| 751 | + Ensure BAL includes storage writes regardless of access list presence. |
| 752 | + """ |
| 753 | + alice = pre.fund_eoa() |
| 754 | + storage_writer = pre.deploy_contract(code=Op.SSTORE(0x01, 0x42) + Op.SSTORE(0x02, 0x43)) |
| 755 | + |
| 756 | + # Access list only includes slot 0x01, but contract writes to both |
| 757 | + # 0x01 and 0x02 |
| 758 | + access_list = AccessList( |
| 759 | + address=storage_writer, |
| 760 | + storage_keys=[Hash(0x01)], |
| 761 | + ) |
| 762 | + |
| 763 | + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() |
| 764 | + gas_limit = ( |
| 765 | + intrinsic_gas_calculator( |
| 766 | + calldata=b"", |
| 767 | + contract_creation=False, |
| 768 | + access_list=[access_list], |
| 769 | + ) |
| 770 | + + 50000 |
| 771 | + ) # intrinsic + buffer for storage writes |
| 772 | + |
| 773 | + tx = Transaction( |
| 774 | + ty=1, sender=alice, to=storage_writer, gas_limit=gas_limit, access_list=[access_list] |
| 775 | + ) |
| 776 | + |
| 777 | + block = Block( |
| 778 | + txs=[tx], |
| 779 | + expected_block_access_list=BlockAccessListExpectation( |
| 780 | + account_expectations={ |
| 781 | + alice: BalAccountExpectation( |
| 782 | + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], |
| 783 | + ), |
| 784 | + storage_writer: BalAccountExpectation( |
| 785 | + storage_changes=[ |
| 786 | + BalStorageSlot( |
| 787 | + slot=0x01, |
| 788 | + slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)], |
| 789 | + ), |
| 790 | + BalStorageSlot( |
| 791 | + slot=0x02, |
| 792 | + slot_changes=[BalStorageChange(tx_index=1, post_value=0x43)], |
| 793 | + ), |
| 794 | + ], |
| 795 | + ), |
| 796 | + } |
| 797 | + ), |
| 798 | + ) |
| 799 | + |
| 800 | + blockchain_test( |
| 801 | + pre=pre, |
| 802 | + blocks=[block], |
| 803 | + post={ |
| 804 | + alice: Account(nonce=1), |
| 805 | + storage_writer: Account(storage={0x01: 0x42, 0x02: 0x43}), |
| 806 | + }, |
| 807 | + ) |
| 808 | + |
| 809 | + |
| 810 | +def test_bal_2930_slot_listed_and_unlisted_reads( |
| 811 | + pre: Alloc, |
| 812 | + blockchain_test: BlockchainTestFiller, |
| 813 | + fork, |
| 814 | +): |
| 815 | + """Ensure BAL includes storage reads regardless of access list presence.""" |
| 816 | + alice = pre.fund_eoa() |
| 817 | + storage_reader = pre.deploy_contract( |
| 818 | + code=Op.SLOAD(0x01) + Op.SLOAD(0x02), |
| 819 | + storage={0x01: 0x42, 0x02: 0x43}, # Pre-populate storage with values |
| 820 | + ) |
| 821 | + |
| 822 | + # Access list only includes slot 0x01, but contract reads from both |
| 823 | + # 0x01 and 0x02 |
| 824 | + access_list = AccessList( |
| 825 | + address=storage_reader, |
| 826 | + storage_keys=[Hash(0x01)], |
| 827 | + ) |
| 828 | + |
| 829 | + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() |
| 830 | + gas_limit = ( |
| 831 | + intrinsic_gas_calculator( |
| 832 | + calldata=b"", |
| 833 | + contract_creation=False, |
| 834 | + access_list=[access_list], |
| 835 | + ) |
| 836 | + + 50000 |
| 837 | + ) # intrinsic + buffer for storage reads |
| 838 | + |
| 839 | + tx = Transaction( |
| 840 | + ty=1, sender=alice, to=storage_reader, gas_limit=gas_limit, access_list=[access_list] |
| 841 | + ) |
| 842 | + |
| 843 | + block = Block( |
| 844 | + txs=[tx], |
| 845 | + expected_block_access_list=BlockAccessListExpectation( |
| 846 | + account_expectations={ |
| 847 | + alice: BalAccountExpectation( |
| 848 | + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], |
| 849 | + ), |
| 850 | + storage_reader: BalAccountExpectation( |
| 851 | + storage_reads=[0x01, 0x02], |
| 852 | + ), |
| 853 | + } |
| 854 | + ), |
| 855 | + ) |
| 856 | + |
| 857 | + blockchain_test( |
| 858 | + pre=pre, |
| 859 | + blocks=[block], |
| 860 | + post={ |
| 861 | + alice: Account(nonce=1), |
| 862 | + storage_reader: Account(storage={0x01: 0x42, 0x02: 0x43}), |
| 863 | + }, |
| 864 | + ) |
0 commit comments