loads the contracts -- starts their event listeners
        :param contract_names:
        :return:

def start(self, contract_names, target):
        '''
        loads the contracts -- starts their event listeners
        :param contract_names:
        :return:
        '''

        if isinstance(contract_names, str):
            contract_names = [contract_names]

        if not isinstance(contract_names, list):
            return None, "error: expecting a string, or a list of contract names"

        contract_listeners = []

        for name in contract_names:
            c, err = Contract.get(name, self)
            if err:
                EZO.log.error(red("error loading contract {}".format(name)))
                EZO.log.error(red(err))
                continue
            if not c:
                EZO.log.warn(blue("contract {} not found".format(name)))
                continue

            address, err = Contract.get_address(name, c.hash, self.db, target=target)

            if err:
                EZO.log.error(red("error obtaining address for contract {}").format(name))
                EZO.log.error(red(err))
                continue
            if not address:
                EZO.log.error(red("no address for contract {}".format(name)))
                continue

            contract_listeners.append(c.listen(address, target))

        if contract_listeners:
            loop = asyncio.get_event_loop()
            loop.run_until_complete(
                asyncio.gather(*contract_listeners)
            )
        else:
            return None, "unable to start contract listeners"