• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

safe-global / safe-eth-py / 10793540350

10 Sep 2024 01:31PM UTC coverage: 93.551% (-0.3%) from 93.892%
10793540350

push

github

falvaradorodriguez
Fix cowswap test

8777 of 9382 relevant lines covered (93.55%)

3.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.37
/safe_eth/safe/tests/safe_test_case.py
1
import logging
4✔
2
import os
4✔
3
from typing import Dict, List, Optional
4✔
4
from unittest import TestCase
4✔
5

6
from eth_account import Account
4✔
7
from eth_typing import ChecksumAddress
4✔
8
from hexbytes import HexBytes
4✔
9
from web3.contract import Contract
4✔
10
from web3.types import Wei
4✔
11

12
from safe_eth.eth.constants import NULL_ADDRESS, SAFE_SINGLETON_FACTORY_DEPLOYER_ADDRESS
4✔
13
from safe_eth.eth.contracts import (
4✔
14
    get_compatibility_fallback_handler_contract,
15
    get_multi_send_contract,
16
    get_proxy_factory_contract,
17
    get_safe_V1_0_0_contract,
18
    get_safe_V1_1_1_contract,
19
    get_safe_V1_3_0_contract,
20
    get_safe_V1_4_1_contract,
21
    get_sign_message_lib_contract,
22
    get_simulate_tx_accessor_V1_4_1_contract,
23
)
24
from safe_eth.eth.exceptions import ContractAlreadyDeployed
4✔
25
from safe_eth.eth.tests.ethereum_test_case import EthereumTestCaseMixin
4✔
26
from safe_eth.eth.tests.utils import send_tx
4✔
27
from safe_eth.eth.utils import get_empty_tx_params
4✔
28
from safe_eth.safe import Safe
4✔
29
from safe_eth.safe.multi_send import MultiSend
4✔
30
from safe_eth.safe.proxy_factory import ProxyFactory, ProxyFactoryV141
4✔
31

32
from ..safe import SafeV001, SafeV100, SafeV111, SafeV130, SafeV141
4✔
33

34
logger = logging.getLogger(__name__)
4✔
35

36

37
class SafeTestCaseMixin(EthereumTestCaseMixin, TestCase):
4✔
38
    compatibility_fallback_handler: Contract
4✔
39
    multi_send: MultiSend
4✔
40
    multi_send_contract: Contract
4✔
41
    proxy_factory: ProxyFactory
4✔
42
    proxy_factory_contract: Contract
4✔
43
    safe_contract_V1_4_1: Contract
4✔
44
    safe_contract_V0_0_1: Contract
4✔
45
    safe_contract_V1_0_0: Contract
4✔
46
    safe_contract_V1_1_1: Contract
4✔
47
    safe_contract_V1_3_0: Contract
4✔
48
    safe_contract_address: ChecksumAddress
4✔
49
    simulate_tx_accessor_V1_4_1: Contract
4✔
50

51
    contract_deployers = {
4✔
52
        "safe_V0_0_1": SafeV001.deploy_contract,
53
        "safe_V1_0_0": SafeV100.deploy_contract,
54
        "safe_V1_1_1": SafeV111.deploy_contract,
55
        "safe_V1_3_0": SafeV130.deploy_contract,
56
        "safe_V1_4_1": SafeV141.deploy_contract,
57
        "compatibility_fallback_handler": Safe.deploy_compatibility_fallback_handler,
58
        "simulate_tx_accessor_V1_4_1": Safe.deploy_simulate_tx_accessor,
59
        "proxy_factory": ProxyFactoryV141.deploy_contract,
60
        "multi_send": MultiSend.deploy_contract,
61
    }
62

63
    contract_addresses: Dict[str, ChecksumAddress] = {}
4✔
64

65
    @property
4✔
66
    def safe_contract(self):
4✔
67
        """
68
        :return: Last Safe Contract available
69
        """
70
        return self.safe_contract_V1_4_1
4✔
71

72
    @classmethod
4✔
73
    def setUpClass(cls):
