Skip to content

Commit

Permalink
Bump web3 to v7 and HexBytes to v1
Browse files Browse the repository at this point in the history
- Update safe-eth-py
- Fix some method names
- Refactor `.hex()` calls to don't depend on `HexBytes`
  • Loading branch information
Uxio0 committed Feb 5, 2025
1 parent 6508405 commit ef64a71
Show file tree
Hide file tree
Showing 44 changed files with 500 additions and 328 deletions.
5 changes: 2 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ drf-spectacular==0.28.0
firebase-admin==6.5.0
flower==2.0.1
gunicorn[gevent]==22.0.0
hexbytes==0.3.1
hiredis==3.0.0
packaging>=21.0
pika==1.3.2
Expand All @@ -33,5 +32,5 @@ psycogreen==1.0.2
psycopg[binary]==3.2.3
redis==5.2.1
requests==2.32.3
safe-eth-py[django]==6.4.0
web3==6.20.2
safe-eth-py[django]==7.0.0
web3==7.8.0
5 changes: 3 additions & 2 deletions safe_transaction_service/account_abstraction/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from eth_typing import ChecksumAddress
from hexbytes import HexBytes
from safe_eth.eth.django.admin import AdvancedAdminSearchMixin
from safe_eth.util.util import to_0x_hex_str

from .models import SafeOperation, UserOperation, UserOperationReceipt

Expand Down Expand Up @@ -42,11 +43,11 @@ class ForeignClassToUserOperationAdmin(AdvancedAdminSearchMixin, admin.ModelAdmi

@admin.display()
def ethereum_tx(self, obj: ForeignClassToUserOperationType) -> str:
return HexBytes(obj.user_operation.ethereum_tx.tx_hash).hex()
return to_0x_hex_str(HexBytes(obj.user_operation.ethereum_tx.tx_hash))

@admin.display()
def user_operation_hash(self, obj: ForeignClassToUserOperationType) -> str:
return HexBytes(obj.user_operation.hash).hex()
return to_0x_hex_str(HexBytes(obj.user_operation.hash))

@admin.display()
def user_operation_sender(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from eth_typing import ChecksumAddress
from safe_eth.eth.utils import fast_to_checksum_address
from safe_eth.util.util import to_0x_hex_str

from safe_transaction_service.history.models import EthereumTx

Expand Down Expand Up @@ -39,7 +40,7 @@ def reindex(
self,
addresses: Optional[Sequence[ChecksumAddress]],
) -> None:
topic = USER_OPERATION_EVENT_TOPIC.hex()
topic = to_0x_hex_str(USER_OPERATION_EVENT_TOPIC)
aa_processor_service = get_aa_processor_service()
processed_user_operations = 0
for tx in EthereumTx.objects.account_abstraction_txs():
Expand Down
9 changes: 5 additions & 4 deletions safe_transaction_service/account_abstraction/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
)
from safe_eth.safe.account_abstraction import SafeOperation as SafeOperationClass
from safe_eth.safe.safe_signature import SafeSignatureType
from safe_eth.util.util import to_0x_hex_str

from safe_transaction_service.history import models as history_models
from safe_transaction_service.utils.constants import SIGNATURE_LENGTH
Expand Down Expand Up @@ -58,7 +59,7 @@ class Meta:
]

def __str__(self) -> str:
return f"{HexBytes(self.hash).hex()} UserOperation for sender={self.sender} with nonce={self.nonce}"
return f"{to_0x_hex_str(HexBytes(self.hash))} UserOperation for sender={self.sender} with nonce={self.nonce}"

@cached_property
def paymaster_and_data(self) -> Optional[HexBytes]:
Expand Down Expand Up @@ -123,7 +124,7 @@ class UserOperationReceipt(models.Model):
deposited = Uint256Field()

def __str__(self) -> str:
return f"{HexBytes(self.user_operation_id).hex()} UserOperationReceipt"
return f"{to_0x_hex_str(HexBytes(self.user_operation_id))} UserOperationReceipt"


class SafeOperationQuerySet(models.QuerySet):
Expand Down Expand Up @@ -151,7 +152,7 @@ class SafeOperation(TimeStampedModel):
module_address = EthereumAddressBinaryField(db_index=True)

def __str__(self) -> str:
return f"{HexBytes(self.hash).hex()} SafeOperation for user-operation={HexBytes(self.user_operation_id).hex()}"
return f"{to_0x_hex_str(HexBytes(self.hash))} SafeOperation for user-operation={to_0x_hex_str(HexBytes(self.user_operation_id))}"

