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 test_token( deploy_client, token_proxy, private_keys, web3, contract_manager, ): privkey = private_keys[1] address = privatekey_to_address(privkey) address = to_canonical_address(address) other_client = JSONRPCClient(web3, privkey) other_token_proxy = Token( jsonrpc_client=other_client, token_address=to_canonical_address(token_proxy.proxy.contract.address), contract_manager=contract_manager, ) # send some funds from deployer to generated address transfer_funds = 100 token_proxy.transfer(address, transfer_funds) assert transfer_funds == token_proxy.balance_of(address) allow_funds = 100 token_proxy.approve(address, allow_funds) assert allow_funds == token_proxy.proxy.contract.functions.allowance( to_checksum_address(deploy_client.address), to_checksum_address(address), ).call(block_identifier='latest') other_token_proxy.transfer(deploy_client.address, transfer_funds) assert token_proxy.balance_of(address) == 0
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 test_token(deploy_client, token_proxy, private_keys, web3, contract_manager): privkey = private_keys[1] address = privatekey_to_address(privkey) address = to_canonical_address(address) other_client = JSONRPCClient(web3, privkey) other_token_proxy = Token( jsonrpc_client=other_client, token_address=to_canonical_address(token_proxy.proxy.address), contract_manager=contract_manager, block_identifier=BLOCK_ID_LATEST, ) # send some funds from deployer to generated address transfer_funds = 100 transaction_hash = token_proxy.transfer(address, transfer_funds) assert is_tx_hash_bytes(transaction_hash) assert transfer_funds == token_proxy.balance_of(address) allow_funds = 100 transaction_hash = token_proxy.approve(address, allow_funds) assert is_tx_hash_bytes(transaction_hash) assert allow_funds == token_proxy.proxy.functions.allowance( deploy_client.address, address).call(block_identifier=BLOCK_ID_LATEST) other_token_proxy.transfer(deploy_client.address, transfer_funds) assert token_proxy.balance_of(address) == 0
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, 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 _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_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 token(self, token_address: TokenAddress) -> Token: """ Return a proxy to interact with a token. """ if not is_binary_address(token_address): raise ValueError("token_address must be a valid address") with self._token_creation_lock: if token_address not in self.address_to_token: self.address_to_token[token_address] = Token( jsonrpc_client=self.client, token_address=token_address, contract_manager=self.contract_manager, ) return self.address_to_token[token_address]
def deploy_token_and_return_proxy(deploy_client, contract_manager): token_contract = deploy_token( deploy_client=deploy_client, contract_manager=contract_manager, initial_amount=10000, decimals=0, token_name="TKN", token_symbol="TKN", ) return Token( jsonrpc_client=deploy_client, token_address=to_canonical_address(token_contract.contract.address), contract_manager=contract_manager, )
def deploy_token_and_return_proxy(deploy_client: JSONRPCClient, contract_manager: ContractManager, token_contract_name: str) -> Token: token_contract = deploy_token( deploy_client=deploy_client, contract_manager=contract_manager, initial_amount=TokenAmount(1000 * 10**18), decimals=0, token_name="TKN", token_symbol="TKN", token_contract_name=token_contract_name, ) return Token( jsonrpc_client=deploy_client, token_address=TokenAddress(token_contract.contract_address), contract_manager=contract_manager, )
def deploy_smart_contract_bundle_concurrently( deploy_client: JSONRPCClient, contract_manager: ContractManager, proxy_manager: ProxyManager, chain_id: ChainID, environment_type: Environment, max_token_networks: int, number_of_tokens: int, private_keys: List[PrivateKey], register_tokens: bool, settle_timeout_max: int, settle_timeout_min: int, token_amount: TokenAmount, token_contract_name: str, ) -> FixtureSmartContracts: greenlets: Set[Greenlet] = set() participants = [privatekey_to_address(key) for key in private_keys] secret_registry_deploy_greenlet = gevent.spawn( deploy_secret_registry, deploy_client=deploy_client, contract_manager=contract_manager, proxy_manager=proxy_manager, ) greenlets.add(secret_registry_deploy_greenlet) token_network_registry_deploy_greenlet = gevent.spawn( deploy_token_network_registry, secret_registry_deploy_result=secret_registry_deploy_greenlet.get, deploy_client=deploy_client, contract_manager=contract_manager, proxy_manager=proxy_manager, chain_id=chain_id, settle_timeout_min=settle_timeout_min, settle_timeout_max=settle_timeout_max, max_token_networks=max_token_networks, ) greenlets.add(token_network_registry_deploy_greenlet) # ERC20 tokens used for token networks token_contracts_greenlets = list() for _ in range(number_of_tokens): token_deploy_greenlet = gevent.spawn( deploy_token, deploy_client=deploy_client, contract_manager=contract_manager, initial_amount=token_amount, decimals=2, token_name="raiden", token_symbol="Rd", token_contract_name=token_contract_name, ) greenlets.add(token_deploy_greenlet) token_contracts_greenlets.append(token_deploy_greenlet) # Fund the nodes for transfer_to in participants: fund_node_greenlet = gevent.spawn( fund_node, token_result=token_deploy_greenlet.get, proxy_manager=proxy_manager, to_address=transfer_to, amount=TokenAmount(token_amount // len(participants)), ) greenlets.add(fund_node_greenlet) if register_tokens: register_grenlet = gevent.spawn( register_token, token_deploy_result=token_deploy_greenlet.get, token_network_registry_deploy_result= token_network_registry_deploy_greenlet.get, ) greenlets.add(register_grenlet) del token_deploy_greenlet if environment_type == Environment.DEVELOPMENT: utility_token_deploy_greenlet = gevent.spawn( deploy_token, deploy_client=deploy_client, contract_manager=contract_manager, initial_amount=TokenAmount(1000 * 10**18), decimals=0, token_name="TKN", token_symbol="TKN", token_contract_name=token_contract_name, ) greenlets.add(utility_token_deploy_greenlet) if register_tokens: register_utility_token_grenlet = gevent.spawn( register_token, token_deploy_result=utility_token_deploy_greenlet.get, token_network_registry_deploy_result= token_network_registry_deploy_greenlet.get, ) greenlets.add(register_utility_token_grenlet) service_registry_deploy_greenlet = gevent.spawn( deploy_service_registry, token_deploy_result=utility_token_deploy_greenlet.get, deploy_client=deploy_client, contract_manager=contract_manager, proxy_manager=proxy_manager, ) greenlets.add(service_registry_deploy_greenlet) user_deposit_deploy_greenlet = gevent.spawn( deploy_user_deposit, token_deploy_result=utility_token_deploy_greenlet.get, deploy_client=deploy_client, contract_manager=contract_manager, proxy_manager=proxy_manager, ) greenlets.add(user_deposit_deploy_greenlet) one_to_n_deploy_greenlet = gevent.spawn( deploy_one_to_n, user_deposit_deploy_result=user_deposit_deploy_greenlet.get, service_registry_deploy_result=service_registry_deploy_greenlet. get, deploy_client=deploy_client, contract_manager=contract_manager, proxy_manager=proxy_manager, chain_id=chain_id, ) greenlets.add(one_to_n_deploy_greenlet) monitoring_service_deploy_greenlet = gevent.spawn( deploy_monitoring_service, token_deploy_result=utility_token_deploy_greenlet.get, user_deposit_deploy_result=user_deposit_deploy_greenlet.get, service_registry_deploy_result=service_registry_deploy_greenlet. get, token_network_registry_deploy_result= token_network_registry_deploy_greenlet.get, deploy_client=deploy_client, contract_manager=contract_manager, proxy_manager=proxy_manager, ) greenlets.add(monitoring_service_deploy_greenlet) for transfer_to in participants: transfer_grenlet = gevent.spawn( transfer_user_deposit_tokens, user_deposit_deploy_result=user_deposit_deploy_greenlet.get, transfer_to=transfer_to, ) greenlets.add(transfer_grenlet) gevent.joinall(greenlets, raise_error=True) secret_registry_proxy = secret_registry_deploy_greenlet.get() token_network_registry_proxy = token_network_registry_deploy_greenlet.get() token_contracts = [ token_deploy_greenlet.get() for token_deploy_greenlet in token_contracts_greenlets ] services_smart_contracts: Optional[ServicesSmartContracts] = None if environment_type == Environment.DEVELOPMENT: one_to_n_proxy = one_to_n_deploy_greenlet.get() user_deposit_proxy = user_deposit_deploy_greenlet.get() service_registry_proxy = service_registry_deploy_greenlet.get() utility_token_contract = utility_token_deploy_greenlet.get() monitoring_service_proxy = monitoring_service_deploy_greenlet.get() utility_token_proxy = Token(deploy_client, utility_token_contract.address, contract_manager, BLOCK_ID_LATEST) utility_token_network_proxy: Optional[TokenNetwork] = None if register_tokens: utility_token_network_address = register_utility_token_grenlet.get( ) utility_token_network_proxy = proxy_manager.token_network( utility_token_network_address, BLOCK_ID_LATEST) services_smart_contracts = ServicesSmartContracts( utility_token_proxy=utility_token_proxy, utility_token_network_proxy=utility_token_network_proxy, one_to_n_proxy=one_to_n_proxy, user_deposit_proxy=user_deposit_proxy, service_registry_proxy=service_registry_proxy, monitoring_service=monitoring_service_proxy, ) return FixtureSmartContracts( secret_registry_proxy=secret_registry_proxy, token_network_registry_proxy=token_network_registry_proxy, token_contracts=token_contracts, services_smart_contracts=services_smart_contracts, )
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 _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
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, beneficiary: Address, total_deposit: TokenAmount, block_identifier: BlockSpecification, ) -> None: """ Deposit provided amount into the user-deposit contract to the beneficiary's account. """ token_address = self.token_address(block_identifier) token = Token( jsonrpc_client=self.client, token_address=token_address, contract_manager=self.contract_manager, ) log_details = { "beneficiary": pex(beneficiary), "contract": pex(self.address), "total_deposit": total_deposit, } checking_block = self.client.get_checking_block() error_prefix = "Call to deposit will fail" with self.deposit_lock: amount_to_deposit, log_details = self._deposit_preconditions( total_deposit=total_deposit, beneficiary=beneficiary, token=token, block_identifier=block_identifier, ) gas_limit = self.proxy.estimate_gas( checking_block, "deposit", to_checksum_address(beneficiary), total_deposit) if gas_limit: error_prefix = "Call to deposit failed" log.debug("deposit called", **log_details) transaction_hash = self.proxy.transact( "deposit", safe_gas_limit(gas_limit), to_checksum_address(beneficiary), total_deposit, ) 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 self.proxy.jsonrpc_client.check_for_insufficient_eth( transaction_name="deposit", transaction_executed=transaction_executed, required_gas=GAS_REQUIRED_FOR_UDC_DEPOSIT, block_identifier=block, ) msg = self._check_why_deposit_failed( token=token, amount_to_deposit=amount_to_deposit, total_deposit=total_deposit, block_identifier=block, ) error_msg = f"{error_prefix}. {msg}" log.critical(error_msg, **log_details) raise RaidenUnrecoverableError(error_msg) log.info("deposit successful", **log_details)
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 _add_token( self, token_address: TokenAddress, channel_participant_deposit_limit: TokenAmount, token_network_deposit_limit: TokenAmount, log_details: Dict[Any, Any], ) -> Tuple[TransactionHash, TokenNetworkAddress]: token_network_address = None kwargs = { "_token_address": token_address, "_channel_participant_deposit_limit": channel_participant_deposit_limit, "_token_network_deposit_limit": token_network_deposit_limit, } estimated_transaction = self.rpc_client.estimate_gas( self.proxy, "createERC20TokenNetwork", log_details, **kwargs) if estimated_transaction is not None: estimated_transaction.estimated_gas = safe_gas_limit( estimated_transaction.estimated_gas, self.gas_measurements[ "TokenNetworkRegistry createERC20TokenNetwork"], ) transaction_sent = self.rpc_client.transact(estimated_transaction) transaction_mined = self.rpc_client.poll_transaction( transaction_sent) receipt = transaction_mined.receipt if not was_transaction_successfully_mined(transaction_mined): failed_at_blocknumber = BlockNumber(receipt["blockNumber"]) max_token_networks = self.get_max_token_networks( block_identifier=failed_at_blocknumber) token_networks_created = self.get_token_network_created( block_identifier=failed_at_blocknumber) already_registered = self.get_token_network( token_address=token_address, block_identifier=failed_at_blocknumber) deprecation_executor = self.get_deprecation_executor( block_identifier=failed_at_blocknumber) settlement_timeout_min = self.settlement_timeout_min( block_identifier=failed_at_blocknumber) settlement_timeout_max = self.settlement_timeout_max( block_identifier=failed_at_blocknumber) chain_id = self.get_chain_id( block_identifier=failed_at_blocknumber) secret_registry_address = self.get_secret_registry_address( block_identifier=failed_at_blocknumber) try: # Creating a new instance to run the constructor checks. token_proxy = Token( jsonrpc_client=self.rpc_client, token_address=token_address, contract_manager=self.proxy_manager.contract_manager, block_identifier=failed_at_blocknumber, ) except AddressWithoutCode: # This cannot be an unrecoverable error, since the ERC20 # code is external. raise RaidenRecoverableError( "Token disappeared! The address " f"{to_checksum_address(token_address)} did have code at " f"block {log_details['given_block_identifier']}, however " f"at block {failed_at_blocknumber} when the registration " "transaction was mined the address didn't have code " "anymore.") check_transaction_failure(transaction_mined, self.rpc_client) check_address_has_code_handle_pruned_block( client=self.rpc_client, address=Address(secret_registry_address), contract_name=CONTRACT_SECRET_REGISTRY, expected_code=decode_hex( self.proxy_manager.contract_manager. get_runtime_hexcode(CONTRACT_SECRET_REGISTRY)), given_block_identifier=failed_at_blocknumber, ) if token_networks_created >= max_token_networks: raise RaidenRecoverableError( "The number of existing token networks reached the maximum allowed" ) if already_registered: # Race condition lost, the token network was created in a different # transaction which got mined first. raise RaidenRecoverableError( "The token was already registered in the TokenNetworkRegistry." ) if deprecation_executor == NULL_ADDRESS_BYTES: raise RaidenUnrecoverableError( "The deprecation executor property for the " "TokenNetworkRegistry is invalid.") if chain_id == 0: raise RaidenUnrecoverableError( "The chain ID property for the TokenNetworkRegistry is invalid." ) if chain_id != self.rpc_client.chain_id: raise RaidenUnrecoverableError( 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 RaidenUnrecoverableError( "The secret registry address for the token network is invalid." ) if settlement_timeout_min == 0: raise RaidenUnrecoverableError( "The minimum settlement timeout for the token network " "should be larger than zero.") if settlement_timeout_max <= settlement_timeout_min: raise RaidenUnrecoverableError( "The maximum settlement timeout for the token network " "should be larger than the minimum settlement timeout." ) total_supply = token_proxy.total_supply( block_identifier=failed_at_blocknumber) if not total_supply or total_supply <= 0: raise RaidenRecoverableError( f"The given token address is not a valid ERC20 token, " f"total_supply() returned an invalid value {total_supply}." ) # At this point, the TokenNetworkRegistry fails to instantiate # a new TokenNetwork. raise RaidenUnrecoverableError( "createERC20TokenNetwork failed for an unknown reason, even " "though the gas estimation succeeded.") succeeded_at_blockhash = receipt["blockHash"] token_network_address = self.get_token_network( token_address, succeeded_at_blockhash) if token_network_address is None: msg = "createERC20TokenNetwork succeeded but token network address is Null" raise RaidenUnrecoverableError(msg) else: # `estimated_transaction` is None # The latest block can not be used reliably because of reorgs, # therefore every call using this block has to handle pruned data. failed_at_block = self.rpc_client.get_block(BLOCK_ID_LATEST) failed_at_blockhash = failed_at_block["hash"].hex() failed_at_blocknumber = failed_at_block["number"] max_token_networks = self.get_max_token_networks( block_identifier=failed_at_blocknumber) token_networks_created = self.get_token_network_created( block_identifier=failed_at_blocknumber) already_registered = self.get_token_network( token_address=token_address, block_identifier=failed_at_blocknumber) deprecation_executor = self.get_deprecation_executor( block_identifier=failed_at_blocknumber) settlement_timeout_min = self.settlement_timeout_min( block_identifier=failed_at_blocknumber) settlement_timeout_max = self.settlement_timeout_max( block_identifier=failed_at_blocknumber) chain_id = self.get_chain_id( block_identifier=failed_at_blocknumber) secret_registry_address = self.get_secret_registry_address( block_identifier=failed_at_blocknumber) try: # Creating a new instance to run the constructor checks. token_proxy = Token( jsonrpc_client=self.rpc_client, token_address=token_address, contract_manager=self.proxy_manager.contract_manager, block_identifier=failed_at_blocknumber, ) except AddressWithoutCode: # This cannot be an unrecoverable error, since the ERC20 # code is external. raise RaidenRecoverableError( "Token disappeared! The address " "{to_checksum_address(token_address)} did have code at " "block {log_details['given_block_identifier']}, however " "at block {failed_at_blocknumber} when the registration " "transaction was mined the address didn't have code " "anymore.") check_address_has_code_handle_pruned_block( client=self.rpc_client, address=Address(secret_registry_address), contract_name=CONTRACT_SECRET_REGISTRY, expected_code=decode_hex( self.proxy_manager.contract_manager.get_runtime_hexcode( CONTRACT_SECRET_REGISTRY)), given_block_identifier=failed_at_blocknumber, ) required_gas = self.gas_measurements[ "TokenNetworkRegistry createERC20TokenNetwork"] self.rpc_client.check_for_insufficient_eth( transaction_name="createERC20TokenNetwork", transaction_executed=False, required_gas=required_gas, block_identifier=failed_at_blocknumber, ) if token_networks_created >= max_token_networks: raise RaidenRecoverableError( "The number of existing token networks reached the maximum allowed" ) if already_registered: # Race condition lost, the token network was created in a different # transaction which got mined first. raise RaidenRecoverableError( "The token was already registered in the TokenNetworkRegistry." ) if deprecation_executor == NULL_ADDRESS_BYTES: raise RaidenUnrecoverableError( "The deprecation executor property for the TokenNetworkRegistry is invalid." ) if chain_id == 0: raise RaidenUnrecoverableError( "The chain ID property for the TokenNetworkRegistry is invalid." ) if chain_id != self.rpc_client.chain_id: raise RaidenUnrecoverableError( 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 RaidenUnrecoverableError( "The secret registry address for the token network is invalid." ) if settlement_timeout_min <= 0: raise RaidenUnrecoverableError( "The minimum settlement timeout for the token network " "should be larger than zero.") if settlement_timeout_max <= settlement_timeout_min: raise RaidenUnrecoverableError( "The maximum settlement timeout for the token network " "should be larger than the minimum settlement timeout.") total_supply = token_proxy.total_supply( block_identifier=failed_at_blocknumber) if not total_supply or total_supply <= 0: raise RaidenRecoverableError( f"The given token address is not a valid ERC20 token, " f"total_supply() returned an invalid value {total_supply}." ) # At this point, the TokenNetworkRegistry fails to instantiate # a new TokenNetwork. raise RaidenUnrecoverableError( f"createERC20TokenNetwork gas estimation failed for an unknown " f"reason. Reference block {failed_at_blockhash} " f"{failed_at_blocknumber}.") return ( TransactionHash(transaction_mined.transaction_hash), TokenNetworkAddress(token_network_address), )
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
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 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