Пример #1
0
    def _add_token(
        self,
        token_address: TokenAddress,
        additional_arguments: Dict,
    ) -> Address:
        if not is_binary_address(token_address):
            raise InvalidAddress('Expected binary address format for token')

        token_proxy = Token(
            jsonrpc_client=self.client,
            token_address=token_address,
            contract_manager=self.contract_manager,
        )

        if token_proxy.total_supply() == '':
            raise InvalidToken(
                'Given token address does not follow the ERC20 standard (missing totalSupply()',
            )

        log_details = {
            'node': pex(self.node_address),
            'token_address': pex(token_address),
            'registry_address': pex(self.address),
        }
        log.debug('createERC20TokenNetwork called', **log_details)

        checking_block = self.client.get_checking_block()
        error_prefix = 'Call to createERC20TokenNetwork will fail'

        kwarguments = {'_token_address': token_address}
        kwarguments.update(additional_arguments)
        gas_limit = self.proxy.estimate_gas(
            checking_block,
            'createERC20TokenNetwork',
            **kwarguments,
        )

        if gas_limit:
            error_prefix = 'Call to createERC20TokenNetwork failed'
            transaction_hash = self.proxy.transact(
                'createERC20TokenNetwork',
                safe_gas_limit(gas_limit,
                               GAS_REQUIRED_FOR_CREATE_ERC20_TOKEN_NETWORK),
                **kwarguments,
            )

            self.client.poll(transaction_hash)
            receipt_or_none = check_transaction_threw(self.client,
                                                      transaction_hash)

        transaction_executed = gas_limit is not None
        if not transaction_executed or receipt_or_none:
            error_type = RaidenUnrecoverableError
            if transaction_executed:
                block = receipt_or_none['blockNumber']
            else:
                block = checking_block

            required_gas = gas_limit if gas_limit else GAS_REQUIRED_FOR_CREATE_ERC20_TOKEN_NETWORK
            self.proxy.jsonrpc_client.check_for_insufficient_eth(
                transaction_name='createERC20TokenNetwork',
                transaction_executed=transaction_executed,
                required_gas=required_gas,
                block_identifier=block,
            )

            msg = ''
            if self.get_token_network(token_address, block):
                msg = 'Token already registered'
                error_type = RaidenRecoverableError

            error_msg = f'{error_prefix}. {msg}'
            if error_type == RaidenRecoverableError:
                log.warning(error_msg, **log_details)
            else:
                log.critical(error_msg, **log_details)
            raise error_type(error_msg)

        token_network_address = self.get_token_network(token_address, 'latest')
        if token_network_address is None:
            msg = 'createERC20TokenNetwork succeeded but token network address is Null'
            log.critical(msg, **log_details)
            raise RuntimeError(msg)

        log.info(
            'createERC20TokenNetwork successful',
            token_network_address=pex(token_network_address),
            **log_details,
        )

        return token_network_address
