Exemplo n.º 1
0
    def setUpTestData(cls):
        super().setUpTestData()

        for key, value in contract_addresses.items():
            if callable(value):
                contract_addresses[key] = value(cls.ethereum_client, cls.ethereum_test_account).contract_address

        settings.SAFE_CONTRACT_ADDRESS = contract_addresses['safe']
        settings.SAFE_MULTISEND_ADDRESS = contract_addresses['multi_send']
        settings.SAFE_V1_0_0_CONTRACT_ADDRESS = contract_addresses['safe_V1_0_0']
        settings.SAFE_V0_0_1_CONTRACT_ADDRESS = contract_addresses['safe_V0_0_1']
        settings.SAFE_PROXY_FACTORY_ADDRESS = contract_addresses['proxy_factory']
        settings.SAFE_PROXY_FACTORY_V1_0_0_ADDRESS = contract_addresses['proxy_factory_V1_0_0']
        settings.SAFE_VALID_CONTRACT_ADDRESSES = {settings.SAFE_CONTRACT_ADDRESS,
                                                  settings.SAFE_V1_0_0_CONTRACT_ADDRESS,
                                                  settings.SAFE_V0_0_1_CONTRACT_ADDRESS,
                                                  }
        cls.safe_contract_address = contract_addresses['safe']
        cls.safe_contract = get_safe_contract(cls.w3, cls.safe_contract_address)
        cls.safe_contract_V1_0_0_address = contract_addresses['safe_V1_0_0']
        cls.safe_contract_V1_0_0 = get_safe_V1_0_0_contract(cls.w3, cls.safe_contract_V1_0_0_address)
        cls.safe_contract_V0_0_1_address = contract_addresses['safe_V0_0_1']
        cls.safe_contract_V0_0_1 = get_safe_V1_0_0_contract(cls.w3, cls.safe_contract_V0_0_1_address)
        cls.proxy_factory_contract_address = contract_addresses['proxy_factory']
        cls.proxy_factory_contract = get_proxy_factory_contract(cls.w3, cls.proxy_factory_contract_address)
        cls.proxy_factory = ProxyFactory(cls.proxy_factory_contract_address, cls.ethereum_client)
        cls.multi_send_contract = get_multi_send_contract(cls.w3, contract_addresses['multi_send'])
        cls.multi_send = MultiSend(cls.multi_send_contract.address, cls.ethereum_client)
Exemplo n.º 2
0
    def setUpClass(cls):
        super().setUpClass()

        for key, value in _contract_addresses.items():
            if callable(value):
                _contract_addresses[key] = value(
                    cls.ethereum_client,
                    cls.ethereum_test_account).contract_address

        settings.SAFE_DEFAULT_CALLBACK_HANDLER = _contract_addresses[
            "compatibility_fallback_handler"]
        settings.SAFE_MULTISEND_ADDRESS = _contract_addresses["multi_send"]
        settings.SAFE_CONTRACT_ADDRESS = _contract_addresses["safe_v1_3_0"]
        settings.SAFE_V1_1_1_CONTRACT_ADDRESS = _contract_addresses[
            "safe_V1_1_1"]
        settings.SAFE_V1_0_0_CONTRACT_ADDRESS = _contract_addresses[
            "safe_V1_0_0"]
        settings.SAFE_V0_0_1_CONTRACT_ADDRESS = _contract_addresses[
            "safe_V0_0_1"]
        settings.SAFE_PROXY_FACTORY_ADDRESS = _contract_addresses[
            "proxy_factory"]
        settings.SAFE_PROXY_FACTORY_V1_0_0_ADDRESS = _contract_addresses[
            "proxy_factory_V1_0_0"]
        settings.SAFE_VALID_CONTRACT_ADDRESSES = {
            settings.SAFE_CONTRACT_ADDRESS,
            settings.SAFE_V1_1_1_CONTRACT_ADDRESS,
            settings.SAFE_V1_0_0_CONTRACT_ADDRESS,
            settings.SAFE_V0_0_1_CONTRACT_ADDRESS,
        }
        cls.compatibility_fallback_handler = (
            get_compatibility_fallback_handler_V1_3_0_contract(
                cls.w3, _contract_addresses["compatibility_fallback_handler"]))
        cls.safe_contract_address = _contract_addresses["safe_v1_3_0"]
        cls.safe_contract = get_safe_V1_3_0_contract(cls.w3,
                                                     cls.safe_contract_address)
        cls.safe_contract_V1_1_1_address = _contract_addresses["safe_V1_1_1"]
        cls.safe_contract_V1_1_1 = get_safe_V1_1_1_contract(
            cls.w3, cls.safe_contract_V1_1_1_address)
        cls.safe_contract_V1_0_0_address = _contract_addresses["safe_V1_0_0"]
        cls.safe_contract_V1_0_0 = get_safe_V1_0_0_contract(
            cls.w3, cls.safe_contract_V1_0_0_address)
        cls.safe_contract_V0_0_1_address = _contract_addresses["safe_V0_0_1"]
        cls.safe_contract_V0_0_1 = get_safe_V1_0_0_contract(
            cls.w3, cls.safe_contract_V0_0_1_address)
        cls.proxy_factory_contract_address = _contract_addresses[
            "proxy_factory"]
        cls.proxy_factory_contract = get_proxy_factory_contract(
            cls.w3, cls.proxy_factory_contract_address)
        cls.proxy_factory = ProxyFactory(cls.proxy_factory_contract_address,
                                         cls.ethereum_client)
        cls.multi_send_contract = get_multi_send_contract(
            cls.w3, _contract_addresses["multi_send"])
        cls.multi_send = MultiSend(cls.multi_send_contract.address,
                                   cls.ethereum_client)