4✔
74
        super().setUpClass()
4✔
75

76
        cls.deploy_safe_singleton_factory()
4✔
77

78
        if not cls.contract_addresses:
4✔
79
            # First time mixin is called, deploy Safe contracts
80
            for key, function in cls.contract_deployers.items():
4✔
81
                try:
4✔
82
                    cls.contract_addresses[key] = function(
4✔
83
                        cls.ethereum_client, cls.ethereum_test_account
84
                    ).contract_address
85
                except ContractAlreadyDeployed as e:
×
86
                    cls.contract_addresses[key] = e.address
×
87

88
        cls.configure_django_settings()
4✔
89
        cls.configure_envvars()
4✔
90

91
        cls.compatibility_fallback_handler = (
4✔
92
            get_compatibility_fallback_handler_contract(
93
                cls.w3, cls.contract_addresses["compatibility_fallback_handler"]
94
            )
95
        )
96
        cls.simulate_tx_accessor_V1_4_1 = get_simulate_tx_accessor_V1_4_1_contract(
4✔
97
            cls.w3, cls.contract_addresses["simulate_tx_accessor_V1_4_1"]
98
        )
99
        cls.safe_contract_V1_4_1 = get_safe_V1_4_1_contract(
4✔
100
            cls.w3, cls.contract_addresses["safe_V1_4_1"]
101
        )
102
        cls.safe_contract_V1_3_0 = get_safe_V1_3_0_contract(
4✔
103
            cls.w3, cls.contract_addresses["safe_V1_3_0"]
104
        )
105
        cls.safe_contract_V1_1_1 = get_safe_V1_1_1_contract(
4✔
106
            cls.w3, cls.contract_addresses["safe_V1_1_1"]
107
        )
108
        cls.safe_contract_V1_0_0 = get_safe_V1_0_0_contract(
4✔
109
            cls.w3, cls.contract_addresses["safe_V1_0_0"]
110
        )
111
        cls.safe_contract_V0_0_1 = get_safe_V1_0_0_contract(
4✔
112
            cls.w3, cls.contract_addresses["safe_V0_0_1"]
113
        )
114
        cls.proxy_factory_contract = get_proxy_factory_contract(
4✔
115
            cls.w3, cls.contract_addresses["proxy_factory"]
116
        )
117
        cls.proxy_factory = ProxyFactory(
4✔
118
            cls.proxy_factory_contract.address, cls.ethereum_client
119
        )
120
        cls.multi_send_contract = get_multi_send_contract(
4✔
121
            cls.w3, cls.contract_addresses["multi_send"]
122
        )
123
        cls.multi_send = MultiSend(
4✔
124
            cls.ethereum_client, address=cls.multi_send_contract.address
125
        )
126

127
    @classmethod
4✔
128
    def configure_django_settings(cls):
4✔
129
        """
130
        Configure settings for django based applications
131

132
        :return:
133
        """
134

135
        try:
4✔
136
            from django.conf import settings
4✔
137

138
            settings.SAFE_CONTRACT_ADDRESS = cls.contract_addresses["safe_V1_4_1"]
4✔
139
            settings.SAFE_DEFAULT_CALLBACK_HANDLER = cls.contract_addresses[
4✔
140
                "compatibility_fallback_handler"
141
            ]
142
            settings.SAFE_MULTISEND_ADDRESS = cls.contract_addresses["multi_send"]
4✔
143
            settings.SAFE_PROXY_FACTORY_ADDRESS = cls.contract_addresses[
4✔
144
                "proxy_factory"
145
            ]
146
            settings.SAFE_V0_0_1_CONTRACT_ADDRESS = cls.contract_addresses[
4✔
147
                "safe_V0_0_1"
148
            ]
149
            settings.SAFE_V1_0_0_CONTRACT_ADDRESS = cls.contract_addresses[
4✔
150
                "safe_V1_0_0"
151
            ]
152
            settings.SAFE_V1_1_1_CONTRACT_ADDRESS = cls.contract_addresses[
4✔
153
                "safe_V1_1_1"
154
            ]