Пример #2
0
    def add_token(
        self,
        token_address: TokenAddress,
        channel_participant_deposit_limit: TokenAmount,
        token_network_deposit_limit: TokenAmount,
        given_block_identifier: BlockIdentifier,
    ) -> Tuple[TransactionHash, TokenNetworkAddress]:
        """
        Register token of `token_address` with the token network.
        The limits apply for version 0.13.0 and above of raiden-contracts,
        since instantiation also takes the limits as constructor arguments.
        """
        if given_block_identifier == BLOCK_ID_LATEST:
            raise ValueError(
                'Calling a proxy with "latest" is usually wrong because '
                "the result of the precondition check is not precisely predictable."
            )

        if token_address == NULL_ADDRESS_BYTES:
            raise InvalidTokenAddress(
                "The call to register a token at 0x00..00 will fail.")

        if token_network_deposit_limit <= 0:
            raise InvalidTokenNetworkDepositLimit(
                f"Token network deposit limit must be larger than zero, "
                f"{token_network_deposit_limit} given.")

        if channel_participant_deposit_limit <= 0:
            raise InvalidTokenNetworkDepositLimit(
                f"Participant deposit limit must be larger than zero, "
                f"{channel_participant_deposit_limit} given")

        if channel_participant_deposit_limit > token_network_deposit_limit:
            raise InvalidChannelParticipantDepositLimit(
                f"Participant deposit limit must be smaller than the network "
                f"deposit limit, {channel_participant_deposit_limit} is larger "
                f"than {token_network_deposit_limit}.")

        token_proxy = self.proxy_manager.token(token_address,
                                               given_block_identifier)
        try:
            token_supply = token_proxy.total_supply(
                block_identifier=given_block_identifier)
            already_registered = self.get_token_network(
                token_address=token_address,
                block_identifier=given_block_identifier)
            deprecation_executor = self.get_deprecation_executor(
                block_identifier=given_block_identifier)
            settlement_timeout_min = self.settlement_timeout_min(
                block_identifier=given_block_identifier)
            settlement_timeout_max = self.settlement_timeout_max(
                block_identifier=given_block_identifier)
            chain_id = self.get_chain_id(
                block_identifier=given_block_identifier)
            secret_registry_address = self.get_secret_registry_address(
                block_identifier=given_block_identifier)
            max_token_networks = self.get_max_token_networks(
                block_identifier=given_block_identifier)
            token_networks_created = self.get_token_network_created(
                block_identifier=given_block_identifier)
        except ValueError:
            # If `given_block_identifier` has been pruned the checks cannot be performed
            pass
        except BadFunctionCallOutput:
            raise_on_call_returned_empty(given_block_identifier)
        else:
            if token_networks_created >= max_token_networks:
                raise MaxTokenNetworkNumberReached(
                    f"Number of token networks will exceed the maximum of {max_token_networks}"
                )

            if token_supply is None:
                raise InvalidToken("Given token address does not follow the "
                                   "ERC20 standard (missing `totalSupply()`)")
            if already_registered:
                raise BrokenPreconditionError(
                    "The token is already registered in the TokenNetworkRegistry."
                )

            if deprecation_executor == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The deprecation executor property for the TokenNetworkRegistry is invalid."
                )

            if chain_id == 0:
                raise BrokenPreconditionError(
                    "The chain ID property for the TokenNetworkRegistry is invalid."
                )

            if chain_id != self.rpc_client.chain_id:
                raise BrokenPreconditionError(
                    f"The provided chain ID {chain_id} does not match the "
                    f"network Raiden is running on: {self.rpc_client.chain_id}."
                )

            if secret_registry_address == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The secret registry address for the token network is invalid."
                )

            if settlement_timeout_min == 0:
                raise BrokenPreconditionError(
                    "The minimum settlement timeout for the token network "
                    "should be larger than zero.")

            if settlement_timeout_max <= settlement_timeout_min:
                raise BrokenPreconditionError(
                    "The maximum settlement timeout for the token network "
                    "should be larger than the minimum settlement timeout.")

        log_details = {
            "given_block_identifier": format_block_id(given_block_identifier)
        }
        return self._add_token(
            token_address=token_address,
            channel_participant_deposit_limit=channel_participant_deposit_limit,
            token_network_deposit_limit=token_network_deposit_limit,
            log_details=log_details,
        )
Пример #3
0
    def _add_token(self, token_address: TokenAddress,
                   additional_arguments: Dict) -> Address:
        if not is_binary_address(token_address):
            raise InvalidAddress("Expected binary address format for token")

        token_proxy = Token(
            jsonrpc_client=self.client,
            token_address=token_address,
            contract_manager=self.contract_manager,
        )

        if token_proxy.total_supply() == "":
            raise InvalidToken(
                "Given token address does not follow the ERC20 standard (missing totalSupply()"
            )

        log_details = {
            "node": pex(self.node_address),
            "token_address": pex(token_address),
            "registry_address": pex(self.address),
        }
        log.debug("createERC20TokenNetwork called", **log_details)

        checking_block = self.client.get_checking_block()
        error_prefix = "Call to createERC20TokenNetwork will fail"

        kwarguments = {"_token_address": token_address}
        kwarguments.update(additional_arguments)
        gas_limit = self.proxy.estimate_gas(checking_block,
                                            "createERC20TokenNetwork",
                                            **kwarguments)

        if gas_limit:
            error_prefix = "Call to createERC20TokenNetwork failed"
            transaction_hash = self.proxy.transact(
                "createERC20TokenNetwork",
                safe_gas_limit(gas_limit,
                               GAS_REQUIRED_FOR_CREATE_ERC20_TOKEN_NETWORK),
                **kwarguments,
            )

            self.client.poll(transaction_hash)
            receipt_or_none = check_transaction_threw(self.client,
                                                      transaction_hash)

        transaction_executed = gas_limit is not None
        if not transaction_executed or receipt_or_none:
            if transaction_executed:
                block = receipt_or_none["blockNumber"]
            else:
                block = checking_block

            required_gas = gas_limit if gas_limit else GAS_REQUIRED_FOR_CREATE_ERC20_TOKEN_NETWORK
            self.proxy.jsonrpc_client.check_for_insufficient_eth(
                transaction_name="createERC20TokenNetwork",
                transaction_executed=transaction_executed,
                required_gas=required_gas,
                block_identifier=block,
            )

            if self.get_token_network(token_address, block):
                error_msg = f"{error_prefix}. Token already registered"
                log.warning(error_msg, **log_details)
                raise RaidenRecoverableError(error_msg)

            error_msg = f"{error_prefix}"
            log.critical(error_msg, **log_details)
            raise RaidenUnrecoverableError(error_msg)

        token_network_address = self.get_token_network(token_address, "latest")
        if token_network_address is None:
            msg = "createERC20TokenNetwork succeeded but token network address is Null"
            log.critical(msg, **log_details)
            raise RuntimeError(msg)

        log.info(
            "createERC20TokenNetwork successful",
            token_network_address=pex(token_network_address),
            **log_details,
        )

        return token_network_address
