From 81ce7a2a8a3998c9430ab00c8eca9358d1b7b181 Mon Sep 17 00:00:00 2001 From: sonhv0212 Date: Thu, 3 Apr 2025 16:25:28 +0700 Subject: [PATCH 1/2] fix(tests): EIP-7702: use penultimate block number instead of fixing block 0 --- src/ethereum_test_rpc/rpc.py | 4 ++++ src/ethereum_test_types/types.py | 4 ++++ src/pytest_plugins/execute/pre_alloc.py | 4 ++++ src/pytest_plugins/filler/pre_alloc.py | 4 ++++ tests/prague/eip7702_set_code_tx/test_set_code_txs.py | 3 ++- 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ethereum_test_rpc/rpc.py b/src/ethereum_test_rpc/rpc.py index bc99344d659..9da2ec0094c 100644 --- a/src/ethereum_test_rpc/rpc.py +++ b/src/ethereum_test_rpc/rpc.py @@ -114,6 +114,10 @@ def __init__( super().__init__(url, extra_headers) self.transaction_wait_timeout = transaction_wait_timeout + def get_block_number(self) -> int: + """`eth_blockNumber`: Returns the number of the most recent block.""" + return int(self.post_request("blockNumber"), 16) + def get_block_by_number(self, block_number: BlockNumberType = "latest", full_txs: bool = True): """`eth_getBlockByNumber`: Returns information about a block by block number.""" block = hex(block_number) if isinstance(block_number, int) else block_number diff --git a/src/ethereum_test_types/types.py b/src/ethereum_test_types/types.py index f180b7cad41..e09c9d1b772 100644 --- a/src/ethereum_test_types/types.py +++ b/src/ethereum_test_types/types.py @@ -298,6 +298,10 @@ def fund_address(self, address: Address, amount: NumberConvertible): """ raise NotImplementedError("fund_address is not implemented in the base class") + def get_block_number(self): + """Return the last block number.""" + raise NotImplementedError("get_block_number is not implemented in the base class") + class WithdrawalGeneric(CamelModel, Generic[NumberBoundTypeVar]): """Withdrawal generic type, used as a parent class for `Withdrawal` and `FixtureWithdrawal`.""" diff --git a/src/pytest_plugins/execute/pre_alloc.py b/src/pytest_plugins/execute/pre_alloc.py index 466249e3dfd..a657a5f928c 100644 --- a/src/pytest_plugins/execute/pre_alloc.py +++ b/src/pytest_plugins/execute/pre_alloc.py @@ -343,6 +343,10 @@ def fund_address(self, address: Address, amount: NumberConvertible): super().__setitem__(address, Account(balance=amount)) + def get_block_number(self): + """Return the last block number.""" + return self._eth_rpc.get_block_number() + def wait_for_transactions(self) -> List[TransactionByHashResponse]: """Wait for all transactions to be included in blocks.""" return self._eth_rpc.wait_for_transactions(self._txs) diff --git a/src/pytest_plugins/filler/pre_alloc.py b/src/pytest_plugins/filler/pre_alloc.py index 9f50790aad7..b70315aadc3 100644 --- a/src/pytest_plugins/filler/pre_alloc.py +++ b/src/pytest_plugins/filler/pre_alloc.py @@ -250,6 +250,10 @@ def fund_address(self, address: Address, amount: NumberConvertible): return super().__setitem__(address, Account(balance=amount)) + def get_block_number(self): + """Return the last block number.""" + return 0 + @pytest.fixture(scope="session") def alloc_mode(request: pytest.FixtureRequest) -> AllocMode: 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 46ba8316d23..2d6c7956a32 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 @@ -2656,7 +2656,8 @@ def test_set_code_to_system_contract( caller_payload = consolidation_request.calldata call_value = consolidation_request.value case Address(0x0000F90827F1C53A10CB7A02335B175320002935): # EIP-2935 - caller_payload = Hash(0) + # Use the penultimate block to ensure it is saved in the history contract + caller_payload = Hash(max(pre.get_block_number() - 1, 0)) caller_code_storage[call_return_data_size_slot] = 32 case _: raise ValueError(f"Not implemented system contract: {system_contract}") From 2badae221b58b832fd79e9ce16bad593b12a6a42 Mon Sep 17 00:00:00 2001 From: sonhv0212 Date: Sat, 10 May 2025 01:05:41 +0700 Subject: [PATCH 2/2] fix(tests): EIP-7702: use contract code to get blocknumber instead of rpc --- src/ethereum_test_rpc/rpc.py | 4 --- src/ethereum_test_types/types.py | 4 --- src/pytest_plugins/execute/pre_alloc.py | 4 --- src/pytest_plugins/filler/pre_alloc.py | 4 --- .../eip7702_set_code_tx/test_set_code_txs.py | 28 ++++++++++++++----- 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/ethereum_test_rpc/rpc.py b/src/ethereum_test_rpc/rpc.py index 9da2ec0094c..bc99344d659 100644 --- a/src/ethereum_test_rpc/rpc.py +++ b/src/ethereum_test_rpc/rpc.py @@ -114,10 +114,6 @@ def __init__( super().__init__(url, extra_headers) self.transaction_wait_timeout = transaction_wait_timeout - def get_block_number(self) -> int: - """`eth_blockNumber`: Returns the number of the most recent block.""" - return int(self.post_request("blockNumber"), 16) - def get_block_by_number(self, block_number: BlockNumberType = "latest", full_txs: bool = True): """`eth_getBlockByNumber`: Returns information about a block by block number.""" block = hex(block_number) if isinstance(block_number, int) else block_number diff --git a/src/ethereum_test_types/types.py b/src/ethereum_test_types/types.py index e09c9d1b772..f180b7cad41 100644 --- a/src/ethereum_test_types/types.py +++ b/src/ethereum_test_types/types.py @@ -298,10 +298,6 @@ def fund_address(self, address: Address, amount: NumberConvertible): """ raise NotImplementedError("fund_address is not implemented in the base class") - def get_block_number(self): - """Return the last block number.""" - raise NotImplementedError("get_block_number is not implemented in the base class") - class WithdrawalGeneric(CamelModel, Generic[NumberBoundTypeVar]): """Withdrawal generic type, used as a parent class for `Withdrawal` and `FixtureWithdrawal`.""" diff --git a/src/pytest_plugins/execute/pre_alloc.py b/src/pytest_plugins/execute/pre_alloc.py index a657a5f928c..466249e3dfd 100644 --- a/src/pytest_plugins/execute/pre_alloc.py +++ b/src/pytest_plugins/execute/pre_alloc.py @@ -343,10 +343,6 @@ def fund_address(self, address: Address, amount: NumberConvertible): super().__setitem__(address, Account(balance=amount)) - def get_block_number(self): - """Return the last block number.""" - return self._eth_rpc.get_block_number() - def wait_for_transactions(self) -> List[TransactionByHashResponse]: """Wait for all transactions to be included in blocks.""" return self._eth_rpc.wait_for_transactions(self._txs) diff --git a/src/pytest_plugins/filler/pre_alloc.py b/src/pytest_plugins/filler/pre_alloc.py index b70315aadc3..9f50790aad7 100644 --- a/src/pytest_plugins/filler/pre_alloc.py +++ b/src/pytest_plugins/filler/pre_alloc.py @@ -250,10 +250,6 @@ def fund_address(self, address: Address, amount: NumberConvertible): return super().__setitem__(address, Account(balance=amount)) - def get_block_number(self): - """Return the last block number.""" - return 0 - @pytest.fixture(scope="session") def alloc_mode(request: pytest.FixtureRequest) -> AllocMode: 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 2d6c7956a32..207fb1a75af 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 @@ -2656,18 +2656,32 @@ def test_set_code_to_system_contract( caller_payload = consolidation_request.calldata call_value = consolidation_request.value case Address(0x0000F90827F1C53A10CB7A02335B175320002935): # EIP-2935 - # Use the penultimate block to ensure it is saved in the history contract - caller_payload = Hash(max(pre.get_block_number() - 1, 0)) + # This payload is used to identify the number of blocks to be subtracted from the + # latest block number + caller_payload = Hash(1) caller_code_storage[call_return_data_size_slot] = 32 case _: raise ValueError(f"Not implemented system contract: {system_contract}") + # Setup the code to call the system contract + match system_contract: + case Address(0x0000F90827F1C53A10CB7A02335B175320002935): # EIP-2935 + # Do a trick here to get the block number of the penultimate block to ensure it is + # saved in the history contract + check_block_number = Op.SUB(Op.NUMBER, Op.CALLDATALOAD(0)) + call_system_contract_code = Op.MSTORE(0, check_block_number) + Op.SSTORE( + call_return_code_slot, + call_opcode(address=auth_signer, value=call_value, args_size=32), + ) + case _: + # Call another system contract with fabricated payload + call_system_contract_code = Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.SSTORE( + call_return_code_slot, + call_opcode(address=auth_signer, value=call_value, args_size=Op.CALLDATASIZE), + ) + caller_code = ( - Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) - + Op.SSTORE( - call_return_code_slot, - call_opcode(address=auth_signer, value=call_value, args_size=Op.CALLDATASIZE), - ) + call_system_contract_code + Op.SSTORE(call_return_data_size_slot, Op.RETURNDATASIZE) + Op.STOP )