155
            settings.SAFE_V1_3_0_CONTRACT_ADDRESS = cls.contract_addresses[
4✔
156
                "safe_V1_3_0"
157
            ]
158
            settings.SAFE_V1_4_1_CONTRACT_ADDRESS = cls.contract_addresses[
4✔
159
                "safe_V1_4_1"
160
            ]
161
            settings.SAFE_SIMULATE_TX_ACCESSOR = cls.contract_addresses[
4✔
162
                "simulate_tx_accessor_V1_4_1"
163
            ]
164
            settings.SAFE_VALID_CONTRACT_ADDRESSES = {
4✔
165
                settings.SAFE_CONTRACT_ADDRESS,
166
                settings.SAFE_V1_3_0_CONTRACT_ADDRESS,
167
                settings.SAFE_V1_1_1_CONTRACT_ADDRESS,
168
                settings.SAFE_V1_0_0_CONTRACT_ADDRESS,
169
                settings.SAFE_V0_0_1_CONTRACT_ADDRESS,
170
            }
171

172
        except ModuleNotFoundError:
×
173
            logger.info("Django library is not installed")
×
174

175
    @classmethod
4✔
176
    def configure_envvars(cls):
4✔
177
        """
178
        Configure environment variables
179

180
        :return:
181
        """
182
        os.environ["SAFE_SIMULATE_TX_ACCESSOR_ADDRESS"] = cls.contract_addresses[
4✔
183
            "simulate_tx_accessor_V1_4_1"
184
        ]
185

186
    @classmethod
4✔
187
    def deploy_safe_singleton_factory(cls) -> bool:
4✔
188
        """
189
        Deploy Safe Singleton Factory for deterministic deployments and speeding up tests,
190
        due to being able to check quickly if contracts are deployed in their expected addresses
191

192
        Singleton factory with `1337` chainId is used
193
        Deployer address: 0xE1CB04A0fA36DdD16a06ea828007E35e1a3cBC37
194
        Expected factory address: 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7
195

196
        :return: `True` if deployed, `False` otherwise
197
        """
198
        if cls.ethereum_client.get_singleton_factory_address():
4✔
199
            return False
4✔
200

201
        raw_tx = HexBytes(
4✔
202
            "0xf8a78085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3820a96a0460c6ea9b8f791e5d9e67fbf2c70aba92bf88591c39ac3747ea1bedc2ef1750ca04b08a4b5cea15a56276513da7a0c0b34f16e89811d5dd911efba5f8625a921cc"
203
        )
204
        send_tx(
4✔
205
            cls.w3,
206
            {
207
                "to": SAFE_SINGLETON_FACTORY_DEPLOYER_ADDRESS,
208
                "value": Wei(10000000000000000),
209
            },
210
            cls.ethereum_test_account,
211
        )
212
        tx_hash = cls.ethereum_client.send_raw_transaction(raw_tx)
4✔
213
        tx_receipt = cls.ethereum_client.get_transaction_receipt(tx_hash, timeout=30)
4✔
214
        assert tx_receipt is not None
4✔
215
        assert tx_receipt["status"] == 1
4✔
216

217
        # Clear cached empty singleton factory
218
        cls.ethereum_client.get_singleton_factory_address.cache_clear()
4✔
219

220
        return True
4✔
221

222
    def deploy_test_safe(self, *args, **kwargs) -> Safe:
4✔
223
        """
224
        :param args:
225
        :param kwargs:
226
        :return: Deploy last available Safe
227
        """
228
        return self.deploy_test_safe_v1_4_1(*args, **kwargs)
4✔
229

230
    def _deploy_test_safe(
4✔
231
        self,
232
        initializer: bytes,
233
        master_copy_address: ChecksumAddress,
234
        initial_funding_wei: Optional[Wei] = None,
235
    ) -> Safe:
