Beispiel #1
0
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
Beispiel #3
0
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"]),
    )
Beispiel #4
0
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
Beispiel #6
0
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
Beispiel #7
0
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())
Beispiel #8
0
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