Skip to content

Upgrade web3py to v7. Add missing tests for W3Provider.get_events #9

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 2 commits into from
Sep 11, 2024
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
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ exclude =
# `pip install eth-prototype[PDF]` like:
# PDF = ReportLab; RXP
web3 =
web3==6.*
web3==7.*

defender =
boto3
Expand All @@ -77,7 +77,7 @@ testing =
pytest
gmpy2
pytest-cov
web3[tester]==6.*
web3[tester]==7.*
boto3

[options.entry_points]
Expand Down
27 changes: 15 additions & 12 deletions src/ethproto/aa_bundler.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import random
from warnings import warn
from enum import Enum
import requests
from warnings import warn

from environs import Env
from eth_abi import encode
from eth_account import Account
from eth_account.messages import encode_defunct
from eth_utils import add_0x_prefix
from hexbytes import HexBytes
from web3 import Web3
from web3.constants import ADDRESS_ZERO
from .contracts import RevertError

from .contracts import RevertError

env = Env()

Expand Down Expand Up @@ -55,8 +56,8 @@


def pack_two(a, b):
a = HexBytes(a).hex()[2:]
b = HexBytes(b).hex()[2:]
a = HexBytes(a).hex()
b = HexBytes(b).hex()
return "0x" + a.zfill(32) + b.zfill(32)


Expand Down Expand Up @@ -102,23 +103,23 @@ def hash_packed_user_operation_only(packed_user_op):
hash_paymaster_and_data,
],
).hex()
).hex()
)


def hash_packed_user_operation(packed_user_op, chain_id, entry_point):
return Web3.keccak(
hexstr=encode(
["bytes32", "address", "uint256"],
[HexBytes(hash_packed_user_operation_only(packed_user_op)), entry_point, chain_id],
[hash_packed_user_operation_only(packed_user_op), entry_point, chain_id],
).hex()
).hex()
)


def sign_user_operation(private_key, user_operation, chain_id, entry_point):
packed_user_op = pack_user_operation(user_operation)
hash = hash_packed_user_operation(packed_user_op, chain_id, entry_point)
signature = Account.sign_message(encode_defunct(hexstr=hash), private_key)
return signature.signature.hex()
signature = Account.sign_message(encode_defunct(hexstr=hash.hex()), private_key)
return signature.signature


def make_nonce(nonce_key, nonce):
Expand Down Expand Up @@ -232,8 +233,10 @@ def send_transaction(w3, tx, retry_nonce=None):
"maxPriorityFeePerGas": "0x00",
}
)
user_operation["signature"] = sign_user_operation(
AA_BUNDLER_EXECUTOR_PK, user_operation, tx["chainId"], AA_BUNDLER_ENTRYPOINT
user_operation["signature"] = add_0x_prefix(
sign_user_operation(
AA_BUNDLER_EXECUTOR_PK, user_operation, tx["chainId"], AA_BUNDLER_ENTRYPOINT
).hex()
)
# Remove paymaster related fields
user_operation.pop("paymaster", None)
Expand Down
25 changes: 16 additions & 9 deletions src/ethproto/w3wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from hexbytes import HexBytes
from web3.contract import Contract
from web3.exceptions import ContractLogicError, ExtraDataLengthError
from web3.middleware import geth_poa_middleware
from web3.middleware import ExtraDataToPOAMiddleware

from .build_artifacts import ArtifactLibrary
from .contracts import RevertError
Expand Down Expand Up @@ -49,14 +49,21 @@ def now(self):
return self.w3.eth.get_block("latest").timestamp


def register_w3_provider(provider_key="w3", tester=None, provider_kwargs={}):
def register_w3_provider(provider_key="w3", w3=None, tester=None, provider_kwargs=None):
if w3 is not None and tester is not None:
raise ValueError("Cannot inject w3 and use tester at the same time")

provider_kwargs = provider_kwargs or {}
if tester is None:
try:
import eth_tester # noqa
except ImportError:
tester = False

if tester:
if w3 is not None:
# the provided w3 instance takes precedence over all other args
pass
elif tester:
from web3 import Web3

w3 = Web3(Web3.EthereumTesterProvider())
Expand All @@ -68,9 +75,9 @@ def register_w3_provider(provider_key="w3", tester=None, provider_kwargs={}):
try:
w3.eth.get_block("latest")
except ExtraDataLengthError:
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
elif W3_POA == "yes":
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)

# If address_book not provided and there are envs with W3_ADDRESS_BOOK_PREFIX,
# use W3EnvAddressBook
Expand Down Expand Up @@ -444,7 +451,7 @@ def deploy(self, eth_contract, init_params, from_, **kwargs):
def get_events(self, eth_wrapper, event_name, filter_kwargs={}):
"""Returns a list of events given a filter, like this:

>>> provider.get_events(currencywrapper, "Transfer", dict(fromBlock=0))
>>> provider.get_events(currencywrapper, "Transfer", dict(from_block=0))
[AttributeDict({
'args': AttributeDict(
{'from': '0x0000000000000000000000000000000000000000',
Expand All @@ -463,8 +470,8 @@ def get_events(self, eth_wrapper, event_name, filter_kwargs={}):
"""
contract = eth_wrapper.contract
event = getattr(contract.events, event_name)
if "fromBlock" not in filter_kwargs:
filter_kwargs["fromBlock"] = self.get_first_block(eth_wrapper)
if "from_block" not in filter_kwargs:
filter_kwargs["from_block"] = self.get_first_block(eth_wrapper)
event_filter = event.create_filter(**filter_kwargs)
return event_filter.get_all_entries()