236
        """
237
        Internal method to deploy a Safe given the initializer and master copy
238

239
        :param initializer:
240
        :param master_copy_address:
241
        :param initial_funding_wei: If provided, funds will be sent to the Safe
242
        :return: A deployed Safe
243
        """
244
        ethereum_tx_sent = self.proxy_factory.deploy_proxy_contract_with_nonce(
4✔
245
            self.ethereum_test_account,
246
            master_copy_address,
247
            initializer=initializer,
248
        )
249
        assert ethereum_tx_sent.contract_address is not None
4✔
250
        safe = Safe(  # type: ignore[abstract]
4✔
251
            ethereum_tx_sent.contract_address,
252
            self.ethereum_client,
253
            simulate_tx_accessor_address=self.simulate_tx_accessor_V1_4_1.address,
254
        )
255

256
        if initial_funding_wei:
4✔
257
            self.send_ether(safe.address, initial_funding_wei)
4✔
258

259
        return safe
4✔
260

261
    def _deploy_new_test_safe(
4✔
262
        self,
263
        master_copy_version: str,
264
        master_copy_address: ChecksumAddress,
265
        number_owners: int = 3,
266
        threshold: Optional[int] = None,
267
        owners: Optional[List[ChecksumAddress]] = None,
268
        initial_funding_wei: int = 0,
269
        fallback_handler: Optional[ChecksumAddress] = None,
270
    ) -> Safe:
271
        """
272
        Internal method to deploy Safes from 1.1.1 to 1.4.1, as setup method didn't change
273

274
        :param master_copy_version:
275
        :param master_copy_address:
276
        :param number_owners:
277
        :param threshold:
278
        :param owners:
279
        :param initial_funding_wei:
280
        :param fallback_handler:
281
        :return: A deployed Safe
282
        """
283

284
        fallback_handler = (
4✔
285
            fallback_handler or self.compatibility_fallback_handler.address
286
        )
287
        owners = (
4✔
288
            owners
289
            if owners
290
            else [Account.create().address for _ in range(number_owners)]
291
        )
292
        if not threshold:
4✔
293
            threshold = len(owners) - 1 if len(owners) > 1 else 1
4✔
294
        to = NULL_ADDRESS
4✔
295
        data = b""
4✔
296
        payment_token = NULL_ADDRESS
4✔
297
        payment = 0
4✔
298
        payment_receiver = NULL_ADDRESS
4✔
299
        initializer = HexBytes(
4✔
300
            self.safe_contract_V1_4_1.functions.setup(
301
                owners,
302
                threshold,
303
                to,
304
                data,
305
                fallback_handler,
306
                payment_token,
307
                payment,
308
                payment_receiver,
309
            ).build_transaction(get_empty_tx_params())["data"]
310
        )
311

312
        safe = self._deploy_test_safe(
4✔
313
            initializer,
314
            master_copy_address,
315
            initial_funding_wei=Wei(initial_funding_wei),
316
        )
317

318
        self.assertEqual(safe.retrieve_version(), master_copy_version)
4✔
319
        self.assertEqual(safe.retrieve_threshold(), threshold)
4✔
320
        self.assertCountEqual(safe.retrieve_owners(), owners)
4✔
321

322
        return safe
4✔
323

324
    def deploy_test_safe_v1_4_1(
4✔
325
        self,
326
        number_owners: int = 3,
327
        threshold: Optional[int] = None,
328
        owners: Optional[List[ChecksumAddress]] = None,
329
        initial_funding_wei: int = 0,
330
        fallback_handler: Optional[ChecksumAddress] = None,
331
    ) -> Safe:
332
        """
333
        Deploy a Safe v1.4.1
334

335
        :param number_owners:
336
        :param threshold:
337
        :param owners:
338
        :param initial_funding_wei:
339
        :param fallback_handler:
340
        :return:
341
        """
342
        return self._deploy_new_test_safe(
4✔
343
            "1.4.1",
344
            self.safe_contract_V1_4_1.address,
345
            number_owners=number_owners,
346
            threshold=threshold,
347
            owners=owners,
348
            initial_funding_wei=initial_funding_wei,
349
            fallback_handler=fallback_handler,
350
        )