Exemplo n.º 3
0
    def retrieve_modules(self, pagination: Optional[int] = 10,
                         block_identifier: Optional[BlockIdentifier] = 'latest') -> List[str]:
        """
        :param pagination: Number of modules to get per request
        :param block_identifier:
        :return: List of module addresses
        """
        try:
            # Contracts with Safe version < 1.1.0 were not paginated
            contract = get_safe_V1_0_0_contract(self.ethereum_client.w3, address=self.address)
            return contract.functions.getModules().call(block_identifier=block_identifier)
        except BadFunctionCallOutput:
            pass

        contract = self.get_contract()
        address = SENTINEL_ADDRESS
        all_modules: List[str] = []
        while True:
            (modules,
             address) = contract.functions.getModulesPaginated(address,
                                                               pagination).call(block_identifier=block_identifier)

            all_modules.extend(modules)
            if address == SENTINEL_ADDRESS:
                break
            else:
                all_modules.append(address)
        return all_modules
Exemplo n.º 4
0
    def deploy_master_contract_v1_0_0(ethereum_client: EthereumClient, deployer_account: LocalAccount) -> EthereumTxSent:
        """
        Deploy master contract. Takes deployer_account (if unlocked in the node) or the deployer private key
        :param ethereum_client:
        :param deployer_account: Ethereum account
        :return: deployed contract address
        """

        safe_contract = get_safe_V1_0_0_contract(ethereum_client.w3)
        constructor_data = safe_contract.constructor().buildTransaction({'gas': 0})['data']
        initializer_data = safe_contract.functions.setup(
            # We use 2 owners that nobody controls for the master copy
            ["0x0000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000003"],
            2,  # Threshold. Maximum security
            NULL_ADDRESS,  # Address for optional DELEGATE CALL
            b'',  # Data for optional DELEGATE CALL
            NULL_ADDRESS,  # Payment token
            0,  # Payment
            NULL_ADDRESS  # Refund receiver
        ).buildTransaction({'to': NULL_ADDRESS})['data']

        ethereum_tx_sent = ethereum_client.deploy_and_initialize_contract(deployer_account, constructor_data,
                                                                          HexBytes(initializer_data))
        logger.info("Deployed and initialized Safe Master Contract=%s by %s", ethereum_tx_sent.contract_address,
                    deployer_account.address)
        return ethereum_tx_sent