Expand All @@ -490,7 +497,7 @@ def init_eth_wrapper(self, eth_wrapper, owner, init_params, kwargs):
constructor_params, init_params = init_params
real_contract = self.construct(eth_contract, constructor_params, {"from": eth_wrapper.owner})
ERC1967Proxy = self.get_contract_factory("ERC1967Proxy")
init_data = eth_contract.encodeABI(fn_name="initialize", args=init_params)
init_data = eth_contract.encode_abi(abi_element_identifier="initialize", args=init_params)
proxy_contract = self.construct(
ERC1967Proxy,
(real_contract.address, init_data),
Expand Down
16 changes: 16 additions & 0 deletions tests/hardhat-project/contracts/EventLauncher.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

contract EventLauncher {
event Event1(uint256 value);

event Event2(uint256 value);

function launchEvent1(uint256 value) public {
emit Event1(value);
}

function launchEvent2(uint256 value) public {
emit Event2(value);
}
}
21 changes: 10 additions & 11 deletions tests/test_aa_bundler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import os
from unittest.mock import MagicMock, patch

from hexbytes import HexBytes
from ethproto import aa_bundler
from web3.constants import HASH_ZERO
from unittest.mock import MagicMock, patch

from ethproto import aa_bundler


def test_pack_two():
Expand Down Expand Up @@ -59,26 +60,24 @@ def test_pack_user_operation():
def test_hash_packed_user_operation():
packed = aa_bundler.pack_user_operation(user_operation)
hash = aa_bundler.hash_packed_user_operation_only(packed)
assert hash == "0xa2c19765d18b0d690c05b20061bd23d066201aff1833a51bd28af115fbd4bcd9"
assert hash == HexBytes("0xa2c19765d18b0d690c05b20061bd23d066201aff1833a51bd28af115fbd4bcd9")
hash = aa_bundler.hash_packed_user_operation(packed, CHAIN_ID, ENTRYPOINT)
assert hash == "0xb365ad4d366e9081718e926912da7a78a2faae592286fda0cc11923bd141b7cf"
assert hash == HexBytes("0xb365ad4d366e9081718e926912da7a78a2faae592286fda0cc11923bd141b7cf")


def test_sign_user_operation():
signature = aa_bundler.sign_user_operation(TEST_PRIVATE_KEY, user_operation, CHAIN_ID, ENTRYPOINT)
assert (
signature
== "0xb9b872bfe4e90f4628e8ec24879a5b01045f91da8457f3ce2b417d2e5774b508261ec1147a820e75a141cb61b884a78d7e88996ceddafb9a7016cfe7a48a1f4f1b" # noqa
assert signature == HexBytes(
"0xb9b872bfe4e90f4628e8ec24879a5b01045f91da8457f3ce2b417d2e5774b508261ec1147a820e75a141cb61b884a78d7e88996ceddafb9a7016cfe7a48a1f4f1b" # noqa
)


def test_sign_user_operation_gas_diff():
user_operation_2 = dict(user_operation)
user_operation_2["maxPriorityFeePerGas"] -= 1
signature = aa_bundler.sign_user_operation(TEST_PRIVATE_KEY, user_operation_2, CHAIN_ID, ENTRYPOINT)
assert (
signature
== "0x8162479d2dbd18d7fe93a2f51e283021d6e4eae4f57d20cdd553042723a0b0ea690ab3903d45126b0047da08ab53dfdf86656e4f258ac4936ba96a759ccb77f61b" # noqa
assert signature == HexBytes(
"0x8162479d2dbd18d7fe93a2f51e283021d6e4eae4f57d20cdd553042723a0b0ea690ab3903d45126b0047da08ab53dfdf86656e4f258ac4936ba96a759ccb77f61b" # noqa
)


Expand Down
29 changes: 29 additions & 0 deletions tests/test_w3.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,32 @@ def test_wrapper_build_from_def():
assert counter.value() == 0
counter.increase()
assert counter.value() == 1


def test_get_events():
provider = wrappers.get_provider("w3")
contract_def = provider.get_contract_def("EventLauncher")
wrapper = wrappers.ETHWrapper.build_from_def(contract_def)

launcher = wrapper()

launcher.launchEvent1(1)

cutoff_block = provider.w3.eth.get_block("latest")
launcher.launchEvent2(2)
launcher.launchEvent1(3)

all_event1 = provider.get_events(launcher, "Event1", dict(from_block=0))
assert len(all_event1) == 2

first_event1_only = provider.get_events(launcher, "Event1", dict(to_block=cutoff_block.number))
assert len(first_event1_only) == 1
assert first_event1_only[0] == all_event1[0]

last_event1_only = provider.get_events(launcher, "Event1", dict(from_block=cutoff_block.number + 1))
assert len(last_event1_only) == 1
assert last_event1_only[0] == all_event1[-1]

event2 = provider.get_events(launcher, "Event2")
assert len(event2) == 1
assert event2[0].args.value == 2
Loading