351

352
    def deploy_test_safe_v1_3_0(
4✔
353
        self,
354
        number_owners: int = 3,
355
        threshold: Optional[int] = None,
356
        owners: Optional[List[ChecksumAddress]] = None,
357
        initial_funding_wei: int = 0,
358
        fallback_handler: Optional[ChecksumAddress] = None,
359
    ) -> Safe:
360
        """
361
        Deploy a Safe v1.3.0
362

363
        :param number_owners:
364
        :param threshold:
365
        :param owners:
366
        :param initial_funding_wei:
367
        :param fallback_handler:
368
        :return:
369
        """
370
        return self._deploy_new_test_safe(
4✔
371
            "1.3.0",
372
            self.safe_contract_V1_3_0.address,
373
            number_owners=number_owners,
374
            threshold=threshold,
375
            owners=owners,
376
            initial_funding_wei=initial_funding_wei,
377
            fallback_handler=fallback_handler,
378
        )
379

380
    def deploy_test_safe_v1_1_1(
4✔
381
        self,
382
        number_owners: int = 3,
383
        threshold: Optional[int] = None,
384
        owners: Optional[List[ChecksumAddress]] = None,
385
        initial_funding_wei: int = 0,
386
        fallback_handler: Optional[ChecksumAddress] = NULL_ADDRESS,
387
    ) -> Safe:
388
        return self._deploy_new_test_safe(
4✔
389
            "1.1.1",
390
            self.safe_contract_V1_1_1.address,
391
            number_owners=number_owners,
392
            threshold=threshold,
393
            owners=owners,
394
            initial_funding_wei=initial_funding_wei,
395
            fallback_handler=fallback_handler,
396
        )
397

398
    def deploy_test_safe_v1_0_0(
4✔
399
        self,
400
        number_owners: int = 3,
401
        threshold: Optional[int] = None,
402
        owners: Optional[List[ChecksumAddress]] = None,
403
        initial_funding_wei: int = 0,
404
    ) -> Safe:
405
        owners = (
4✔
406
            owners
407
            if owners
408
            else [Account.create().address for _ in range(number_owners)]
409
        )
410
        if not threshold:
4✔
411
            threshold = len(owners) - 1 if len(owners) > 1 else 1
4✔
412
        to = NULL_ADDRESS
4✔
413
        data = b""
4✔
414
        payment_token = NULL_ADDRESS
4✔
415
        payment = 0
4✔
416
        payment_receiver = NULL_ADDRESS
4✔
417
        initializer = HexBytes(
4✔
418
            self.safe_contract_V1_0_0.functions.setup(
419
                owners, threshold, to, data, payment_token, payment, payment_receiver
420
            ).build_transaction(get_empty_tx_params())["data"]
421
        )
422
        safe = self._deploy_test_safe(
4✔
423
            initializer,
424
            self.safe_contract_V1_0_0.address,
425
            initial_funding_wei=Wei(initial_funding_wei),
426
        )
427

428
        self.assertEqual(safe.retrieve_version(), "1.0.0")
4✔
429
        self.assertEqual(safe.retrieve_threshold(), threshold)
4✔
430
        self.assertCountEqual(safe.retrieve_owners(), owners)
4✔
431

432
        return safe
4✔
433

434
    def deploy_example_guard(self) -> Optional[ChecksumAddress]:
4✔
435
        """
436
        :return: An example DebugTransactionGuard (from safe contracts v1.4.1) supporting IERC165
437
        """
438