def build_signature_prefix(self) -> bytes:
"""
Expand Down Expand Up @@ -217,5 +218,5 @@ class Meta:
def __str__(self):
return (
f"Safe Operation Confirmation of owner={self.owner} for "
f"safe-operation={HexBytes(self.safe_operation_id).hex()}"
f"safe-operation={to_0x_hex_str(HexBytes(self.safe_operation_id))}"
)
9 changes: 5 additions & 4 deletions safe_transaction_service/account_abstraction/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from safe_eth.eth.utils import fast_keccak, fast_to_checksum_address
from safe_eth.safe.account_abstraction import SafeOperation as SafeOperationClass
from safe_eth.safe.safe_signature import SafeSignature, SafeSignatureType
from safe_eth.util.util import to_0x_hex_str

from safe_transaction_service.utils.constants import SIGNATURE_LENGTH
from safe_transaction_service.utils.ethereum import get_chain_id
Expand Down Expand Up @@ -72,11 +73,11 @@ def _validate_signature(
if owner not in safe_owners:
raise ValidationError(
f"Signer={owner} is not an owner. Current owners={safe_owners}. "
f"Safe-operation-hash={safe_operation_hash.hex()}"
f"Safe-operation-hash={to_0x_hex_str(safe_operation_hash)}"
)
if not safe_signature.is_valid(self.ethereum_client, safe_address):
raise ValidationError(
f"Signature={safe_signature.signature.hex()} for owner={owner} is not valid"
f"Signature={to_0x_hex_str(safe_signature.signature)} for owner={owner} is not valid"
)
if owner in owners_processed:
raise ValidationError(f"Signature for owner={owner} is duplicated")
Expand Down Expand Up @@ -241,7 +242,7 @@ def validate(self, attrs):

if SafeOperationModel.objects.filter(hash=safe_operation_hash).exists():
raise ValidationError(
f"SafeOperation with hash={safe_operation_hash.hex()} already exists"
f"SafeOperation with hash={to_0x_hex_str(safe_operation_hash)} already exists"
)

safe_signatures = self._validate_signature(
Expand Down Expand Up @@ -456,7 +457,7 @@ def get_prepared_signature(self, obj: SafeOperationModel) -> HexStr:
:return: Serialized queryset
"""
signature = obj.build_signature()
return HexStr(HexBytes(signature).hex())
return to_0x_hex_str(HexBytes(signature))


class SafeOperationWithUserOperationResponseSerializer(SafeOperationResponseSerializer):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from safe_eth.eth.utils import fast_to_checksum_address
from safe_eth.safe.account_abstraction import SafeOperation
from safe_eth.safe.safe_signature import SafeSignature
from safe_eth.util.util import to_0x_hex_str
from web3.types import LogReceipt

from safe_transaction_service.history import models as history_models
Expand Down Expand Up @@ -161,15 +162,15 @@ def index_safe_operation(
"[%s] Cannot find ExecutionFromModuleSuccess or ExecutionFromModuleFailure "
"events for user-operation-hash=%s , it seems like UserOperation was reverted",
user_operation_model.sender,
user_operation.user_operation_hash.hex(),
to_0x_hex_str(user_operation.user_operation_hash),
)
if user_operation_receipt.get_deployed_account():
# UserOperation `initCode` was executed but `callData` failed, so account was deployed but
# SafeOperation was reverted
logger.info(
"[%s] user-operation-hash=%s was reverted but contract was deployed",
user_operation_model.sender,
user_operation.user_operation_hash.hex(),
to_0x_hex_str(user_operation.user_operation_hash),
)
# As `module_address` cannot be detected there's not enough data to index the SafeOperation
return None
Expand All @@ -195,8 +196,8 @@ def index_safe_operation(
logger.debug(
"[%s] safe-operation-hash=%s for user-operation-hash=%s was already indexed",
user_operation_model.sender,
HexBytes(safe_operation_hash).hex(),
user_operation.user_operation_hash.hex(),
to_0x_hex_str(HexBytes(safe_operation_hash)),
to_0x_hex_str(user_operation.user_operation_hash),
)
self.index_safe_operation_confirmations(
HexBytes(safe_operation.signature), safe_operation_model, safe_operation
Expand All @@ -214,8 +215,8 @@ def index_user_operation_receipt(
:return: Tuple with ``UserOperation`` and ``UserOperationReceipt``
"""
safe_address = user_operation_model.sender
user_operation_hash_hex = HexBytes(user_operation_model.hash).hex()
tx_hash = HexBytes(user_operation_model.ethereum_tx_id).hex()
user_operation_hash_hex = to_0x_hex_str(HexBytes(user_operation_model.hash))
tx_hash = to_0x_hex_str(HexBytes(user_operation_model.ethereum_tx_id))
logger.debug(
"[%s] Retrieving UserOperation Receipt with user-operation-hash=%s on tx-hash=%s",
safe_address,
Expand Down Expand Up @@ -285,7 +286,7 @@ def index_user_operation(
:param ethereum_tx: Stored EthereumTx in database containing the ``UserOperation``
:return: tuple of ``UserOperationModel`` and ``UserOperation``
"""
user_operation_hash_hex = user_operation_hash.hex()
user_operation_hash_hex = to_0x_hex_str(user_operation_hash)
# If the UserOperationReceipt is present, UserOperation was already processed and mined
if self.is_user_operation_indexed(user_operation_hash_hex):
logger.warning(
Expand Down
11 changes: 8 additions & 3 deletions safe_transaction_service/account_abstraction/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from safe_eth.eth.constants import NULL_ADDRESS
from safe_eth.eth.utils import fast_keccak_text
from safe_eth.safe.safe_signature import SafeSignatureType
from safe_eth.util.util import to_0x_hex_str

from safe_transaction_service.history.tests import factories as history_factories

Expand All @@ -23,7 +24,9 @@ class Params:
valid_after = 0
valid_until = 0

hash = factory.Sequence(lambda n: fast_keccak_text(f"user-operation-{n}").hex())
hash = factory.Sequence(
lambda n: to_0x_hex_str(fast_keccak_text(f"user-operation-{n}"))
)
ethereum_tx = factory.SubFactory(history_factories.EthereumTxFactory)
sender = factory.LazyFunction(lambda: Account.create().address)
nonce = factory.Sequence(lambda n: n)
Expand Down Expand Up @@ -59,7 +62,9 @@ class SafeOperationFactory(DjangoModelFactory):
class Meta:
model = models.SafeOperation

hash = factory.Sequence(lambda n: fast_keccak_text(f"safe-operation-{n}").hex())
hash = factory.Sequence(
lambda n: to_0x_hex_str(fast_keccak_text(f"safe-operation-{n}"))
)
user_operation = factory.SubFactory(UserOperationFactory)
valid_after = factory.LazyFunction(timezone.now)
valid_until = factory.LazyFunction(timezone.now)
Expand All @@ -76,6 +81,6 @@ class Params:
safe_operation = factory.SubFactory(SafeOperationFactory)
owner = factory.LazyAttribute(lambda o: o.signing_owner.address)
signature = factory.LazyAttribute(
lambda o: o.signing_owner.signHash(o.safe_operation.hash)["signature"]
lambda o: o.signing_owner.unsafe_sign_hash(o.safe_operation.hash)["signature"]
)
signature_type = SafeSignatureType.EOA.value
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
user_operation_v07_hash,
user_operation_v07_mock,
)
from safe_eth.util.util import to_0x_hex_str

from safe_transaction_service.account_abstraction.services import (
get_aa_processor_service,
Expand Down Expand Up @@ -71,7 +72,8 @@ def tearDown(self):
"get_user_operation_by_hash",
autospec=True,
return_value=UserOperationClass.from_bundler_response(
safe_4337_user_operation_hash_mock.hex(), user_operation_mock["result"]
to_0x_hex_str(safe_4337_user_operation_hash_mock),
user_operation_mock["result"],
),
)
@mock.patch.object(
Expand All @@ -97,10 +99,10 @@ def test_process_aa_transaction(
user_operation_confirmation_model = SafeOperationConfirmationModel.objects.get()

self.assertEqual(
user_operation_model.hash, aa_expected_user_operation_hash.hex()
user_operation_model.hash, to_0x_hex_str(aa_expected_user_operation_hash)
)
self.assertEqual(
safe_operation_model.hash, aa_expected_safe_operation_hash.hex()
safe_operation_model.hash, to_0x_hex_str(aa_expected_safe_operation_hash)
)
self.assertEqual(user_operation_receipt_model.deposited, 759940285250436)
self.assertEqual(
Expand Down Expand Up @@ -128,7 +130,8 @@ def test_process_aa_transaction(
"get_user_operation_by_hash",
autospec=True,
return_value=UserOperationClass.from_bundler_response(
user_operation_v07_hash.hex(), user_operation_v07_mock["result"]
to_0x_hex_str(user_operation_v07_hash),
user_operation_v07_mock["result"],
),
)
@mock.patch.object(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
user_operation_mock,
)
from safe_eth.safe.account_abstraction import SafeOperation as SafeOperationClass
from safe_eth.util.util import to_0x_hex_str

from safe_transaction_service.history.tests import factories as history_factories

Expand All @@ -20,7 +21,8 @@ class TestModels(TestCase):
def test_user_operation(self):
expected_user_operation_hash = safe_4337_user_operation_hash_mock
expected_user_operation = UserOperationClass.from_bundler_response(
expected_user_operation_hash.hex(), user_operation_mock["result"]
to_0x_hex_str(expected_user_operation_hash),
user_operation_mock["result"],
)
expected_safe_operation = SafeOperationClass.from_user_operation(
expected_user_operation
Expand Down
Loading

0 comments on commit ef64a71

Please sign in to comment.