def _deposit_preconditions( self, beneficiary: Address, total_deposit: TokenAmount, given_block_identifier: BlockIdentifier, token: Token, ) -> Tuple[TokenAmount, TokenAmount]: try: previous_total_deposit = self.get_total_deposit( address=beneficiary, block_identifier=given_block_identifier ) current_balance = token.balance_of( address=self.node_address, block_identifier=given_block_identifier ) whole_balance = self.whole_balance(block_identifier=given_block_identifier) whole_balance_limit = self.whole_balance_limit(block_identifier=given_block_identifier) except ValueError: # If 'given_block_identifier' has been pruned, we cannot perform the # precondition checks but must still set the amount_to_deposit to a # reasonable value. previous_total_deposit = self.get_total_deposit( address=beneficiary, block_identifier=self.client.get_checking_block() ) amount_to_deposit = TokenAmount(total_deposit - previous_total_deposit) except BadFunctionCallOutput: raise_on_call_returned_empty(given_block_identifier) else: amount_to_deposit = TokenAmount(total_deposit - previous_total_deposit) 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 BrokenPreconditionError(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 BrokenPreconditionError(msg) 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}" ) raise BrokenPreconditionError(msg) if current_balance < amount_to_deposit: msg = ( f"new_total_deposit - previous_total_deposit = {amount_to_deposit} " f"can not be larger than the available balance {current_balance}, " f"for token at address {to_checksum_address(token.address)}" ) raise BrokenPreconditionError(msg) return previous_total_deposit, amount_to_deposit
def _check_why_deposit_failed( self, token: Token, amount_to_deposit: TokenAmount, total_deposit: TokenAmount, block_identifier: BlockSpecification, ) -> str: msg = "" latest_deposit = self.get_total_deposit( address=self.node_address, block_identifier=block_identifier) allowance = token.allowance( owner=self.node_address, spender=Address(self.address), block_identifier=block_identifier, ) if allowance < amount_to_deposit: msg = ("The allowance is insufficient. Check concurrent deposits " "for the same token network but different proxies.") elif token.balance_of(self.node_address, block_identifier) < amount_to_deposit: msg = "The address doesnt have enough tokens" elif latest_deposit < total_deposit: msg = "Deposit amount did not increase after deposit transaction" else: msg = "Deposit failed of unknown reason" return msg
def _check_why_deposit_failed( self, token: Token, amount_to_deposit: TokenAmount, total_deposit: TokenAmount, block_identifier: BlockSpecification, ) -> Tuple[Union[RaidenRecoverableError, RaidenUnrecoverableError], str, ]: error_type = RaidenUnrecoverableError msg = '' latest_deposit = self.get_total_deposit( address=self.node_address, block_identifier=block_identifier, ) allowance = token.allowance( owner=self.node_address, spender=Address(self.address), block_identifier=block_identifier, ) if allowance < amount_to_deposit: msg = ('The allowance is insufficient. Check concurrent deposits ' 'for the same token network but different proxies.') elif token.balance_of(self.node_address, block_identifier) < amount_to_deposit: msg = 'The address doesnt have enough tokens' elif latest_deposit < total_deposit: msg = 'Deposit amount did not increase after deposit transaction' else: msg = 'Deposit failed of unknown reason' return error_type, msg
def _withdraw_check_result( self, transaction_sent: Optional[TransactionSent], amount_to_withdraw: TokenAmount, token: Token, previous_token_balance: TokenAmount, ) -> None: if transaction_sent is None: failed_at = self.client.get_block(BLOCK_ID_LATEST) failed_at_blocknumber = failed_at["number"] self.client.check_for_insufficient_eth( transaction_name="withdraw", transaction_executed=False, required_gas=self.gas_measurements["UserDeposit.withdraw"], block_identifier=failed_at_blocknumber, ) raise RaidenRecoverableError( "Withdraw transaction failed to be sent for an unknown reason." ) transaction_mined = self.client.poll_transaction(transaction_sent) if not was_transaction_successfully_mined(transaction_mined): failed_at_blocknumber = BlockNumber(transaction_mined.receipt["blockNumber"]) withdraw_plan = self.get_withdraw_plan( withdrawer_address=self.node_address, block_identifier=failed_at_blocknumber ) whole_balance = self.whole_balance(block_identifier=failed_at_blocknumber) if amount_to_withdraw > withdraw_plan.withdraw_amount: raise RaidenRecoverableError( f"Couldn't withdraw {amount_to_withdraw}, " f"current withdraw plan only allows for {withdraw_plan.withdraw_amount}." ) if withdraw_plan.withdraw_block > failed_at_blocknumber: raise RaidenRecoverableError( f"Couldn't withdraw at block {failed_at_blocknumber}. " f"The current withdraw plan requires block number " f"{withdraw_plan.withdraw_block}." ) if whole_balance - amount_to_withdraw < 0: raise RaidenRecoverableError( f"The current whole balance is {whole_balance}. " f"The withdraw of {amount_to_withdraw} would have lead to an underflow." ) current_token_balance = TokenAmount( token.balance_of(self.node_address, block_identifier=failed_at_blocknumber) ) # FIXME: This seems fishy. The token balance could have an unexpected value for # unrelated reasons (e.g. concurrent token transfers via transferFrom). if current_token_balance != previous_token_balance + amount_to_withdraw: raise RaidenRecoverableError("Token transfer during withdraw failed.") raise RaidenRecoverableError("Withdraw failed for an unknown reason.")
def deposit(self, amount): """ Deposit amount token in the channel. Raises: AddressWithoutCode: If the channel was settled prior to the call. RuntimeError: If the netting channel token address is empty. """ if not isinstance(amount, (int, long)): raise ValueError('amount needs to be an integral number.') token_address = self.token_address() token = Token( self.client, token_address, self.startgas, self.gasprice, self.poll_timeout, ) current_balance = token.balance_of(self.node_address) if current_balance < amount: raise ValueError( 'deposit [{}] cant be larger than the available balance [{}].'. format( amount, current_balance, )) if log.isEnabledFor(logging.INFO): log.info('deposit called', contract=pex(self.address), amount=amount) transaction_hash = estimate_and_transact( self.proxy, 'deposit', self.startgas, self.gasprice, amount, ) 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', contract=pex(self.address)) self._check_exists() raise TransactionThrew('Deposit', receipt_or_none) if log.isEnabledFor(logging.INFO): log.info('deposit sucessfull', contract=pex(self.address), amount=amount)
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
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
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")
def test_payment_channel_proxy_basics( token_network_registry_address: TokenNetworkRegistryAddress, token_network_proxy: TokenNetwork, token_proxy: Token, chain_id: ChainID, private_keys: List[PrivateKey], web3: Web3, contract_manager: ContractManager, reveal_timeout: BlockTimeout, ) -> None: token_network_address = token_network_proxy.address partner = privatekey_to_address(private_keys[0]) rpc_client = JSONRPCClient(web3, private_keys[1]) proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_proxy = proxy_manager.token_network( address=token_network_address, block_identifier=BLOCK_ID_LATEST ) start_block = web3.eth.blockNumber channel_details = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier=BLOCK_ID_LATEST, ) channel_identifier = channel_details.channel_identifier assert channel_identifier is not None channel_state = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=channel_identifier, ), token_address=token_network_proxy.token_address(), token_network_registry_address=token_network_registry_address, reveal_timeout=reveal_timeout, settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN), fee_schedule=FeeScheduleState(), our_state=NettingChannelEndState( address=token_network_proxy.client.address, contract_balance=Balance(0) ), partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)), open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)), ) channel_proxy_1 = proxy_manager.payment_channel( channel_state=channel_state, block_identifier=BLOCK_ID_LATEST ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_1.opened(BLOCK_ID_LATEST) is True # Test deposit initial_token_balance = 100 token_proxy.transfer(rpc_client.address, TokenAmount(initial_token_balance)) assert token_proxy.balance_of(rpc_client.address) == initial_token_balance assert token_proxy.balance_of(partner) == 0 channel_proxy_1.approve_and_set_total_deposit( total_deposit=TokenAmount(10), block_identifier=BLOCK_ID_LATEST ) # ChannelOpened, ChannelNewDeposit channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 2 block_before_close = web3.eth.blockNumber empty_balance_proof = BalanceProof( channel_identifier=channel_proxy_1.channel_identifier, token_network_address=token_network_address, balance_hash=EMPTY_BALANCE_HASH, nonce=0, chain_id=chain_id, transferred_amount=TokenAmount(0), ) closing_data = ( empty_balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE ) channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=BLOCK_ID_LATEST, ) assert channel_proxy_1.closed(BLOCK_ID_LATEST) is True # ChannelOpened, ChannelNewDeposit, ChannelClosed channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 3 # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer -- we need to wait on +1 since we use the latest block on parity for # estimate gas and at the time the latest block is the settle timeout block. # More info: https://github.com/raiden-network/raiden/pull/3699#discussion_r270477227 rpc_client.wait_until_block( target_block_number=BlockNumber(rpc_client.block_number() + TEST_SETTLE_TIMEOUT_MIN + 1) ) transaction_hash = channel_proxy_1.settle( transferred_amount=TokenAmount(0), locked_amount=LockedAmount(0), locksroot=LOCKSROOT_OF_NO_LOCKS, partner_transferred_amount=TokenAmount(0), partner_locked_amount=LockedAmount(0), partner_locksroot=LOCKSROOT_OF_NO_LOCKS, block_identifier=BLOCK_ID_LATEST, ) assert is_tx_hash_bytes(transaction_hash) assert channel_proxy_1.settled(BLOCK_ID_LATEST) is True # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 4 channel_details = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier=BLOCK_ID_LATEST, ) new_channel_identifier = channel_details.channel_identifier assert new_channel_identifier is not None channel_state = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=new_channel_identifier, ), token_address=token_network_proxy.token_address(), token_network_registry_address=token_network_registry_address, reveal_timeout=reveal_timeout, settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN), fee_schedule=FeeScheduleState(), our_state=NettingChannelEndState( address=token_network_proxy.client.address, contract_balance=Balance(0) ), partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)), open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)), ) channel_proxy_2 = proxy_manager.payment_channel( channel_state=channel_state, block_identifier=BLOCK_ID_LATEST ) assert channel_proxy_2.channel_identifier == new_channel_identifier assert channel_proxy_2.opened(BLOCK_ID_LATEST) is True msg = "The channel was already closed, the second call must fail" with pytest.raises(RaidenRecoverableError): channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=block_before_close, ) pytest.fail(msg) msg = "The channel is not open at latest, this must raise" with pytest.raises(RaidenUnrecoverableError): channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=BLOCK_ID_LATEST, ) pytest.fail(msg) msg = ( "The channel was not opened at the provided block (latest). " "This call should never have been attempted." ) with pytest.raises(BrokenPreconditionError): channel_proxy_1.approve_and_set_total_deposit( total_deposit=TokenAmount(20), block_identifier=BLOCK_ID_LATEST ) pytest.fail(msg)
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, ) 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, )
def _deposit_check_result( self, transaction_sent: Optional[TransactionSent], token: Token, beneficiary: Address, total_deposit: TokenAmount, amount_to_deposit: TokenAmount, ) -> None: if transaction_sent is None: failed_at = self.client.get_block(BLOCK_ID_LATEST) failed_at_blocknumber = failed_at["number"] self.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=beneficiary, 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: transaction_mined = self.client.poll_transaction(transaction_sent) if not was_transaction_successfully_mined(transaction_mined): failed_at_blocknumber = BlockNumber(transaction_mined.receipt["blockNumber"]) latest_deposit = self.get_total_deposit( address=beneficiary, 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 = ( "Transaction failed and balance decreased unexpectedly. " "This could be a bug in Raiden or a mallicious " "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")
def deposit(self, amount): """ Deposit amount token in the channel. Raises: AddressWithoutCode: If the channel was settled prior to the call. ChannelBusyError: If the channel is busy with another operation RuntimeError: If the netting channel token address is empty. """ if not isinstance(amount, int): raise ValueError('amount 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) if current_balance < amount: raise ValueError('deposit [{}] cant be larger than the available balance [{}].'.format( amount, current_balance, )) log.info( 'deposit called', node=pex(self.node_address), contract=pex(self.address), amount=amount, ) if not self.channel_operations_lock.acquire(blocking=False): raise ChannelBusyError( f'Channel with address {self.address} is ' f'busy with another ongoing operation.' ) with releasing(self.channel_operations_lock): transaction_hash = estimate_and_transact( self.proxy, 'deposit', amount, ) 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', node=pex(self.node_address), contract=pex(self.address), ) self._check_exists() raise TransactionThrew('Deposit', receipt_or_none) log.info( 'deposit successful', node=pex(self.node_address), contract=pex(self.address), amount=amount, )
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