def deploy_user_deposit_and_return_address( proxy_manager: ProxyManager, deploy_client: JSONRPCClient, contract_manager: ContractManager, token_proxy: Token, private_keys: List[PrivateKey], environment_type: Environment, ) -> Optional[Address]: """ Deploy UserDeposit and fund accounts with some balances """ if environment_type != Environment.DEVELOPMENT: return None constructor_arguments = [token_proxy.address, UINT256_MAX] user_deposit_address = deploy_contract_web3( contract_name=CONTRACT_USER_DEPOSIT, deploy_client=deploy_client, contract_manager=contract_manager, constructor_arguments=constructor_arguments, ) user_deposit = proxy_manager.user_deposit( UserDepositAddress(user_deposit_address)) participants = [privatekey_to_address(key) for key in private_keys] for transfer_to in participants: user_deposit.deposit( beneficiary=transfer_to, total_deposit=MONITORING_REWARD, given_block_identifier="latest", ) return user_deposit_address
def get_udc_and_corresponding_token_from_dependencies( chain_id: ChainID, proxy_manager: ProxyManager, development_environment: ContractDevEnvironment, udc_address: ChecksumAddress = None, ) -> Tuple[UserDeposit, CustomToken]: """Return contract proxies for the UserDepositContract and associated token. This will return a proxy to the `UserDeposit` contract as determined by the **local** Raiden depedency. """ if udc_address is None: contracts = get_contracts_deployment_info( chain_id, version=RAIDEN_CONTRACT_VERSION, development_environment=development_environment, ) msg = (f"invalid chain_id, {chain_id} is not available " f"for version {RAIDEN_CONTRACT_VERSION}") assert contracts, msg udc_address = contracts["contracts"][CONTRACT_USER_DEPOSIT]["address"] userdeposit_proxy = proxy_manager.user_deposit( UserDepositAddress(to_canonical_address(udc_address)), "latest") token_address = userdeposit_proxy.token_address("latest") user_token_proxy = proxy_manager.custom_token(token_address, "latest") return userdeposit_proxy, user_token_proxy
def deploy_user_deposit( token_deploy_result: Callable[[], Contract], deploy_client: JSONRPCClient, contract_manager: ContractManager, proxy_manager: ProxyManager, ) -> UserDeposit: token_contract = token_deploy_result() contract, receipt = deploy_client.deploy_single_contract( contract_name=CONTRACT_USER_DEPOSIT, contract=contract_manager.get_contract(CONTRACT_USER_DEPOSIT), constructor_parameters=[token_contract.address, UINT256_MAX], ) return proxy_manager.user_deposit( UserDepositAddress(to_canonical_address(contract.address)), BlockNumber(receipt["blockNumber"]), )
def load_deployment_addresses_from_udc( proxy_manager: ProxyManager, user_deposit_address: UserDepositAddress, block_identifier: BlockIdentifier, ) -> DeploymentAddresses: """Given a user deposit address, this function returns the list of contract addresses which are used as services which are bound to the user deposit contract deployed. """ block_identifier = BLOCK_ID_LATEST user_deposit = proxy_manager.user_deposit( UserDepositAddress(to_canonical_address(user_deposit_address)), block_identifier=block_identifier, ) monitoring_service_address = user_deposit.monitoring_service_address( block_identifier) one_to_n_address = user_deposit.one_to_n_address( block_identifier=block_identifier) monitoring_service_proxy = proxy_manager.monitoring_service( address=monitoring_service_address, block_identifier=block_identifier) token_network_registry_address = monitoring_service_proxy.token_network_registry_address( block_identifier=block_identifier) token_network_registry_proxy = proxy_manager.token_network_registry( token_network_registry_address, block_identifier=block_identifier) secret_registry_address = token_network_registry_proxy.get_secret_registry_address( block_identifier=block_identifier) service_registry_address = monitoring_service_proxy.service_registry_address( block_identifier=block_identifier) return DeploymentAddresses( token_network_registry_address=token_network_registry_address, secret_registry_address=secret_registry_address, user_deposit_address=user_deposit_address, service_registry_address=service_registry_address, monitoring_service_address=monitoring_service_address, one_to_n_address=one_to_n_address, )
def test_user_deposit_proxy_withdraw( private_keys: List[bytes], web3: Web3, contract_manager: ContractManager, user_deposit_address: Address, ): c0_client = JSONRPCClient(web3, PrivateKey(private_keys[0])) c0_proxy_manager = ProxyManager( rpc_client=c0_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c0_user_deposit_proxy = c0_proxy_manager.user_deposit( UserDepositAddress(user_deposit_address), BLOCK_ID_LATEST) withdraw_plan = c0_user_deposit_proxy.get_withdraw_plan( c0_client.address, BLOCK_ID_LATEST) # There should be no withdraw plan assert withdraw_plan.withdraw_block == 0 assert withdraw_plan.withdraw_amount == 0 current_deposit = c0_user_deposit_proxy.get_total_deposit( c0_client.address, BLOCK_ID_LATEST) # None of these are valid plan_withdraw amounts for value in [-1, 0, current_deposit + 1]: with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.plan_withdraw(TokenAmount(value), BLOCK_ID_LATEST) # With no plan any withdraw must fail in the precondition check with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(1), BLOCK_ID_LATEST) withdraw_amount = TokenAmount(current_deposit // 2) withdraw_block = c0_user_deposit_proxy.plan_withdraw( withdraw_amount, BLOCK_ID_LATEST) # The effective balance must take the planned withdraw into account effective_balance_after_withdraw_plan = c0_user_deposit_proxy.effective_balance( c0_client.address, BLOCK_ID_LATEST) assert effective_balance_after_withdraw_plan == current_deposit - withdraw_amount # Wait until target block - 1. # We set the retry timeout to 0.1 to make sure there is enough time for the failing case # below. c0_client.wait_until_block(BlockNumber(withdraw_block - 1), retry_timeout=0.1) # Withdraw should still fail with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(withdraw_amount), BLOCK_ID_LATEST) # Wait the final block c0_user_deposit_proxy.client.wait_until_block(withdraw_block) # Now withdraw must succeed c0_user_deposit_proxy.withdraw(TokenAmount(withdraw_amount), BLOCK_ID_LATEST) # The total deposit must now match the reduced value new_current_deposit = c0_user_deposit_proxy.get_total_deposit( c0_client.address, BLOCK_ID_LATEST) assert new_current_deposit == current_deposit - withdraw_amount
def setup_proxies_or_exit( config: Dict[str, Any], tokennetwork_registry_contract_address: TokenNetworkRegistryAddress, secret_registry_contract_address: Address, user_deposit_contract_address: Address, service_registry_contract_address: Address, proxy_manager: ProxyManager, contracts: Dict[str, Any], routing_mode: RoutingMode, pathfinding_service_address: str, ) -> Proxies: """ Initialize and setup the contract proxies. Depending on the provided contract addresses via the CLI, the routing mode, the environment type and the network id try to initialize the proxies. Returns the initialized proxies or exits the application with an error if there is a problem. Also depending on the given arguments populate config with PFS related settings """ node_network_id = config["chain_id"] environment_type = config["environment_type"] check_smart_contract_addresses( environment_type=environment_type, node_network_id=node_network_id, tokennetwork_registry_contract_address= tokennetwork_registry_contract_address, secret_registry_contract_address=secret_registry_contract_address, contracts=contracts, ) token_network_registry = None try: if tokennetwork_registry_contract_address is not None: registered_address = tokennetwork_registry_contract_address else: registered_address = to_canonical_address( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]["address"]) token_network_registry = proxy_manager.token_network_registry( registered_address) except ContractCodeMismatch as e: handle_contract_code_mismatch(e) except AddressWithoutCode: handle_contract_no_code( "token network registry", Address(tokennetwork_registry_contract_address)) except AddressWrongContract: handle_contract_wrong_address( "token network registry", Address(tokennetwork_registry_contract_address)) secret_registry = None try: secret_registry = proxy_manager.secret_registry( secret_registry_contract_address or to_canonical_address( contracts[CONTRACT_SECRET_REGISTRY]["address"])) except ContractCodeMismatch as e: handle_contract_code_mismatch(e) except AddressWithoutCode: handle_contract_no_code("secret registry", secret_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address("secret registry", secret_registry_contract_address) # If services contracts are provided via the CLI use them instead if user_deposit_contract_address is not None: contracts[CONTRACT_USER_DEPOSIT] = user_deposit_contract_address if service_registry_contract_address is not None: contracts[ CONTRACT_SERVICE_REGISTRY] = service_registry_contract_address user_deposit = None should_use_user_deposit = ( environment_type == Environment.DEVELOPMENT and ID_TO_NETWORKNAME.get(node_network_id) != "smoketest" and CONTRACT_USER_DEPOSIT in contracts) if should_use_user_deposit: try: user_deposit = proxy_manager.user_deposit( user_deposit_contract_address or to_canonical_address( contracts[CONTRACT_USER_DEPOSIT]["address"])) except ContractCodeMismatch as e: handle_contract_code_mismatch(e) except AddressWithoutCode: handle_contract_no_code("user deposit", user_deposit_contract_address) except AddressWrongContract: handle_contract_wrong_address("user_deposit", user_deposit_contract_address) service_registry = None if CONTRACT_SERVICE_REGISTRY in contracts or service_registry_contract_address: try: service_registry = proxy_manager.service_registry( service_registry_contract_address or to_canonical_address( contracts[CONTRACT_SERVICE_REGISTRY]["address"])) except ContractCodeMismatch as e: handle_contract_code_mismatch(e) except AddressWithoutCode: handle_contract_no_code("service registry", service_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address("secret registry", service_registry_contract_address) # By now these should be set or Raiden aborted assert token_network_registry, "TokenNetworkRegistry needs to be set" assert secret_registry, "SecretRegistry needs to be set" if routing_mode == RoutingMode.PFS: check_pfs_configuration( service_registry=service_registry, pathfinding_service_address=pathfinding_service_address, ) pfs_info = configure_pfs_or_exit( pfs_url=pathfinding_service_address, routing_mode=routing_mode, service_registry=service_registry, node_network_id=node_network_id, token_network_registry_address=token_network_registry.address, pathfinding_max_fee=config["services"]["pathfinding_max_fee"], ) msg = "Eth address of selected pathfinding service is unknown." assert pfs_info.payment_address is not None, msg # Only check that PFS is registered in production mode if environment_type == Environment.PRODUCTION: check_pfs_for_production(service_registry=service_registry, pfs_info=pfs_info) config["pfs_config"] = PFSConfig( info=pfs_info, maximum_fee=config["services"]["pathfinding_max_fee"], iou_timeout=config["services"]["pathfinding_iou_timeout"], max_paths=config["services"]["pathfinding_max_paths"], ) else: config["pfs_config"] = None proxies = Proxies( token_network_registry=token_network_registry, secret_registry=secret_registry, user_deposit=user_deposit, service_registry=service_registry, ) return proxies
def test_user_deposit_proxy_withdraw( private_keys: List[bytes], web3: Web3, contract_manager: ContractManager, user_deposit_address: Address, ): c0_client = JSONRPCClient(web3, PrivateKey(private_keys[0])) c0_proxy_manager = ProxyManager( rpc_client=c0_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c0_user_deposit_proxy = c0_proxy_manager.user_deposit( UserDepositAddress(user_deposit_address), BLOCK_ID_LATEST) withdraw_plan = c0_user_deposit_proxy.get_withdraw_plan( c0_client.address, BLOCK_ID_LATEST) # There should be no withdraw plan assert withdraw_plan.withdraw_block == 0 assert withdraw_plan.withdraw_amount == 0 initial_deposit = c0_user_deposit_proxy.get_total_deposit( c0_client.address, BLOCK_ID_LATEST) # None of these are valid plan_withdraw amounts for value in [-1, 0, initial_deposit + 1]: with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.plan_withdraw(TokenAmount(value), BLOCK_ID_LATEST) # With no plan any withdraw must fail in the precondition check with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(1), BLOCK_ID_LATEST) withdraw_amount = TokenAmount(initial_deposit // 2) transaction_hash, withdraw_block = c0_user_deposit_proxy.plan_withdraw( withdraw_amount, BLOCK_ID_LATEST) assert is_tx_hash_bytes(transaction_hash) # The effective balance must take the planned withdraw into account effective_balance_after_withdraw_plan = c0_user_deposit_proxy.effective_balance( c0_client.address, BLOCK_ID_LATEST) assert effective_balance_after_withdraw_plan == initial_deposit - withdraw_amount # Wait until target block - 1. # We set the retry timeout to 0.1 to make sure there is enough time for the failing case # below. c0_client.wait_until_block(BlockNumber(withdraw_block - 1), retry_timeout=0.1) # Withdraw should still fail with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(withdraw_amount), BLOCK_ID_LATEST) # Wait the final block c0_user_deposit_proxy.client.wait_until_block(withdraw_block) # Now withdraw must succeed transaction_hash = c0_user_deposit_proxy.withdraw( TokenAmount(withdraw_amount), BLOCK_ID_LATEST) assert is_tx_hash_bytes(transaction_hash) # The current balance must now match the reduced value new_current_balance = c0_user_deposit_proxy.get_balance( c0_client.address, BLOCK_ID_LATEST) assert new_current_balance == initial_deposit - withdraw_amount # Deposit again after the funds were withdrawn amount_to_deposit = 1 tasks = set() # Force a race condition between deposits, letting successive, concurrent calls # wait for the first inflight transaction for _ in range(3): task = gevent.spawn( c0_user_deposit_proxy.approve_and_deposit, beneficiary=c0_client.address, # the total deposit needs to increase monotonically in the contract total_deposit=initial_deposit + amount_to_deposit, given_block_identifier=BLOCK_ID_LATEST, ) tasks.add(task) results = gevent.joinall(tasks, raise_error=True) # All tx have the same deposit, # so one of them should successfully transact, # while all others should wait for the inflight transaction # All calls should then be associated to the same on-chain transaction tx_hashes = set(result.get() for result in results) assert len(tx_hashes) == 1 assert is_tx_hash_bytes(tx_hashes.pop())
def deploy_smoketest_contracts( client: JSONRPCClient, proxy_manager: ProxyManager, chain_id: ChainID, contract_manager: ContractManager, token_address: AddressHex, ) -> Dict[str, Address]: client.web3.personal.unlockAccount(client.web3.eth.accounts[0], DEFAULT_PASSPHRASE) secret_registry_address = deploy_contract_web3( contract_name=CONTRACT_SECRET_REGISTRY, deploy_client=client, contract_manager=contract_manager, ) constructor_arguments = [ to_checksum_address(secret_registry_address), chain_id, TEST_SETTLE_TIMEOUT_MIN, TEST_SETTLE_TIMEOUT_MAX, UINT256_MAX, ] token_network_registry_address = deploy_contract_web3( contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY, deploy_client=client, contract_manager=contract_manager, constructor_arguments=constructor_arguments, ) addresses = { CONTRACT_SECRET_REGISTRY: secret_registry_address, CONTRACT_TOKEN_NETWORK_REGISTRY: token_network_registry_address, } service_registry_address = deploy_contract_web3( contract_name=CONTRACT_SERVICE_REGISTRY, deploy_client=client, contract_manager=contract_manager, constructor_arguments=( token_address, EMPTY_ADDRESS, int(500e18), 6, 5, 180 * SECONDS_PER_DAY, 1000, 200 * SECONDS_PER_DAY, ), ) addresses[CONTRACT_SERVICE_REGISTRY] = service_registry_address user_deposit_address = deploy_contract_web3( contract_name=CONTRACT_USER_DEPOSIT, deploy_client=client, contract_manager=contract_manager, constructor_arguments=(token_address, UINT256_MAX), ) addresses[CONTRACT_USER_DEPOSIT] = user_deposit_address monitoring_service_address = deploy_contract_web3( contract_name=CONTRACT_MONITORING_SERVICE, deploy_client=client, contract_manager=contract_manager, constructor_arguments=( token_address, service_registry_address, user_deposit_address, token_network_registry_address, ), ) addresses[CONTRACT_MONITORING_SERVICE] = monitoring_service_address one_to_n_address = deploy_contract_web3( contract_name=CONTRACT_ONE_TO_N, deploy_client=client, contract_manager=contract_manager, constructor_arguments=(user_deposit_address, chain_id, service_registry_address), ) addresses[CONTRACT_ONE_TO_N] = one_to_n_address user_deposit_proxy = proxy_manager.user_deposit(UserDepositAddress(user_deposit_address)) user_deposit_proxy.init( monitoring_service_address=MonitoringServiceAddress(monitoring_service_address), one_to_n_address=OneToNAddress(one_to_n_address), given_block_identifier="latest", ) return addresses