예제 #1
0
    def _deposit_preconditions(
        self,
        total_deposit: TokenAmount,
        beneficiary: Address,
        token: Token,
        block_identifier: BlockSpecification,
    ) -> Tuple[TokenAmount, Dict]:
        if not isinstance(total_deposit, int):
            raise ValueError('total_deposit needs to be an integer number.')

        previous_total_deposit = self.get_total_deposit(
            address=beneficiary,
            block_identifier=block_identifier,
        )
        amount_to_deposit = total_deposit - previous_total_deposit

        log_details = {
            'user_deposit_address': pex(self.address),
            'node': pex(self.node_address),
            'beneficiary': pex(beneficiary),
            'new_total_deposit': total_deposit,
            'previous_total_deposit': previous_total_deposit,
        }

        if total_deposit <= previous_total_deposit:
            msg = (
                f'Current total deposit {previous_total_deposit} is already larger '
                f'than the requested total deposit amount {total_deposit}')
            log.info('deposit failed', reason=msg, **log_details)
            raise DepositMismatch(msg)

        current_balance = token.balance_of(
            address=self.node_address,
            block_identifier=block_identifier,
        )
        if current_balance < amount_to_deposit:
            msg = (
                f'new_total_deposit - previous_total_deposit =  {amount_to_deposit} can not '
                f'be larger than the available balance {current_balance}, '
                f'for token at address {pex(token.address)}')
            log.info('deposit failed', reason=msg, **log_details)
            raise DepositMismatch(msg)

        token.approve(
            allowed_address=Address(self.address),
            allowance=amount_to_deposit,
        )

        return amount_to_deposit, log_details
예제 #2
0
    def _deposit_preconditions(
        self,
        total_deposit: TokenAmount,
        beneficiary: Address,
        token: Token,
        block_identifier: BlockSpecification,
    ) -> Tuple[TokenAmount, Dict]:
        if not isinstance(total_deposit, int):
            raise ValueError("total_deposit needs to be an integer number.")

        previous_total_deposit = self.get_total_deposit(
            address=beneficiary, block_identifier=block_identifier
        )
        amount_to_deposit = TokenAmount(total_deposit - previous_total_deposit)

        log_details = {
            "user_deposit_address": pex(self.address),
            "node": pex(self.node_address),
            "beneficiary": pex(beneficiary),
            "new_total_deposit": total_deposit,
            "previous_total_deposit": previous_total_deposit,
        }

        if total_deposit <= previous_total_deposit:
            msg = (
                f"Current total deposit {previous_total_deposit} is already larger "
                f"than the requested total deposit amount {total_deposit}"
            )
            log.info("deposit failed", reason=msg, **log_details)
            raise DepositMismatch(msg)

        current_balance = token.balance_of(
            address=self.node_address, block_identifier=block_identifier
        )
        if current_balance < amount_to_deposit:
            msg = (
                f"new_total_deposit - previous_total_deposit =  {amount_to_deposit} can not "
                f"be larger than the available balance {current_balance}, "
                f"for token at address {pex(token.address)}"
            )
            log.info("deposit failed", reason=msg, **log_details)
            raise DepositMismatch(msg)

        token.approve(allowed_address=Address(self.address), allowance=amount_to_deposit)

        return amount_to_deposit, log_details