Пример #4
0
    def add_token(
        self,
        token_address: TokenAddress,
        channel_participant_deposit_limit: TokenAmount,
        token_network_deposit_limit: TokenAmount,
        block_identifier: BlockSpecification,
    ) -> TokenNetworkAddress:
        """
        Register token of `token_address` with the token network.
        The limits apply for version 0.13.0 and above of raiden-contracts,
        since instantiation also takes the limits as constructor arguments.
        """
        if block_identifier == "latest":
            raise ValueError(
                'Calling a proxy with "latest" is usually wrong because '
                "the result of the precondition check is not precisely predictable."
            )

        if token_address == NULL_ADDRESS_BYTES:
            raise InvalidTokenAddress(
                "The call to register a token at 0x00..00 will fail.")

        if token_network_deposit_limit <= 0:
            raise InvalidTokenNetworkDepositLimit(
                f"Token network deposit limit of {token_network_deposit_limit} is invalid"
            )

        if channel_participant_deposit_limit > token_network_deposit_limit:
            raise InvalidChannelParticipantDepositLimit(
                f"Channel participant deposit limit of "
                f"{channel_participant_deposit_limit} is invalid")

        token_proxy = self.proxy_manager.token(token_address)
        try:
            token_supply = token_proxy.total_supply(
                block_identifier=block_identifier)
            already_registered = self.get_token_network(
                token_address=token_address, block_identifier=block_identifier)
            deprecation_executor = self.get_deprecation_executor(
                block_identifier=block_identifier)
            settlement_timeout_min = self.settlement_timeout_min(
                block_identifier=block_identifier)
            settlement_timeout_max = self.settlement_timeout_max(
                block_identifier=block_identifier)
            chain_id = self.get_chain_id(block_identifier=block_identifier)
            secret_registry_address = self.get_secret_registry_address(
                block_identifier=block_identifier)
            max_token_networks = self.get_max_token_networks(
                block_identifier=block_identifier)
            token_networks_created = self.get_token_network_created(
                block_identifier=block_identifier)
        except ValueError:
            # If `block_identifier` has been pruned the checks cannot be performed
            pass
        except BadFunctionCallOutput:
            raise_on_call_returned_empty(block_identifier)
        else:
            if token_networks_created >= max_token_networks:
                raise BrokenPreconditionError(
                    f"Number of token networks will exceed the max of {max_token_networks}"
                )

            if token_supply == "":
                raise InvalidToken("Given token address does not follow the "
                                   "ERC20 standard (missing `totalSupply()`)")
            if already_registered:
                raise BrokenPreconditionError(
                    "The token is already registered in the TokenNetworkRegistry."
                )

            if deprecation_executor == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The deprecation executor property for the TokenNetworkRegistry is invalid."
                )

            if chain_id == 0:
                raise BrokenPreconditionError(
                    "The chain ID property for the TokenNetworkRegistry is invalid."
                )

            if secret_registry_address == NULL_ADDRESS_BYTES:
                raise BrokenPreconditionError(
                    "The secret registry address for the token network is invalid."
                )

            if settlement_timeout_min == 0:
                raise BrokenPreconditionError(
                    "The minimum settlement timeout for the token network "
                    "should be larger than zero.")

            if settlement_timeout_min == 0:
                raise BrokenPreconditionError(
                    "The minimum settlement timeout for the token network "
                    "should be larger than zero.")

            if settlement_timeout_max <= settlement_timeout_min:
                raise BrokenPreconditionError(
                    "The maximum settlement timeout for the token network "
                    "should be larger than the minimum settlement timeout.")

        log_details = {
            "node": to_checksum_address(self.node_address),
            "contract": to_checksum_address(self.address),
            "token_address": to_checksum_address(token_address),
        }
        with log_transaction(log, "add_token", log_details):
            return self._add_token(
                token_address=token_address,
                channel_participant_deposit_limit=
                channel_participant_deposit_limit,
                token_network_deposit_limit=token_network_deposit_limit,
                log_details=log_details,
            )