Skip to content

Commit 6cd6b44

Browse files
committed
v1.5.0: support both v1.4.1 and v1.5.0 in account abstraction, fix account abstraction tests
1 parent 8118253 commit 6cd6b44

File tree

2 files changed

+63
-5
lines changed

2 files changed

+63
-5
lines changed

safe_transaction_service/account_abstraction/helpers.py

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
from eth_typing import ChecksumAddress
44
from safe_eth.eth import EthereumClient
5-
from safe_eth.eth.contracts import get_safe_V1_5_0_contract
5+
from safe_eth.eth.contracts import get_safe_V1_4_1_contract, get_safe_V1_5_0_contract
66
from safe_eth.eth.utils import fast_to_checksum_address
7-
from safe_eth.safe.proxy_factory import ProxyFactoryV150
7+
from safe_eth.safe.proxy_factory import ProxyFactoryV141, ProxyFactoryV150
8+
from safe_eth.safe.safe_deployments import default_safe_deployments
89

910

1011
@dataclasses.dataclass(eq=True, frozen=True)
@@ -41,12 +42,15 @@ def decode_init_code(
4142
- The ``ProxyFactory`` then deploys a ``Safe Proxy`` and calls ``setup`` with all the configuration parameters.
4243
:param ethereum_client:
4344
:return: Decoded Init Code dataclass
44-
:raises ValueError: Problem decoding
45+
:raises ValueError: Problem decoding or unknown factory address
4546
"""
4647
factory_address = fast_to_checksum_address(init_code[:20])
4748
factory_data = init_code[20:]
48-
proxy_factory = ProxyFactoryV150(factory_address, ethereum_client)
49-
safe_contract = get_safe_V1_5_0_contract(ethereum_client.w3)
49+
50+
proxy_factory, safe_contract = get_contract_instances(
51+
factory_address, ethereum_client
52+
)
53+
5054
_, data = proxy_factory.contract.decode_function_input(factory_data)
5155
initializer = data.pop("initializer")
5256
_, safe_deployment_data = safe_contract.decode_function_input(initializer)
@@ -77,3 +81,35 @@ def decode_init_code(
7781
]
7882
),
7983
)
84+
85+
86+
def get_contract_instances(
87+
factory_address: ChecksumAddress, ethereum_client: EthereumClient
88+
):
89+
"""
90+
Find the appropriate proxy factory and safe contract instances for a given factory address.
91+
92+
:param factory_address: The address of the ProxyFactory contract
93+
:param ethereum_client: Ethereum client instance
94+
:return: Tuple of (proxy_factory, safe_contract)
95+
:raises ValueError: If factory address is not found in safe_deployments
96+
"""
97+
# Map versions to their factory and contract classes
98+
version_configs = {
99+
"1.4.1": (ProxyFactoryV141, get_safe_V1_4_1_contract),
100+
"1.5.0": (ProxyFactoryV150, get_safe_V1_5_0_contract),
101+
}
102+
103+
# Find which version the factory address belongs to
104+
for version, (factory_class, safe_contract_fn) in version_configs.items():
105+
factory_addresses = default_safe_deployments[version]["SafeProxyFactory"]
106+
if any(factory_address == address for address in factory_addresses):
107+
return (
108+
factory_class(factory_address, ethereum_client),
109+
safe_contract_fn(ethereum_client.w3),
110+
)
111+
112+
raise ValueError(
113+
f"Unknown ProxyFactory address: {factory_address}. "
114+
"Factory address is not registered in safe_deployments."
115+
)

safe_transaction_service/account_abstraction/tests/test_helpers.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,35 @@
11
from django.test import TestCase
22

33
from hexbytes import HexBytes
4+
from safe_eth.eth.contracts import get_proxy_factory_contract
45
from safe_eth.eth.tests.mocks.mock_bundler import user_operation_mock
6+
from safe_eth.safe.proxy_factory import ProxyFactoryV141
57
from safe_eth.safe.tests.safe_test_case import SafeTestCaseMixin
68

79
from ..helpers import DecodedInitCode, decode_init_code
810

911

1012
class TestAccountAbstractionHelpers(SafeTestCaseMixin, TestCase):
13+
@classmethod
14+
def setUpClass(cls):
15+
super().setUpClass()
16+
17+
# Deploy v1.4.1 proxy factory if not already deployed
18+
if "proxy_factory_V1_4_1" not in cls.contract_addresses:
19+
cls.contract_addresses["proxy_factory_V1_4_1"] = (
20+
ProxyFactoryV141.deploy_contract(
21+
cls.ethereum_client, cls.ethereum_test_account
22+
).contract_address
23+
)
24+
25+
# Create proxy factory v1.4.1 instance
26+
cls.proxy_factory_contract_V1_4_1 = get_proxy_factory_contract(
27+
cls.w3, cls.contract_addresses["proxy_factory_V1_4_1"]
28+
)
29+
cls.proxy_factory_V1_4_1 = ProxyFactoryV141(
30+
cls.proxy_factory_contract_V1_4_1.address, cls.ethereum_client
31+
)
32+
1133
def test_decode_init_code(self):
1234
with self.assertRaises(ValueError):
1335
decode_init_code(b"", self.ethereum_client)

0 commit comments

Comments
 (0)