예제 #3
0
    def _deposit(
        self,
        beneficiary: Address,
        token: Token,
        total_deposit: TokenAmount,
        amount_to_deposit: TokenAmount,
        log_details: Dict[str, Any],
    ) -> None:
        token.approve(allowed_address=Address(self.address),
                      allowance=amount_to_deposit)

        checking_block = self.client.get_checking_block()
        gas_limit = self.proxy.estimate_gas(checking_block, "deposit",
                                            to_checksum_address(beneficiary),
                                            total_deposit)

        if not gas_limit:
            failed_at = self.proxy.rpc_client.get_block("latest")
            failed_at_blocknumber = failed_at["number"]

            self.proxy.rpc_client.check_for_insufficient_eth(
                transaction_name="deposit",
                transaction_executed=False,
                required_gas=self.gas_measurements["UserDeposit.deposit"],
                block_identifier=failed_at_blocknumber,
            )

            latest_deposit = self.get_total_deposit(
                address=self.node_address,
                block_identifier=failed_at_blocknumber)
            amount_to_deposit = TokenAmount(total_deposit - latest_deposit)

            allowance = token.allowance(
                owner=self.node_address,
                spender=Address(self.address),
                block_identifier=failed_at_blocknumber,
            )
            whole_balance = self.whole_balance(
                block_identifier=failed_at_blocknumber)
            whole_balance_limit = self.whole_balance_limit(
                block_identifier=failed_at_blocknumber)

            if allowance < amount_to_deposit:
                msg = (
                    "The allowance is insufficient. Check concurrent deposits "
                    "for the same user deposit but different proxies.")
                raise RaidenRecoverableError(msg)

            if token.balance_of(self.node_address,
                                failed_at_blocknumber) < amount_to_deposit:
                msg = "The address doesnt have enough tokens"
                raise RaidenRecoverableError(msg)

            if latest_deposit < total_deposit:
                msg = "Deposit amount did not increase after deposit transaction"
                raise RaidenRecoverableError(msg)

            if whole_balance + amount_to_deposit > UINT256_MAX:
                msg = (
                    f"Current whole balance is {whole_balance}. "
                    f"The new deposit of {amount_to_deposit} would lead to an overflow."
                )
                raise RaidenRecoverableError(msg)

            if whole_balance + amount_to_deposit > whole_balance_limit:
                msg = (
                    f"Current whole balance is {whole_balance}. "
                    f"With the new deposit of {amount_to_deposit}, the deposit "
                    f"limit of {whole_balance_limit} would be exceeded.")
                raise RaidenRecoverableError(msg)

            raise RaidenRecoverableError("Deposit failed of unknown reason")

        else:
            gas_limit = safe_gas_limit(gas_limit)
            log_details["gas_limit"] = gas_limit

            transaction_hash = self.proxy.transact(
                "deposit", gas_limit, to_checksum_address(beneficiary),
                total_deposit)

            receipt = self.client.poll(transaction_hash)
            failed_receipt = check_transaction_threw(receipt=receipt)

            if failed_receipt:
                failed_at_blocknumber = failed_receipt["blockNumber"]

                latest_deposit = self.get_total_deposit(
                    address=self.node_address,
                    block_identifier=failed_at_blocknumber)
                amount_to_deposit = TokenAmount(total_deposit - latest_deposit)

                allowance = token.allowance(
                    owner=self.node_address,
                    spender=Address(self.address),
                    block_identifier=failed_at_blocknumber,
                )

                whole_balance = self.whole_balance(
                    block_identifier=failed_at_blocknumber)
                whole_balance_limit = self.whole_balance_limit(
                    block_identifier=failed_at_blocknumber)

                if latest_deposit >= total_deposit:
                    msg = "Deposit amount already increased after another transaction"
                    raise RaidenRecoverableError(msg)

                if allowance < amount_to_deposit:
                    msg = (
                        "The allowance is insufficient. Check concurrent deposits "
                        "for the same token network but different proxies.")
                    raise RaidenRecoverableError(msg)

                # Because we acquired the lock for the token, and the gas estimation succeeded,
                # We know that the account had enough balance for the deposit transaction.
                if token.balance_of(self.node_address,
                                    failed_at_blocknumber) < amount_to_deposit:
                    msg = (
                        f"Transaction failed and balance decreased unexpectedly. "
                        f"This could be a bug in Raiden or a mallicious "
                        f"ERC20 Token.")
                    raise RaidenRecoverableError(msg)

                if whole_balance + amount_to_deposit > UINT256_MAX:
                    msg = (
                        f"Current whole balance is {whole_balance}. "
                        f"The new deposit of {amount_to_deposit} caused an overflow."
                    )
                    raise RaidenRecoverableError(msg)

                if whole_balance + amount_to_deposit > whole_balance_limit:
                    msg = (
                        f"Current whole balance is {whole_balance}. "
                        f"With the new deposit of {amount_to_deposit}, the deposit "
                        f"limit of {whole_balance_limit} was exceeded.")
                    raise RaidenRecoverableError(msg)

                if latest_deposit < total_deposit:
                    msg = "Deposit amount did not increase after deposit transaction"
                    raise RaidenRecoverableError(msg)

                raise RaidenRecoverableError(
                    "Deposit failed of unknown reason")