Exemplo n.º 5
0
    def __init__(self, w3: Web3, master_copy_address: str,
                 proxy_factory_address: str):
        """
        Init builder for safe creation using create2
        :param w3: Web3 instance
        :param master_copy_address: `Gnosis Safe` master copy address
        :param proxy_factory_address: `Gnosis Proxy Factory` address
        """
        assert Web3.isChecksumAddress(master_copy_address)
        assert Web3.isChecksumAddress(proxy_factory_address)

        self.w3 = w3
        self.master_copy_address = master_copy_address
        self.proxy_factory_address = proxy_factory_address
        self.safe_version = get_safe_contract(
            w3, master_copy_address).functions.VERSION().call()
        if self.safe_version == '1.1.1':
            self.master_copy_contract = get_safe_contract(
                w3, master_copy_address)
        elif self.safe_version == '1.0.0':
            self.master_copy_contract = get_safe_V1_0_0_contract(
                w3, master_copy_address)
        else:
            raise ValueError('Safe version must be 1.1.1 or 1.0.0')
        self.proxy_factory_contract = get_proxy_factory_contract(
            w3, proxy_factory_address)
    def __init__(self, ethereum_client: EthereumClient):
        # This safe_tx_failure events allow us to detect a failed safe transaction
        self.ethereum_client = ethereum_client
        dummy_w3 = Web3()
        self.safe_tx_failure_events = [
            get_safe_V1_0_0_contract(dummy_w3).events.ExecutionFailed(),
            get_safe_V1_3_0_contract(dummy_w3).events.ExecutionFailure(),
        ]
        self.safe_tx_module_failure_events = [
            get_safe_V1_3_0_contract(
                dummy_w3).events.ExecutionFromModuleFailure()
        ]

        self.safe_tx_failure_events_topics = {
            event_abi_to_log_topic(event.abi)
            for event in self.safe_tx_failure_events
        }
        self.safe_tx_module_failure_topics = {
            event_abi_to_log_topic(event.abi)
            for event in self.safe_tx_module_failure_events
        }
        self.safe_last_status_cache: Dict[str, SafeStatus] = {}
        self.signature_breaking_versions = (  # Versions where signing changed
            Version("1.0.0"),  # Safes >= 1.0.0 Renamed `baseGas` to `dataGas`
            Version("1.3.0"),  # ChainId was included
        )
    def __init__(self):
        #TODO  Refactor this using inheritance
        self.dummy_w3 = Web3()
        exchanges = [
            get_uniswap_exchange_contract(self.dummy_w3),
            self.dummy_w3.eth.contract(abi=gnosis_protocol_abi)
        ]
        sight_contracts = [
            self.dummy_w3.eth.contract(abi=abi)
            for abi in (conditional_token_abi, market_maker_abi,
                        market_maker_factory_abi)
        ]
        erc_contracts = [
            get_erc721_contract(self.dummy_w3),
            get_erc20_contract(self.dummy_w3)
        ]
        safe_contracts = [
            get_safe_V0_0_1_contract(self.dummy_w3),
            get_safe_V1_0_0_contract(self.dummy_w3),
            get_safe_contract(self.dummy_w3)
        ]

        # Order is important. If signature is the same (e.g. renaming of `baseGas`) last elements in the list
        # will take preference
        self.supported_contracts = exchanges + sight_contracts + erc_contracts + safe_contracts

        # Web3 generates possible selectors every time. We cache that and use a dict to do a fast check
        # Store selectors with abi
        self.supported_fn_selectors: Dict[bytes, ContractFunction] = {}
        for supported_contract in self.supported_contracts:
            self.supported_fn_selectors.update(
                self._generate_selectors_with_abis_from_contract(
                    supported_contract))
 def __init__(self):
     # This safe_tx_failure events allow us to detect a failed safe transaction
     self.safe_tx_failure_events = [get_safe_V1_0_0_contract(Web3()).events.ExecutionFailed(),
                                    get_safe_contract(Web3()).events.ExecutionFailure()]
     self.safe_tx_failure_events_topics = {event_abi_to_log_topic(event.abi) for event
                                           in self.safe_tx_failure_events}
     self.safe_status_cache: Dict[str, SafeStatus] = {}
Exemplo n.º 9
0
    def __init__(self):
        self.dummy_w3 = Web3()
        self.safe_contracts = [get_safe_V0_0_1_contract(self.dummy_w3), get_safe_V1_0_0_contract(self.dummy_w3),
                               get_safe_contract(self.dummy_w3)]

        # Order is important. If signature is the same (e.g. renaming of `baseGas`) last elements in the list
        # will take preference
        self.supported_contracts = self.safe_contracts
    def get_supported_abis(self) -> List[ABI]:
        safe_abis = [get_safe_V0_0_1_contract(self.dummy_w3).abi,
                     get_safe_V1_0_0_contract(self.dummy_w3).abi,
                     get_safe_V1_3_0_contract(self.dummy_w3).abi,
                     get_safe_contract(self.dummy_w3).abi]

        # Order is important. If signature is the same (e.g. renaming of `baseGas`) last elements in the list
        # will take preference
        return safe_abis