439
        bytecode = "0x608060405234801561001057600080fd5b50610929806100206000396000f3fe608060405234801561001057600080fd5b50600436106100505760003560e01c806301ffc9a71461005357806375f0bb52146100b657806393271368146102be578063ddbdba63146102f857610051565b5b005b61009e6004803603602081101561006957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061033a565b60405180821515815260200191505060405180910390f35b6102bc60048036036101608110156100cd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561011457600080fd5b82018360208201111561012657600080fd5b8035906020019184600183028401116401000000008311171561014857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561021657600080fd5b82018360208201111561022857600080fd5b8035906020019184600183028401116401000000008311171561024a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061040c565b005b6102f6600480360360408110156102d457600080fd5b81019080803590602001909291908035151590602001909291905050506107de565b005b6103246004803603602081101561030e57600080fd5b81019080803590602001909291905050506108db565b6040518082815260200191505060405180910390f35b60007fe6d7a83a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061040557507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600080600033905060018173ffffffffffffffffffffffffffffffffffffffff1663affed0e06040518163ffffffff1660e01b815260040160206040518083038186803b15801561045c57600080fd5b505afa158015610470573d6000803e3d6000fd5b505050506040513d602081101561048657600080fd5b81019080805190602001909291905050500392508073ffffffffffffffffffffffffffffffffffffffff1663d8d11f788f8f8f8f8f8f8f8f8f8d6040518b63ffffffff1660e01b8152600401808b73ffffffffffffffffffffffffffffffffffffffff1681526020018a81526020018060200189600181111561050557fe5b81526020018881526020018781526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182810382528a818151815260200191508051906020019080838360005b83811015610592578082015181840152602081019050610577565b50505050905090810190601f1680156105bf5780820380516001836020036101000a031916815260200191505b509b50505050505050505050505060206040518083038186803b1580156105e557600080fd5b505afa1580156105f9573d6000803e3d6000fd5b505050506040513d602081101561060f57600080fd5b8101908080519060200190929190505050915050803373ffffffffffffffffffffffffffffffffffffffff167fa65fef32cd19a6639a4bf7a6d196f132c151e4f0bbd2706f7f831b3a778e1ac08f8f8f8f8f60008f118a8d8d604051808a73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018060200188600181111561069e57fe5b81526020018781526020018615158152602001858152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528a818151815260200191508051906020019080838360005b8381101561070f5780820151818401526020810190506106f4565b50505050905090810190601f16801561073c5780820380516001836020036101000a031916815260200191505b50838103825285818151815260200191508051906020019080838360005b8381101561077557808201518184015260208101905061075a565b50505050905090810190601f1680156107a25780820380516001836020036101000a031916815260200191505b509b50505050505050505050505060405180910390a3816000808381526020019081526020016000208190555050505050505050505050505050565b6000806000848152602001908152602001600020549050600081141561086c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f436f756c64206e6f7420676574206e6f6e63650000000000000000000000000081525060200191505060405180910390fd5b60008060008581526020019081526020016000208190555080833373ffffffffffffffffffffffffffffffffffffffff167f0dcc0fb56a30b6fe6b188f45b47369bc7f3c928a9748e245a79fc3f54ddd05688560405180821515815260200191505060405180910390a4505050565b6000602052806000526040600020600091509050548156fea26469706673582212206b4220320ac3fc43010ac2089f4931c4c383ca9873db22b0040a28af93142dd864736f6c63430007060033"
4✔
440
        guard_contract = self.w3.eth.contract(abi=[], bytecode=bytecode)
4✔
441
        tx_hash = guard_contract.constructor().transact(
4✔
442
            {"from": self.w3.eth.accounts[0]}
443
        )
444
        tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
4✔
445
        assert tx_receipt["status"] == 1, "Problem deploying example guard"
4✔
446
        return tx_receipt["contractAddress"]
4✔
447

448
    def deploy_sign_message_lib(self) -> Optional[ChecksumAddress]:
4✔
449
        """
450
        Deploy sign message lib
451

452
        :return: Deployed address
453
        """
454
        contract = get_sign_message_lib_contract(self.ethereum_client.w3)
4✔
455
        tx_hash = contract.constructor().transact({"from": self.w3.eth.accounts[0]})
4✔
456
        tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
4✔
457
        assert tx_receipt["status"] == 1, "Problem deploying sign message lib"
4✔
458
        return tx_receipt["contractAddress"]
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc