Skip to content
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

Check if ETHEREUM_4337_BUNDLER_URL uses the correct chainId #2013

Merged
merged 1 commit into from
Apr 29, 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
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from ..models import SafeOperationConfirmation as SafeOperationConfirmationModel
from ..models import UserOperation as UserOperationModel
from ..models import UserOperationReceipt as UserOperationReceiptModel
from ..utils import get_bundler_client

logger = logging.getLogger(__name__)

Expand All @@ -42,11 +43,7 @@ class ExecutionFromSafeModuleNotDetected(AaProcessorServiceException):
@cache
def get_aa_processor_service() -> "AaProcessorService":
ethereum_client = EthereumClientProvider()
bundler_client = (
BundlerClient(settings.ETHEREUM_4337_BUNDLER_URL)
if settings.ETHEREUM_4337_BUNDLER_URL
else None
)
bundler_client = get_bundler_client()
if not bundler_client:
logger.warning("Ethereum 4337 bundler client was not configured")
supported_entry_points = settings.ETHEREUM_4337_SUPPORTED_ENTRY_POINTS
Expand Down
20 changes: 20 additions & 0 deletions safe_transaction_service/account_abstraction/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import logging
from functools import cache
from typing import Optional

from django.conf import settings

from gnosis.eth.account_abstraction import BundlerClient

logger = logging.getLogger(__name__)


@cache
def get_bundler_client() -> Optional[BundlerClient]:
"""
:return: Initialized `ERC4337 RPC Bundler Client` if configured, `None` otherwise
"""
if settings.ETHEREUM_4337_BUNDLER_URL:
return BundlerClient(settings.ETHEREUM_4337_BUNDLER_URL)
logger.warning("ETHEREUM_4337_BUNDLER_URL not set, cannot configure bundler client")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One warning is for the bundler client, other is for initializing the AccountAbstractionService, I don't think they are redundant

return None
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.core.management.base import BaseCommand, CommandError

from safe_transaction_service.account_abstraction.utils import get_bundler_client
from safe_transaction_service.utils.ethereum import get_chain_id

from ...models import Chain
Expand All @@ -16,11 +17,23 @@ def handle(self, *args, **options):
except Chain.DoesNotExist:
chain = Chain.objects.create(chain_id=chain_id)

if chain.chain_id == chain_id:
self.stdout.write(
self.style.SUCCESS(f"EthereumRPC chainId {chain_id} looks good")
)
else:
if chain_id != chain.chain_id:
raise CommandError(
f"EthereumRPC chainId {chain_id} does not match previously used chainId {chain.chain_id}"
)
self.stdout.write(
self.style.SUCCESS(f"EthereumRPC chainId {chain_id} looks good")
)

if bundler_client := get_bundler_client():
bundler_chain_id = bundler_client.get_chain_id()
if bundler_chain_id != chain.chain_id:
raise CommandError(
f"ERC4337 BundlerClient chainId {bundler_chain_id} does not match "
f"EthereumClient chainId {chain.chain_id}"
)
self.stdout.write(
self.style.SUCCESS(
f"ERC4337 BundlerClient chainId {chain_id} looks good"
)
)
39 changes: 38 additions & 1 deletion safe_transaction_service/history/tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django_celery_beat.models import PeriodicTask
from eth_account import Account

from gnosis.eth.account_abstraction import BundlerClient
from gnosis.eth.ethereum_client import EthereumClient, EthereumNetwork
from gnosis.safe.tests.safe_test_case import SafeTestCaseMixin

Expand Down Expand Up @@ -421,10 +422,16 @@ def test_export_multisig_tx_data(self):
call_command(command, arguments, stdout=buf)
self.assertIn("Start exporting of 1", buf.getvalue())

@mock.patch(
"safe_transaction_service.history.management.commands.check_chainid_matches.get_bundler_client",
return_value=None,
)
@mock.patch(
"safe_transaction_service.history.management.commands.check_chainid_matches.get_chain_id"
)
def test_check_chainid_matches(self, get_chain_id_mock: MagicMock):
def test_check_chainid_matches(
self, get_chain_id_mock: MagicMock, get_bundler_client_mock: MagicMock
):
command = "check_chainid_matches"

# Create ChainId model
Expand All @@ -447,6 +454,36 @@ def test_check_chainid_matches(self, get_chain_id_mock: MagicMock):
call_command(command, stdout=buf)
self.assertIn("EthereumRPC chainId 1 looks good", buf.getvalue())

@mock.patch.object(BundlerClient, "get_chain_id", return_value=1234)
@mock.patch(
"safe_transaction_service.history.management.commands.check_chainid_matches.get_bundler_client",
return_value=BundlerClient(""),
)
@mock.patch(
"safe_transaction_service.history.management.commands.check_chainid_matches.get_chain_id",
return_value=EthereumNetwork.MAINNET.value,
)
def test_check_chainid_bundler_matches(
self,
get_chain_id_mock: MagicMock,
get_bundler_client_mock: MagicMock,
bundler_get_chain_id_mock: MagicMock,
):
command = "check_chainid_matches"
with self.assertRaisesMessage(
CommandError,
"ERC4337 BundlerClient chainId 1234 does not match EthereumClient chainId 1",
):
call_command(command)

bundler_get_chain_id_mock.return_value = EthereumNetwork.MAINNET.value
buf = StringIO()
call_command(command, stdout=buf)
self.assertEqual(
"EthereumRPC chainId 1 looks good\nERC4337 BundlerClient chainId 1 looks good\n",
buf.getvalue(),
)

@mock.patch(
"safe_transaction_service.history.management.commands.check_index_problems.settings.ETH_L2_NETWORK",
return_value=True,
Expand Down
Loading