예제 #4
0
def deploy_service_registry_and_set_urls(
        private_keys, web3, contract_manager,
        service_registry_address) -> Tuple[ServiceRegistry, List[str]]:
    urls = ["http://foo", "http://boo", "http://coo"]
    c1_client = JSONRPCClient(web3, private_keys[0])
    c1_service_proxy = ServiceRegistry(
        jsonrpc_client=c1_client,
        service_registry_address=service_registry_address,
        contract_manager=contract_manager,
    )
    token_address = c1_service_proxy.token_address(block_identifier="latest")
    c1_token_proxy = Token(jsonrpc_client=c1_client,
                           token_address=token_address,
                           contract_manager=contract_manager)
    c2_client = JSONRPCClient(web3, private_keys[1])
    c2_service_proxy = ServiceRegistry(
        jsonrpc_client=c2_client,
        service_registry_address=service_registry_address,
        contract_manager=contract_manager,
    )
    c2_token_proxy = Token(jsonrpc_client=c2_client,
                           token_address=token_address,
                           contract_manager=contract_manager)
    c3_client = JSONRPCClient(web3, private_keys[2])
    c3_service_proxy = ServiceRegistry(
        jsonrpc_client=c3_client,
        service_registry_address=service_registry_address,
        contract_manager=contract_manager,
    )
    c3_token_proxy = Token(jsonrpc_client=c3_client,
                           token_address=token_address,
                           contract_manager=contract_manager)

    # Test that getting a random service for an empty registry returns None
    pfs_address = get_random_pfs(c1_service_proxy,
                                 "latest",
                                 pathfinding_max_fee=TokenAmount(1))
    assert pfs_address is None

    # Test that setting the urls works
    c1_price = c1_service_proxy.current_price(block_identifier="latest")
    tx = c1_token_proxy.proxy.transact("mint", 1000000, c1_price)
    receipt = c1_client.poll(tx)
    assert not check_transaction_threw(receipt=receipt)
    assert c1_token_proxy.balance_of(c1_client.address) > 0
    c1_token_proxy.approve(allowed_address=service_registry_address,
                           allowance=c1_price)
    c1_service_proxy.deposit(block_identifier="latest", limit_amount=c1_price)
    c1_service_proxy.set_url(urls[0])

    c2_price = c2_service_proxy.current_price(block_identifier="latest")
    tx = c2_token_proxy.proxy.transact("mint", 1000000, c2_price)
    receipt = c2_client.poll(tx)
    assert not check_transaction_threw(receipt=receipt)
    assert c2_token_proxy.balance_of(c2_client.address) > 0
    c2_token_proxy.approve(allowed_address=service_registry_address,
                           allowance=c2_price)
    c2_service_proxy.deposit(block_identifier="latest", limit_amount=c2_price)
    c2_service_proxy.set_url(urls[1])

    c3_price = c3_service_proxy.current_price(block_identifier="latest")
    tx = c3_token_proxy.proxy.transact("mint", 1000000, c3_price)
    receipt = c3_client.poll(tx)
    assert not check_transaction_threw(receipt=receipt)
    assert c3_token_proxy.balance_of(c3_client.address) > 0
    c3_token_proxy.approve(allowed_address=service_registry_address,
                           allowance=c3_price)
    c3_service_proxy.deposit(block_identifier="latest", limit_amount=c3_price)
    c3_token_proxy.proxy.transact("mint", 1000000, c3_price)
    c3_token_proxy.approve(allowed_address=service_registry_address,
                           allowance=c3_price)
    c3_service_proxy.set_url(urls[2])

    return c1_service_proxy, urls
예제 #5
0
    def deposit(self, total_deposit: typing.TokenAmount,
                partner: typing.Address):
        """ Set total token deposit in the channel to total_deposit.

        Raises:
            ChannelBusyError: If the channel is busy with another operation
            RuntimeError: If the token address is empty.
        """
        if not isinstance(total_deposit, int):
            raise ValueError('total_deposit needs to be an integral number.')

        token_address = self.token_address()

        token = Token(
            self.client,
            token_address,
            self.poll_timeout,
        )
        current_balance = token.balance_of(self.node_address)
        current_deposit = self.detail_participant(self.node_address,
                                                  partner)['deposit']
        amount_to_deposit = total_deposit - current_deposit

        if amount_to_deposit <= 0:
            raise ValueError('deposit [{}] must be greater than 0.'.format(
                amount_to_deposit, ))

        if current_balance < amount_to_deposit:
            raise ValueError(
                f'deposit {amount_to_deposit} cant be larger than the '
                f'available balance {current_balance}, '
                f'for token at address {pex(token_address)}', )

        log.info(
            'deposit called',
            token_network=pex(self.address),
            node=pex(self.node_address),
            partner=pex(partner),
            total_deposit=total_deposit,
            amount_to_deposit=amount_to_deposit,
        )
        token.approve(self.address, amount_to_deposit)

        self._check_channel_lock(partner)

        with releasing(self.channel_operations_lock[partner]):
            transaction_hash = self.proxy.transact(
                'setTotalDeposit',
                self.node_address,
                total_deposit,
                partner,
            )

            self.client.poll(
                unhexlify(transaction_hash),
                timeout=self.poll_timeout,
            )

            receipt_or_none = check_transaction_threw(self.client,
                                                      transaction_hash)
            if receipt_or_none:
                log.critical(
                    'deposit failed',
                    token_network=pex(self.address),
                    node=pex(self.node_address),
                    partner=pex(partner),
                    total_deposit=total_deposit,
                )

                channel_opened = self.channel_is_opened(partner)
                if channel_opened is False:
                    raise ChannelIncorrectStateError(
                        'Channel is not in an opened state. A deposit cannot be made',
                    )
                raise TransactionThrew('Deposit', receipt_or_none)

            log.info(
                'deposit successful',
                token_network=pex(self.address),
                node=pex(self.node_address),
                partner=pex(partner),
                total_deposit=total_deposit,
            )