-
Notifications
You must be signed in to change notification settings - Fork 284
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Decode owners using init_code - Use `init_code` decoded owners for signature validation - Add helper to decode init_code - Refactor 4337 serializer
- Loading branch information
Showing
5 changed files
with
232 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import dataclasses | ||
from typing import List | ||
|
||
from eth_typing import ChecksumAddress | ||
|
||
from gnosis.eth import EthereumClient | ||
from gnosis.eth.contracts import get_safe_V1_4_1_contract | ||
from gnosis.eth.utils import fast_to_checksum_address | ||
from gnosis.safe.proxy_factory import ProxyFactoryV141 | ||
|
||
|
||
@dataclasses.dataclass(eq=True, frozen=True) | ||
class DecodedInitCode: | ||
# UserOperation data | ||
factory_address: ChecksumAddress | ||
factory_data: bytes # Factory call with function identifier | ||
initializer: bytes # Initializer passed to ProxyFactory | ||
# ProxyFactory data | ||
singleton: ChecksumAddress | ||
salt_nonce: int | ||
expected_address: ChecksumAddress # Expected Safe deployment address | ||
# Safe creation data | ||
owners: List[ChecksumAddress] | ||
threshold: int | ||
to: ChecksumAddress | ||
data: bytes | ||
fallback_handler: ChecksumAddress | ||
payment_token: ChecksumAddress | ||
payment: int | ||
payment_receiver: ChecksumAddress | ||
|
||
|
||
def decode_init_code( | ||
init_code: bytes, ethereum_client: EthereumClient | ||
) -> DecodedInitCode: | ||
""" | ||
Decode data to check for a valid ProxyFactory Safe deployment. | ||
:param init_code: should be composed of: | ||
- 20 first bytes with the address of the factory. | ||
- Call data for the ``Factory``. In the case of the Safe: | ||
- Call to the ``ProxyFactory``, with the ``initializer``, ``singleton`` and ``saltNonce`` | ||
- The ``ProxyFactory`` then deploys a ``Safe Proxy`` and calls ``setup`` with all the configuration parameters. | ||
:param ethereum_client: | ||
:return: Decoded Init Code dataclass | ||
:raises ValueError: Problem decoding | ||
""" | ||
factory_address = fast_to_checksum_address(init_code[:20]) | ||
factory_data = init_code[20:] | ||
proxy_factory = ProxyFactoryV141(factory_address, ethereum_client) | ||
safe_contract = get_safe_V1_4_1_contract(ethereum_client.w3) | ||
_, data = proxy_factory.contract.decode_function_input(factory_data) | ||
initializer = data.pop("initializer") | ||
_, safe_deployment_data = safe_contract.decode_function_input(initializer) | ||
|
||
singleton = data.pop("_singleton") | ||
salt_nonce = data.pop("saltNonce") | ||
expected_address = proxy_factory.calculate_proxy_address( | ||
singleton, initializer, salt_nonce, chain_specific=False | ||
) | ||
return DecodedInitCode( | ||
factory_address, | ||
factory_data, | ||
initializer, | ||
singleton, | ||
salt_nonce, | ||
expected_address, | ||
*( | ||
safe_deployment_data[field] | ||
for field in [ | ||
"_owners", | ||
"_threshold", | ||
"to", | ||
"data", | ||
"fallbackHandler", | ||
"paymentToken", | ||
"payment", | ||
"paymentReceiver", | ||
] | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
safe_transaction_service/account_abstraction/tests/test_helpers.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from django.test import TestCase | ||
|
||
from hexbytes import HexBytes | ||
|
||
from gnosis.eth.tests.mocks.mock_bundler import user_operation_mock | ||
from gnosis.safe.tests.safe_test_case import SafeTestCaseMixin | ||
|
||
from ..helpers import DecodedInitCode, decode_init_code | ||
|
||
|
||
class TestAccountAbstractionHelpers(SafeTestCaseMixin, TestCase): | ||
def test_decode_init_code(self): | ||
with self.assertRaises(ValueError): | ||
decode_init_code(b"", self.ethereum_client) | ||
|
||
expected = DecodedInitCode( | ||
factory_address="0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67", | ||
factory_data=HexBytes( | ||
"0x1688f0b900000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c7620000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4b63e800d000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008ecd4ec46d4d2a6b64fe960b3d64e8b94b2234eb0000000000000000000000000000000000000000000000000000000000000140000000000000000000000000a581c4a4db7175302464ff3c06380bc3270b403700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005ac255889882acd3da2aa939679e3f3d4cea221e00000000000000000000000000000000000000000000000000000000000000648d0dc49f00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a581c4a4db7175302464ff3c06380bc3270b40370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" | ||
), | ||
initializer=b"\xb6>\x80\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8e\xcdN\xc4mM*kd\xfe\x96\x0b=d\xe8\xb9K\"4\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa5\x81\xc4\xa4\xdbqu0$d\xff<\x068\x0b\xc3'\x0b@7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Z\xc2U\x88\x98\x82\xac\xd3\xda*\xa99g\x9e?=L\xea\"\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x8d\r\xc4\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa5\x81\xc4\xa4\xdbqu0$d\xff<\x068\x0b\xc3'\x0b@7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | ||
singleton="0x29fcB43b46531BcA003ddC8FCB67FFE91900C762", | ||
salt_nonce=0, | ||
expected_address="0xB0B5c0578Aa134b0496a6C0e51A7aae47C522861", | ||
owners=["0x5aC255889882aCd3da2aA939679E3f3d4cea221e"], | ||
threshold=1, | ||
to="0x8EcD4ec46D4D2a6B64fE960B3D64e8B94B2234eb", | ||
data=b"\x8d\r\xc4\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa5\x81\xc4\xa4\xdbqu0$d\xff<\x068\x0b\xc3'\x0b@7", | ||
fallback_handler="0xa581c4A4DB7175302464fF3C06380BC3270b4037", | ||
payment_token="0x0000000000000000000000000000000000000000", | ||
payment=0, | ||
payment_receiver="0x0000000000000000000000000000000000000000", | ||
) | ||
result = decode_init_code( | ||
HexBytes(user_operation_mock["result"]["userOperation"]["initCode"]), | ||
self.ethereum_client, | ||
) | ||
self.assertEqual(result, expected) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters