Skip to content

chore(tests): additional eip6110 edge cases #1467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Test fixtures for use by clients are available for each release on the [Github r
- ✨ [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702): Test precompile case in same transaction as delegation without extra gas in case of precompile code execution; parametrize all call opcodes in existing precompile test ([#1431](https://github.com/ethereum/execution-spec-tests/pull/1431)).
- ✨ [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702): Add invalid nonce authorizations tests for the case of multiple signers when the sender's nonce gets increased ([#1441](https://github.com/ethereum/execution-spec-tests/pull/1441)).
- ✨ [EIP-7623](https://eips.ethereum.org/EIPS/eip-7623): Additionally parametrize transaction validity tests with the `to` set to an EOA account (previously only contracts) ([#1422](https://github.com/ethereum/execution-spec-tests/pull/1422)).
- ✨ [EIP-6110](https://eips.ethereum.org/EIPS/eip-6110): Add extra deposit request edge cases, sending eth to the deposit contract while sending a deposit request ([#1467](https://github.com/ethereum/execution-spec-tests/pull/1467)).
- ✨ [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251): Remove pytest skips for consolidation request cases ([#1449](https://github.com/ethereum/execution-spec-tests/pull/1449)).

### 📋 Misc

Expand Down
34 changes: 34 additions & 0 deletions src/ethereum_test_types/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1109,10 +1109,26 @@ class DepositRequest(RequestBase, CamelModel):
"""Deposit Request type."""

pubkey: BLSPublicKey
"""
The public key of the beacon chain validator.
"""
withdrawal_credentials: Hash
"""
The withdrawal credentials of the beacon chain validator.
"""
amount: HexNumber
"""
The amount in gwei of the deposit.
"""
signature: BLSSignature
"""
The signature of the deposit using the validator's private key that matches the
`pubkey`.
"""
index: HexNumber
"""
The index of the deposit.
"""

type: ClassVar[int] = 0

Expand All @@ -1131,8 +1147,17 @@ class WithdrawalRequest(RequestBase, CamelModel):
"""Withdrawal Request type."""

source_address: Address = Address(0)
"""
The address of the execution layer account that made the withdrawal request.
"""
validator_pubkey: BLSPublicKey
"""
The current public key of the validator as it currently is in the beacon state.
"""
amount: HexNumber
"""
The amount in gwei to be withdrawn on the beacon chain.
"""

type: ClassVar[int] = 1

Expand All @@ -1149,8 +1174,17 @@ class ConsolidationRequest(RequestBase, CamelModel):
"""Consolidation Request type."""

source_address: Address = Address(0)
"""
The address of the execution layer account that made the consolidation request.
"""
source_pubkey: BLSPublicKey
"""
The public key of the source validator as it currently is in the beacon state.
"""
target_pubkey: BLSPublicKey
"""
The public key of the target validator as it currently is in the beacon state.
"""

type: ClassVar[int] = 2

Expand Down
31 changes: 25 additions & 6 deletions tests/prague/eip6110_deposits/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,29 @@ class DepositRequest(DepositRequestBase):
"""
Calldata modifier function.
"""
extra_wei: int = 0
"""
Extra amount in wei to be sent with the deposit.
If this value modulo 10**9 is not zero, the deposit will be invalid.
The value can be negative but if the total value is negative, an exception will be raised.
"""

interaction_contract_address: ClassVar[Address] = Address(Spec.DEPOSIT_CONTRACT_ADDRESS)

@cached_property
def value(self) -> int:
"""Returns the value of the deposit transaction."""
return self.amount * 10**9
"""
Return the value of the deposit transaction, equal to the amount in gwei plus the
extra amount in wei.
"""
value = (self.amount * 10**9) + self.extra_wei
if value < 0:
raise ValueError("Value cannot be negative")
return value

@cached_property
def deposit_data_root(self) -> Hash:
"""Returns the deposit data root of the deposit."""
"""Return the deposit data root of the deposit."""
pubkey_root = sha256(self.pubkey, b"\x00" * 16)
signature_root = sha256(
sha256(self.signature[:64]), sha256(self.signature[64:], b"\x00" * 32)
Expand All @@ -55,7 +67,7 @@ def deposit_data_root(self) -> Hash:
@cached_property
def calldata(self) -> bytes:
"""
Returns the calldata needed to call the beacon chain deposit contract and make the deposit.
Return the calldata needed to call the beacon chain deposit contract and make the deposit.

deposit(
bytes calldata pubkey,
Expand Down Expand Up @@ -157,6 +169,10 @@ class DepositContract(DepositInteractionBase):
"""
Gas limit for the transaction.
"""
tx_value: int = 0
"""
Value to send with the transaction.
"""

contract_balance: int = 32_000_000_000_000_000_000 * 100
"""
Expand Down Expand Up @@ -212,15 +228,18 @@ def transactions(self) -> List[Transaction]:
gas_limit=self.tx_gas_limit,
gas_price=0x07,
to=self.entry_address,
value=0,
value=self.tx_value,
data=b"".join(r.calldata for r in self.requests),
sender=self.sender_account,
)
]

def update_pre(self, pre: Alloc):
"""Return the pre-state of the account."""
self.sender_account = pre.fund_eoa(self.sender_balance)
required_balance = self.sender_balance
if self.tx_value > 0:
required_balance = max(required_balance, self.tx_value + self.tx_gas_limit * 7)
self.sender_account = pre.fund_eoa(required_balance)
self.contract_address = pre.deploy_contract(
code=self.contract_code, balance=self.contract_balance
)
Expand Down
216 changes: 215 additions & 1 deletion tests/prague/eip6110_deposits/test_deposits.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,25 @@
],
id="send_eth_from_eoa",
),
pytest.param(
[
DepositContract(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=32_000_000_000,
signature=0x03,
index=0x0,
valid=False,
calldata_modifier=lambda _: b"",
)
],
),
],
# TODO: EIP-5920: Send using PAY opcode
id="send_eth_to_contract_no_deposit_data",
),
pytest.param(
[
DepositContract(
Expand Down Expand Up @@ -694,7 +713,202 @@
],
id="single_deposit_from_contract_call_high_depth",
),
# TODO: Send eth with the transaction to the contract
pytest.param(
[
DepositTransaction(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=1_000_000_001,
signature=0x03,
index=0x0,
)
],
),
],
id="single_deposit_from_eoa_minimum_plus_one",
),
pytest.param(
[
DepositTransaction(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=1_000_000_000,
signature=0x03,
index=0x0,
extra_wei=1,
valid=False,
)
],
),
],
id="single_deposit_from_eoa_minimum_plus_one_wei",
),
pytest.param(
[
DepositTransaction(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=1_000_000_000,
signature=0x03,
index=0x0,
extra_wei=-1,
valid=False,
)
],
),
],
id="single_deposit_from_eoa_minimum_minus_one_wei",
),
pytest.param(
[
DepositContract(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=1_000_000_000,
signature=0x03,
index=0x0,
extra_wei=1,
valid=False,
)
],
),
],
id="single_deposit_from_contract_minimum_plus_one_wei",
),
pytest.param(
[
DepositContract(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=1_000_000_000,
signature=0x03,
index=0x0,
extra_wei=-1,
valid=False,
)
],
),
],
id="single_deposit_from_contract_minimum_minus_one_wei",
),
pytest.param(
[
DepositTransaction(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=1_000_000_001,
signature=0x03,
index=0x0,
),
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=999_999_999,
signature=0x03,
index=0x1,
valid=False,
),
],
),
],
id="multiple_deposits_from_eoa_minimum_plus_one_minimum_minus_one",
),
pytest.param(
[
DepositContract(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=32_000_000_000,
signature=0x03,
index=0x0,
valid=False,
)
],
# Send 32 ETH minus 1 wei to the contract, note `DepositRequest.amount` is in
# gwei
tx_value=32_000_000_000 * 10**9 - 1,
contract_balance=0,
),
],
id="send_not_enough_eth_to_contract_with_zero_balance",
),
pytest.param(
[
DepositContract(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=999_999_999,
signature=0x03,
index=0x0,
valid=False,
)
],
tx_value=1_000_000_000 * 10**9,
),
],
id="send_eth_to_contract_insufficient_deposit",
),
pytest.param(
[
DepositContract(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=32_000_000_000,
signature=0x03,
index=0x0,
)
],
# Send 32 ETH (in wei) to the contract
tx_value=32_000_000_000 * 10**9,
contract_balance=0,
),
],
id="send_exact_eth_amount_for_deposit",
),
pytest.param(
[
DepositContract(
requests=[
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=32_000_000_000,
signature=0x03,
index=0x0,
),
DepositRequest(
pubkey=0x01,
withdrawal_credentials=0x02,
amount=32_000_000_000,
signature=0x03,
index=0x1,
),
],
# Send 64 ETH (in wei) to the contract
tx_value=64_000_000_000 * 10**9,
contract_balance=0,
),
],
id="send_exact_eth_amount_for_multiple_deposits",
),
],
)
def test_deposit(
Expand Down
Loading
Loading