|
17 | 17 | Conditional,
|
18 | 18 | Environment,
|
19 | 19 | Hash,
|
| 20 | + Initcode, |
20 | 21 | StateTestFiller,
|
21 | 22 | Storage,
|
22 | 23 | Switch,
|
|
25 | 26 | )
|
26 | 27 | from ethereum_test_tools.eof.v1 import Container, Section
|
27 | 28 | from ethereum_test_tools.vm.opcode import Opcodes as Op
|
| 29 | +from ethereum_test_types import compute_create2_address |
28 | 30 | from ethereum_test_vm import Macros
|
29 | 31 |
|
30 | 32 | from .spec import Spec, ref_spec_7702
|
@@ -1689,3 +1691,148 @@ def test_pointer_resets_an_empty_code_account_with_storage(
|
1689 | 1691 | Block(txs=[tx_create_suicide_from_pointer]),
|
1690 | 1692 | ],
|
1691 | 1693 | )
|
| 1694 | + |
| 1695 | + |
| 1696 | +@pytest.mark.valid_from("Prague") |
| 1697 | +@pytest.mark.parametrize("chain_id", [0, 1]) |
| 1698 | +def test_chained_delegation_stops_after_one_hop( |
| 1699 | + blockchain_test: BlockchainTestFiller, |
| 1700 | + pre: Alloc, |
| 1701 | + chain_id: int, |
| 1702 | +): |
| 1703 | + """ |
| 1704 | + Tests a chained delegation via EIP-7702 transaction. |
| 1705 | +
|
| 1706 | + A delegates to B which delegates to C |
| 1707 | +
|
| 1708 | + Only one level of delegation should be followed when code is executed. Even though |
| 1709 | + B delegates to C, a call to A should stop at B. The control shows how the contract |
| 1710 | + should behave. |
| 1711 | + """ |
| 1712 | + address_a = pre.fund_eoa() |
| 1713 | + address_b = pre.fund_eoa() |
| 1714 | + control_address = pre.fund_eoa() |
| 1715 | + |
| 1716 | + store_1_at_0 = Op.SSTORE(0, 1) + Op.STOP() |
| 1717 | + contract = pre.deploy_contract(code=store_1_at_0) |
| 1718 | + |
| 1719 | + # this is the control, showing the contract works as expected |
| 1720 | + control_tx = Transaction( |
| 1721 | + gas_limit=200_000, |
| 1722 | + data=b"", |
| 1723 | + value=0, |
| 1724 | + to=control_address, |
| 1725 | + sender=control_address, |
| 1726 | + authorization_list=[ |
| 1727 | + AuthorizationTuple( |
| 1728 | + address=contract, |
| 1729 | + chain_id=chain_id, |
| 1730 | + nonce=1, |
| 1731 | + signer=control_address, |
| 1732 | + ) |
| 1733 | + ], |
| 1734 | + ) |
| 1735 | + chained_delegation_tx = Transaction( |
| 1736 | + gas_limit=200_000, |
| 1737 | + data=b"", |
| 1738 | + value=0, |
| 1739 | + to=address_a, |
| 1740 | + authorization_list=[ |
| 1741 | + AuthorizationTuple( |
| 1742 | + address=contract, |
| 1743 | + chain_id=chain_id, |
| 1744 | + nonce=0, |
| 1745 | + signer=address_b, |
| 1746 | + ), |
| 1747 | + AuthorizationTuple( |
| 1748 | + address=address_b, |
| 1749 | + chain_id=chain_id, |
| 1750 | + nonce=1, |
| 1751 | + signer=address_a, |
| 1752 | + ), |
| 1753 | + ], |
| 1754 | + ) |
| 1755 | + |
| 1756 | + post = { |
| 1757 | + control_address: Account(code=Spec.delegation_designation(contract), storage={0: 1}), |
| 1758 | + address_a: Account(code=Spec.delegation_designation(address_b), nonce=2), |
| 1759 | + address_b: Account(code=Spec.delegation_designation(contract), nonce=1), |
| 1760 | + contract: Account(code=store_1_at_0, storage={}), |
| 1761 | + } |
| 1762 | + |
| 1763 | + blockchain_test( |
| 1764 | + environment=Environment(), |
| 1765 | + pre=pre, |
| 1766 | + blocks=[Block(txs=[control_tx, chained_delegation_tx])], |
| 1767 | + post=post, |
| 1768 | + ) |
| 1769 | + |
| 1770 | + |
| 1771 | +@pytest.mark.valid_from("Prague") |
| 1772 | +def test_delegation_to_initially_empty_account_with_eventual_bytecode_deployed( |
| 1773 | + blockchain_test: BlockchainTestFiller, |
| 1774 | + pre: Alloc, |
| 1775 | +): |
| 1776 | + """ |
| 1777 | + Tests a delegation to an initially empty account which later has a contract |
| 1778 | + deployed to it, making sure delegation to the newly deployed contract works as |
| 1779 | + expected. |
| 1780 | + """ |
| 1781 | + sender = pre.fund_eoa() |
| 1782 | + delegated_address = pre.fund_eoa() |
| 1783 | + |
| 1784 | + creator_contract_code = Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.CREATE2( |
| 1785 | + 0, 0, Op.CALLDATASIZE, 0 |
| 1786 | + ) |
| 1787 | + creator_address = pre.deploy_contract(creator_contract_code) |
| 1788 | + |
| 1789 | + store_1_at_0 = Op.SSTORE(0, 1) |
| 1790 | + initcode = Initcode(deploy_code=store_1_at_0) |
| 1791 | + initially_empty_address = compute_create2_address( |
| 1792 | + address=creator_address, salt=0, initcode=initcode |
| 1793 | + ) |
| 1794 | + |
| 1795 | + delegate_to_initially_empty_acct = Transaction( |
| 1796 | + to=delegated_address, |
| 1797 | + gas_limit=100_000, |
| 1798 | + authorization_list=[ |
| 1799 | + AuthorizationTuple( |
| 1800 | + signer=delegated_address, |
| 1801 | + chain_id=1, |
| 1802 | + address=initially_empty_address, |
| 1803 | + nonce=0, |
| 1804 | + ), |
| 1805 | + ], |
| 1806 | + sender=sender, |
| 1807 | + ) |
| 1808 | + create2_initcode_to_empty_acct = Transaction( |
| 1809 | + to=creator_address, |
| 1810 | + gas_limit=100_000, |
| 1811 | + data=initcode, |
| 1812 | + sender=sender, |
| 1813 | + ) |
| 1814 | + should_delegate_to_contract_code = Transaction( |
| 1815 | + to=delegated_address, |
| 1816 | + gas_limit=100_000, |
| 1817 | + sender=sender, |
| 1818 | + ) |
| 1819 | + |
| 1820 | + blockchain_test( |
| 1821 | + pre=pre, |
| 1822 | + blocks=[ |
| 1823 | + Block( |
| 1824 | + txs=[ |
| 1825 | + delegate_to_initially_empty_acct, |
| 1826 | + create2_initcode_to_empty_acct, |
| 1827 | + should_delegate_to_contract_code, |
| 1828 | + ] |
| 1829 | + ) |
| 1830 | + ], |
| 1831 | + post={ |
| 1832 | + delegated_address: Account( |
| 1833 | + code=Spec.delegation_designation(initially_empty_address), |
| 1834 | + storage={0: 1}, |
| 1835 | + ), |
| 1836 | + initially_empty_address: Account(code=store_1_at_0), |
| 1837 | + }, |
| 1838 | + ) |
0 commit comments