Skip to content

Commit ceea2e4

Browse files
committed
Additional EIP-7702 cases:
- Test a chained delegation stops after one hop (does not delegate to and address that is itself delegated). - Test delegation to an initially-empty address that later has bytecode deployed to it. This tests before and after and makes sure once code is present, it successfully delegates to the deployed code.
1 parent 823718a commit ceea2e4

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

tests/prague/eip7702_set_code_tx/test_set_code_txs_2.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
Conditional,
1818
Environment,
1919
Hash,
20+
Initcode,
2021
StateTestFiller,
2122
Storage,
2223
Switch,
@@ -25,6 +26,7 @@
2526
)
2627
from ethereum_test_tools.eof.v1 import Container, Section
2728
from ethereum_test_tools.vm.opcode import Opcodes as Op
29+
from ethereum_test_types import compute_create2_address
2830
from ethereum_test_vm import Macros
2931

3032
from .spec import Spec, ref_spec_7702
@@ -1689,3 +1691,148 @@ def test_pointer_resets_an_empty_code_account_with_storage(
16891691
Block(txs=[tx_create_suicide_from_pointer]),
16901692
],
16911693
)
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

Comments
 (0)