diff --git a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py index 3af6d5e151..a423627279 100644 --- a/tests/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/tests/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -686,6 +686,54 @@ def test_set_code_to_self_caller( ) +@pytest.mark.execute(pytest.mark.skip(reason="excessive gas")) +def test_set_code_max_depth_call_stack( + state_test: StateTestFiller, + pre: Alloc, +): + """ + Test re-entry to delegated account until the max call stack depth is reached. + """ + storage = Storage() + auth_signer = pre.fund_eoa(auth_account_start_balance) + set_code = Conditional( + condition=Op.ISZERO(Op.TLOAD(0)), + if_true=Op.TSTORE(0, 1) + + Op.CALL(address=auth_signer) + + Op.SSTORE(storage.store_next(1025), Op.TLOAD(0)), + if_false=Op.TSTORE(0, Op.ADD(1, Op.TLOAD(0))) + Op.CALL(address=auth_signer), + ) + set_code_to_address = pre.deploy_contract(set_code) + + tx = Transaction( + gas_limit=100_000_000_000_000, + to=auth_signer, + authorization_list=[ + AuthorizationTuple( + address=set_code_to_address, + nonce=0, + signer=auth_signer, + ), + ], + sender=pre.fund_eoa(), + ) + + state_test( + env=Environment(), + pre=pre, + tx=tx, + post={ + set_code_to_address: Account(storage={}), + auth_signer: Account( + nonce=1, + code=Spec.delegation_designation(set_code_to_address), + storage=storage, + balance=auth_account_start_balance, + ), + }, + ) + + @pytest.mark.with_all_call_opcodes @pytest.mark.parametrize( "value", @@ -3164,6 +3212,139 @@ def test_delegation_clearing( ) +@pytest.mark.parametrize( + "self_sponsored", + [ + pytest.param(False, id="not_self_sponsored"), + pytest.param(True, id="self_sponsored"), + ], +) +@pytest.mark.parametrize( + "pre_set_delegation_code", + [ + pytest.param(Op.RETURN(0, 1), id="delegated_account"), + pytest.param(None, id="undelegated_account"), + ], +) +def test_delegation_clearing_tx_to( + state_test: StateTestFiller, + pre: Alloc, + pre_set_delegation_code: Bytecode | None, + self_sponsored: bool, +): + """ + Tests directly calling the account which delegation is being cleared. + + Args: + pre_set_delegation_code: The code to set on the account before clearing delegation, or None + if the account should not have any code set. + self_sponsored: Whether the delegation clearing transaction is self-sponsored. + """ # noqa: D417 + pre_set_delegation_address: Address | None = None + if pre_set_delegation_code is not None: + pre_set_delegation_address = pre.deploy_contract(pre_set_delegation_code) + + if self_sponsored: + auth_signer = pre.fund_eoa(delegation=pre_set_delegation_address) + else: + auth_signer = pre.fund_eoa(0, delegation=pre_set_delegation_address) + + sender = pre.fund_eoa() if not self_sponsored else auth_signer + + tx = Transaction( + gas_limit=200_000, + to=auth_signer, + value=0, + authorization_list=[ + AuthorizationTuple( + address=Spec.RESET_DELEGATION_ADDRESS, # Reset + nonce=auth_signer.nonce + (1 if self_sponsored else 0), + signer=auth_signer, + ), + ], + sender=sender, + ) + + state_test( + env=Environment(), + pre=pre, + tx=tx, + post={ + auth_signer: Account( + nonce=auth_signer.nonce + 1, + code=b"", + storage={}, + ), + }, + ) + + +@pytest.mark.parametrize( + "pre_set_delegation_code", + [ + pytest.param(Op.RETURN(0, 1), id="delegated_account"), + pytest.param(None, id="undelegated_account"), + ], +) +def test_delegation_clearing_and_set( + state_test: StateTestFiller, + pre: Alloc, + pre_set_delegation_code: Bytecode | None, +): + """ + Tests clearing and setting the delegation again in the same authorization list. + + Args: + pre_set_delegation_code: The code to set on the account before clearing delegation, or None + if the account should not have any code set. + """ # noqa: D417 + pre_set_delegation_address: Address | None = None + if pre_set_delegation_code is not None: + pre_set_delegation_address = pre.deploy_contract(pre_set_delegation_code) + + auth_signer = pre.fund_eoa(0, delegation=pre_set_delegation_address) + + reset_code_address = pre.deploy_contract( + Op.CALL(address=Spec.RESET_DELEGATION_ADDRESS) + Op.SSTORE(0, 1) + Op.STOP + ) + + sender = pre.fund_eoa() + + tx = Transaction( + gas_limit=200_000, + to=auth_signer, + value=0, + authorization_list=[ + AuthorizationTuple( + address=Spec.RESET_DELEGATION_ADDRESS, # Reset + nonce=auth_signer.nonce, + signer=auth_signer, + ), + AuthorizationTuple( + address=reset_code_address, + nonce=auth_signer.nonce + 1, + signer=auth_signer, + ), + ], + sender=sender, + ) + + state_test( + env=Environment(), + pre=pre, + tx=tx, + post={ + auth_signer: Account( + nonce=auth_signer.nonce + 2, + code=Spec.delegation_designation(reset_code_address), + storage={ + 0: 1, + }, + ), + }, + ) + + @pytest.mark.parametrize( "entry_code", [