Skip to content
Draft
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
26 changes: 21 additions & 5 deletions eth_tester/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import time
from typing import (
List,
Union,
)

from eth_typing import (
Expand All @@ -29,6 +30,12 @@
from eth_tester.backends import (
get_chain_backend,
)
from eth_tester.backends.eels.main import (
EELSBackend,
)
from eth_tester.backends.pyevm.main import (
PyEVMBackend,
)
from eth_tester.constants import (
ZERO_ADDRESS_HEX,
)
Expand All @@ -40,6 +47,9 @@
TransactionNotFound,
ValidationError,
)
from eth_tester.models import (
Account,
)
from eth_tester.normalization import (
get_normalizer_backend,
)
Expand Down Expand Up @@ -105,7 +115,7 @@ def _clean_pending_transaction(pending_transaction):


class EthereumTester:
backend = None
backend: Union[PyEVMBackend, EELSBackend] = None

validator = None
normalizer = None
Expand Down Expand Up @@ -186,10 +196,16 @@ def time_travel(self, to_timestamp):
#
# Accounts
#
def get_accounts(self):
raw_accounts = self.backend.get_accounts()
self.validator.validate_outbound_accounts(raw_accounts)
accounts = self.normalizer.normalize_outbound_account_list(raw_accounts)
# def get_accounts(self):
# raw_accounts = self.backend.get_accounts()
# self.validator.validate_outbound_accounts(raw_accounts)
# accounts = self.normalizer.normalize_outbound_account_list(raw_accounts)
# return accounts

def get_accounts(self) -> List[Account]:
accounts = [
Account(address=account).address for account in self.backend.get_accounts()
]
return accounts

def add_account(self, private_key, password=None):
Expand Down
90 changes: 90 additions & 0 deletions eth_tester/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from typing import (
List,
)

from eth_typing import (
HexStr,
)
from eth_utils.curried import (
to_checksum_address,
)
from pydantic import (
BaseModel,
Field,
field_validator,
)

from eth_tester.validation.common import (
validate_bytes,
)
from eth_tester.validation.outbound import (
validate_canonical_address,
)


def _validate_address(value: bytes) -> bytes:
"""
Validate that the given value is a valid Ethereum address.
"""
validate_bytes(value)
validate_canonical_address(value)
return value


class Account(BaseModel):
"""
An account is a representation of an Ethereum account.
It contains information about the account, such as its address and balance.
"""

# The address of the account
address: bytes

@field_validator("address")
@classmethod
def validate_address(cls, value: bytes) -> HexStr:
"""
Validate that the given value is a valid Ethereum address.
"""
return to_checksum_address(_validate_address(value))


class LogEntry(BaseModel):
"""
A log entry is a record of an event emitted by a contract.
It contains information about the event, such as its address, topics, and data.
"""

# The address of the contract that emitted the event
address: str = Field(default="", description="Address of the contract")

# The topics of the event
topics: List[str] = Field(default_factory=list, description="Topics of the event")

# The data of the event
data: str = Field(default="", description="Data of the event")


class Receipt(BaseModel):
"""
A receipt is a record of the execution of a transaction.
It contains information about the transaction, such as its status, gas used, and logs generated.
"""

# The status of the transaction (1 for success, 0 for failure)
status: int = Field(
default=1, description="Transaction status: 1 for success, 0 for failure"
)

# The cumulative gas used by the transaction
cumulative_gas_used: int = Field(
default=0, description="Cumulative gas used by the transaction"
)

# The gas used by the transaction
gas_used: int = Field(default=0, description="Gas used by the transaction")

# The logs generated by the transaction
logs: List[LogEntry] = Field(
default_factory=List, description="Logs generated by the transaction"
)
10 changes: 6 additions & 4 deletions tests/backends/test_pyevm.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pytest

from eth.constants import (
POST_MERGE_DIFFICULTY,
POST_MERGE_MIX_HASH,
Expand All @@ -25,6 +24,8 @@
)
from eth_utils import (
ValidationError as EthUtilsValidationError,
)
from eth_utils import (
encode_hex,
is_hexstr,
to_hex,
Expand All @@ -50,6 +51,9 @@
BlockNotFound,
ValidationError,
)
from eth_tester.models import (
Account as AccountModel,
)
from eth_tester.normalization.outbound import (
normalize_withdrawal,
)
Expand Down Expand Up @@ -194,9 +198,7 @@ def test_apply_withdrawals():
)
# withdrawal amounts are in gwei, balance is measured in wei
assert backend.get_balance(b"\x01" * 20) == 100 * 10**9 # 100 gwei
assert (
backend.get_balance(b"\x02" * 20) == (2**64 - 1) * 10**9
) # 2**64 - 1 gwei
assert backend.get_balance(b"\x02" * 20) == (2**64 - 1) * 10**9 # 2**64 - 1 gwei

assert (
mined_block["withdrawals_root"]
Expand Down