Exemplo n.º 11
0
    def __init__(self):
        self.dummy_w3 = Web3()
        # Order is important. If signature is the same (e.g. renaming of `baseGas`) last elements in the list
        # will take preference
        self.supported_contracts = [get_safe_V0_0_1_contract(self.dummy_w3),
                                    get_safe_V1_0_0_contract(self.dummy_w3),
                                    get_safe_contract(self.dummy_w3)]

        # Web3 generates possible selectors every time. We cache that and use a dict to do a fast check
        # Store selectors with abi
        self.supported_fn_selectors: Dict[bytes, ContractFunction] = {}
        for supported_contract in self.supported_contracts:
            self.supported_fn_selectors.update(self._generate_selectors_with_abis_from_contract(supported_contract))
Exemplo n.º 12
0
    def __init__(self, ethereum_client: EthereumClient):
        # This safe_tx_failure events allow us to detect a failed safe transaction
        self.ethereum_client = ethereum_client
        dummy_w3 = Web3()
        self.safe_tx_failure_events = [
            get_safe_V1_0_0_contract(dummy_w3).events.ExecutionFailed(),
            get_safe_contract(dummy_w3).events.ExecutionFailure()
        ]
        self.safe_tx_module_failure_events = [
            get_safe_contract(dummy_w3).events.ExecutionFromModuleFailure()
        ]

        self.safe_tx_failure_events_topics = {
            event_abi_to_log_topic(event.abi)
            for event in self.safe_tx_failure_events
        }
        self.safe_tx_module_failure_topics = {
            event_abi_to_log_topic(event.abi)
            for event in self.safe_tx_module_failure_events
        }
        self.safe_status_cache: Dict[str, SafeStatus] = {}
Exemplo n.º 13
0
    def test_safe_create2_tx_builder_v_1_0_0(self):
        w3 = self.w3
        tx_hash = get_safe_V1_0_0_contract(self.w3).constructor().transact(
            {'from': self.ethereum_test_account.address})
        tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
        master_copy = tx_receipt['contractAddress']

        salt_nonce = generate_salt_nonce()
        funder_account = self.ethereum_test_account
        owners = [Account.create().address for _ in range(4)]
        threshold = len(owners) - 1
        gas_price = self.gas_price

        safe_creation_tx = SafeCreate2TxBuilder(
            w3=w3,
            master_copy_address=master_copy,
            proxy_factory_address=self.proxy_factory_contract_address).build(
                owners=owners,
                threshold=threshold,
                salt_nonce=salt_nonce,
                gas_price=gas_price)

        self.assertEqual(safe_creation_tx.payment,
                         safe_creation_tx.payment_ether)
        self.send_tx(
            {
                'to': safe_creation_tx.safe_address,
                'value': safe_creation_tx.payment,
            }, funder_account)

        funder_balance = self.ethereum_client.get_balance(
            funder_account.address)
        ethereum_tx_sent = self.proxy_factory.deploy_proxy_contract_with_nonce(
            funder_account, master_copy, safe_creation_tx.safe_setup_data,
            salt_nonce, safe_creation_tx.gas, safe_creation_tx.gas_price)
        tx_receipt = w3.eth.wait_for_transaction_receipt(
            ethereum_tx_sent.tx_hash)
        self.assertEqual(tx_receipt.status, 1)

        # Funder balance must be bigger after a Safe deployment, as Safe deployment is a little overpriced
        self.assertGreater(
            self.ethereum_client.get_balance(funder_account.address),
            funder_balance)
        logs = self.proxy_factory_contract.events.ProxyCreation(
        ).processReceipt(tx_receipt)
        log = logs[0]
        self.assertIsNone(tx_receipt.contractAddress)
        self.assertEqual(log['event'], 'ProxyCreation')
        proxy_address = log['args']['proxy']
        self.assertEqual(proxy_address, safe_creation_tx.safe_address)
        self.assertEqual(ethereum_tx_sent.contract_address,
                         safe_creation_tx.safe_address)

        deployed_safe_proxy_contract = get_safe_contract(w3, proxy_address)
        self.assertEqual(
            deployed_safe_proxy_contract.functions.VERSION().call(), '1.0.0')
        self.assertEqual(
            deployed_safe_proxy_contract.functions.getThreshold().call(),
            threshold)
        self.assertEqual(
            deployed_safe_proxy_contract.functions.getOwners().call(), owners)
        self.assertEqual(self.ethereum_client.get_balance(proxy_address), 0)