def contract_manager_meta(contracts_path: Path) -> None:
    """ See failures in looking up non-existent ABI entries of TokenNetwork and CLOSED """
    manager = ContractManager(contracts_path)

    abi = manager.get_contract_abi(CONTRACT_TOKEN_NETWORK)
    assert isinstance(abi, list)
    with pytest.raises(KeyError):
        manager.get_contract_abi("SomeName")
    with pytest.raises(KeyError):
        manager.get_contract("SomeName")

    abi2 = manager.get_event_abi(CONTRACT_TOKEN_NETWORK, ChannelEvent.CLOSED)
    assert isinstance(abi2, dict)
    with pytest.raises(ValueError):
        manager.get_event_abi(CONTRACT_TOKEN_NETWORK, "NonExistant")
Exemple #2
0
def deploy_token_network_registry(
    secret_registry_deploy_result: Callable[[], SecretRegistry],
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    proxy_manager: ProxyManager,
    chain_id: ChainID,
    settle_timeout_min: int,
    settle_timeout_max: int,
    max_token_networks: int,
) -> TokenNetworkRegistry:
    secret_registry_proxy = secret_registry_deploy_result()
    contract, receipt = deploy_client.deploy_single_contract(
        contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY,
        contract=contract_manager.get_contract(
            CONTRACT_TOKEN_NETWORK_REGISTRY),
        constructor_parameters=[
            secret_registry_proxy.address,
            chain_id,
            settle_timeout_min,
            settle_timeout_max,
            max_token_networks,
        ],
    )

    return proxy_manager.token_network_registry(
        TokenNetworkRegistryAddress(to_canonical_address(contract.address)),
        BlockNumber(receipt["blockNumber"]),
    )
Exemple #3
0
def deploy_monitoring_service(
    token_deploy_result: Callable[[], Contract],
    user_deposit_deploy_result: Callable[[], UserDeposit],
    service_registry_deploy_result: Callable[[], ServiceRegistry],
    token_network_registry_deploy_result: Callable[[], TokenNetworkRegistry],
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    proxy_manager: ProxyManager,
) -> MonitoringService:
    token_contract = token_deploy_result()
    token_network_registry_proxy = token_network_registry_deploy_result()
    user_deposit_proxy = user_deposit_deploy_result()
    service_registry_proxy = service_registry_deploy_result()
    contract, receipt = deploy_client.deploy_single_contract(
        contract_name=CONTRACT_MONITORING_SERVICE,
        contract=contract_manager.get_contract(CONTRACT_MONITORING_SERVICE),
        constructor_parameters=[
            token_contract.address,
            service_registry_proxy.address,
            user_deposit_proxy.address,
            token_network_registry_proxy.address,
        ],
    )
    return proxy_manager.monitoring_service(
        MonitoringServiceAddress(to_canonical_address(contract.address)),
        BlockNumber(receipt["blockNumber"]),
    )
Exemple #4
0
def deploy_service_registry(
    token_deploy_result: Callable[[], Contract],
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    proxy_manager: ProxyManager,
) -> ServiceRegistry:
    token_contract = token_deploy_result()
    contract, receipt = deploy_client.deploy_single_contract(
        contract_name=CONTRACT_SERVICE_REGISTRY,
        contract=contract_manager.get_contract(CONTRACT_SERVICE_REGISTRY),
        constructor_parameters=(
            token_contract.address,
            EMPTY_ADDRESS,
            int(500e18),
            6,
            5,
            180 * SECONDS_PER_DAY,
            1000,
            200 * SECONDS_PER_DAY,
        ),
    )

    return proxy_manager.service_registry(
        ServiceRegistryAddress(to_canonical_address(contract.address)),
        BlockNumber(receipt["blockNumber"]),
    )
Exemple #5
0
def deploy_contract_web3(
    contract_name: str,
    deploy_client: JSONRPCClient,
    *args,
) -> typing.Address:
    manager = ContractManager(CONTRACTS_SOURCE_DIRS)
    contract_interface = manager.get_contract(contract_name)

    contract = deploy_client.web3.eth.contract(
        abi=contract_interface['abi'],
        bytecode=contract_interface['bin'],
    )

    transaction = contract.constructor(*args).buildTransaction()
    transaction['nonce'] = deploy_client.nonce()

    signed_txn = deploy_client.web3.eth.account.signTransaction(
        transaction,
        deploy_client.privkey,
    )
    tx_hash = deploy_client.web3.eth.sendRawTransaction(
        signed_txn.rawTransaction)

    deploy_client.poll(tx_hash)

    receipt = deploy_client.get_transaction_receipt(tx_hash)

    if receipt.get('status', 0) == 0:
        raise RuntimeError('contract was not sucessfully deployed')

    return unhexlify(remove_0x_prefix(receipt['contractAddress']))
Exemple #6
0
def deploy_contract_txhash(
    web3: Web3,
    contracts_manager: ContractManager,
    deployer_address: HexAddress,
    contract_name: str,
    libs: Dict = None,
    **kwargs: Any,
) -> Tuple[HexAddress, Contract]:
    json_contract = contracts_manager.get_contract(contract_name)
    abi = json_contract["abi"]
    bytecode = json_contract["bin"]
    bytecode_runtime = None

    if isinstance(libs, dict) and len(libs.keys()) > 0:
        bytecode = link_code(bytecode, libs)
        bytecode_runtime = link_code(json_contract["bin-runtime"], libs)

    if bytecode_runtime is not None:
        contract = web3.eth.contract(abi=abi, bytecode=bytecode, bytecode_runtime=bytecode_runtime)
    else:
        contract = web3.eth.contract(abi=abi, bytecode=bytecode)

    mine_blocks(web3, 3)
    # Failure does not fire an exception. Check the receipt for status.
    txhash = contract.constructor(**kwargs).transact({"from": deployer_address})
    mine_blocks(web3, 1)

    receipt = web3.eth.getTransactionReceipt(txhash)
    if receipt["status"] != 1:
        raise TransactionFailed("deployment failed")

    return txhash, contract(receipt["contractAddress"])
Exemple #7
0
class ContractDeployer:
    def __init__(
        self,
        web3: Web3,
        private_key: str,
        gas_limit: int,
        gas_price: int = 1,
        wait: int = 10,
    ):
        self.web3 = web3
        self.private_key = private_key
        self.wait = wait
        owner = private_key_to_address(private_key)
        self.transaction = {'from': owner, 'gas_limit': gas_limit}
        if gas_price != 0:
            self.transaction['gasPrice'] = gas_price * denoms.gwei

        self.contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH)

        # Check that the precompiled data is correct
        self.contract_manager = ContractManager(CONTRACTS_SOURCE_DIRS)
        self.contract_manager.checksum_contracts()
        self.contract_manager.verify_precompiled_checksums(
            CONTRACTS_PRECOMPILED_PATH)

    def deploy(
        self,
        contract_name: str,
        args=None,
    ):
        if args is None:
            args = list()
        contract_interface = self.contract_manager.get_contract(
            contract_name, )

        # Instantiate and deploy contract
        contract = self.web3.eth.contract(
            abi=contract_interface['abi'],
            bytecode=contract_interface['bin'],
        )
        contract = PrivateContract(contract)

        # Get transaction hash from deployed contract
        txhash = contract.constructor(*args).transact(
            self.transaction,
            private_key=self.private_key,
        )

        # Get tx receipt to get contract address
        log.debug("Deploying %s txHash=%s" %
                  (contract_name, encode_hex(txhash)))
        receipt = check_succesful_tx(self.web3, txhash, self.wait)
        log.info(
            '{0} address: {1}. Gas used: {2}'.format(
                contract_name,
                receipt['contractAddress'],
                receipt['gasUsed'],
            ), )
        return receipt['contractAddress']
Exemple #8
0
def get_or_deploy_token(runner: 'ScenarioRunner') -> ContractProxy:
    """ Deploy or reuse  """
    contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH)
    token_contract = contract_manager.get_contract(CONTRACT_CUSTOM_TOKEN)

    token_config = runner.scenario.get('token', {})
    if not token_config:
        token_config = {}
    address = token_config.get('address')
    reuse = token_config.get('reuse', False)

    token_address_file = runner.data_path.joinpath('token.addr')
    if reuse:
        if address:
            raise ScenarioError(
                'Token settings "address" and "reuse" are mutually exclusive.')
        if token_address_file.exists():
            address = token_address_file.read_text()
    if address:
        check_address_has_code(runner.client, address, 'Token')
        token_ctr = runner.client.new_contract_proxy(token_contract['abi'],
                                                     address)

        log.debug(
            "Reusing token",
            address=to_checksum_address(address),
            name=token_ctr.contract.functions.name().call(),
            symbol=token_ctr.contract.functions.symbol().call(),
        )
        return token_ctr

    token_id = uuid.uuid4()
    now = datetime.now()
    name = token_config.get(
        'name', f"Scenario Test Token {token_id!s} {now:%Y-%m-%dT%H:%M}")
    symbol = token_config.get('symbol', f"T{token_id!s:.3}")
    decimals = token_config.get('decimals', 0)

    log.debug("Deploying token", name=name, symbol=symbol, decimals=decimals)

    token_ctr = runner.client.deploy_solidity_contract(
        'CustomToken',
        contract_manager.contracts,
        constructor_parameters=(0, decimals, name, symbol),
        confirmations=1,
    )
    contract_checksum_address = to_checksum_address(token_ctr.contract_address)
    if reuse:
        token_address_file.write_text(contract_checksum_address)

    log.info(
        "Deployed token",
        address=contract_checksum_address,
        name=name,
        symbol=symbol,
    )
    return token_ctr
class ContractTester:
    def __init__(self, generate_keys=0):
        self.tester = EthereumTester(PyEVMBackend())
        self.tester.set_fork_block('FORK_BYZANTIUM', 0)
        self.web3 = Web3(EthereumTesterProvider(self.tester))
        if generate_keys > 0:
            generated_keys = [urandom(32) for _ in range(generate_keys)]
            self.private_keys = [PrivateKey(key) for key in generated_keys]
            self.accounts = [
                self.tester.add_account(f'0x{hexlify(key).decode()}')
                for key in generated_keys
            ]
            for account in self.accounts:
                self.tester.send_transaction({
                    'from':
                    self.tester.get_accounts()[0],
                    'to':
                    account,
                    'value':
                    10**21,
                    'gas':
                    21000,
                })
        else:
            self.accounts = self.tester.get_accounts()
        self.contract_manager = ContractManager(CONTRACTS_SOURCE_DIRS)
        self.name_to_creation_hash = dict()
        self.name_to_contract = dict()

    def deploy_contract(self, name, **kwargs):
        data = self.contract_manager.get_contract(name)
        contract = self.web3.eth.contract(abi=data['abi'],
                                          bytecode=data['bin'])
        transaction = contract.constructor(**kwargs).buildTransaction({
            'from':
            self.accounts[0],
            'gas':
            5900000,
        })
        self.name_to_creation_hash[name] = self.web3.eth.sendTransaction(
            transaction)
        self.name_to_contract[name] = self.web3.eth.contract(
            address=self.contract_address(name),
            abi=data['abi'],
        )

    def contract_address(self, name):
        tx_hash = self.name_to_creation_hash[name]
        return self.web3.eth.getTransactionReceipt(tx_hash)['contractAddress']

    def call_transaction(self, contract, function, **kwargs):
        sender = kwargs.pop('sender', self.accounts[0])
        tx_hash = self.name_to_contract[contract].functions[function](
            **kwargs).transact({
                'from': sender,
            })
        return self.web3.eth.getTransactionReceipt(tx_hash)
Exemple #10
0
def deploy_contract_web3(
    contract_name: str,
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    constructor_arguments: Sequence = None,
) -> Address:
    contract_proxy, _ = deploy_client.deploy_single_contract(
        contract_name=contract_name,
        contract=contract_manager.get_contract(contract_name),
        constructor_parameters=constructor_arguments,
    )
    return Address(to_canonical_address(contract_proxy.contract.address))
Exemple #11
0
def get_or_deploy_token(runner) -> ContractProxy:
    """ Deploy or reuse  """
    contract_manager = ContractManager(contracts_precompiled_path())
    token_contract = contract_manager.get_contract(CONTRACT_CUSTOM_TOKEN)

    token_config = runner.scenario.get('token', {})
    if not token_config:
        token_config = {}
    address = token_config.get('address')
    reuse = token_config.get('reuse', False)

    token_address_file = runner.data_path.joinpath('token.addr')
    if reuse:
        if address:
            raise ScenarioError('Token settings "address" and "reuse" are mutually exclusive.')
        if token_address_file.exists():
            address = token_address_file.read_text()
    if address:
        check_address_has_code(runner.client, address, 'Token')
        token_ctr = runner.client.new_contract_proxy(token_contract['abi'], address)

        log.debug(
            "Reusing token",
            address=to_checksum_address(address),
            name=token_ctr.contract.functions.name().call(),
            symbol=token_ctr.contract.functions.symbol().call(),
        )
        return token_ctr

    token_id = uuid.uuid4()
    now = datetime.now()
    name = token_config.get('name', f"Scenario Test Token {token_id!s} {now:%Y-%m-%dT%H:%M}")
    symbol = token_config.get('symbol', f"T{token_id!s:.3}")
    decimals = token_config.get('decimals', 0)

    log.debug("Deploying token", name=name, symbol=symbol, decimals=decimals)

    token_ctr = runner.client.deploy_solidity_contract(
        'CustomToken',
        contract_manager.contracts,
        constructor_parameters=(0, decimals, name, symbol),
    )
    contract_checksum_address = to_checksum_address(token_ctr.contract_address)
    if reuse:
        token_address_file.write_text(contract_checksum_address)

    log.info(
        "Deployed token",
        address=contract_checksum_address,
        name=name,
        symbol=symbol,
    )
    return token_ctr
Exemple #12
0
def deploy_contract_web3(
    contract_name: str,
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    constructor_arguments: Tuple[Any] = None,
) -> Address:
    compiled = {contract_name: contract_manager.get_contract(contract_name)}
    contract_proxy, _ = deploy_client.deploy_solidity_contract(
        contract_name=contract_name,
        all_contracts=compiled,
        constructor_parameters=constructor_arguments,
    )
    return Address(to_canonical_address(contract_proxy.contract.address))
Exemple #13
0
def deploy_secret_registry(deploy_client: JSONRPCClient,
                           contract_manager: ContractManager,
                           proxy_manager: ProxyManager) -> SecretRegistry:
    contract, receipt = deploy_client.deploy_single_contract(
        contract_name=CONTRACT_SECRET_REGISTRY,
        contract=contract_manager.get_contract(CONTRACT_SECRET_REGISTRY),
        constructor_parameters=None,
    )

    return proxy_manager.secret_registry(
        SecretRegistryAddress(to_canonical_address(contract.address)),
        BlockNumber(receipt["blockNumber"]),
    )
def deploy_contract(
    web3: Web3,
    contracts_manager: ContractManager,
    contract_name: str,
    deployer_key: CCPrivateKey,
    args: List[Any],
) -> Contract:
    deployer_address = private_key_to_address(deployer_key.to_hex())
    json_contract = contracts_manager.get_contract(contract_name)
    contract = web3.eth.contract(abi=json_contract["abi"], bytecode=json_contract["bin"])
    tx_hash = contract.constructor(*args).transact(TxParams({"from": deployer_address}))
    contract_address = web3.eth.get_transaction_receipt(tx_hash)["contractAddress"]

    return contract(contract_address)
def deploy_contract_web3(
        contract_name: str,
        deploy_client: JSONRPCClient,
        contract_manager: ContractManager,
        constructor_arguments: typing.Tuple[typing.Any, ...] = (),
) -> typing.Address:
    compiled = {
        contract_name: contract_manager.get_contract(contract_name),
    }
    contract_proxy = deploy_client.deploy_solidity_contract(
        contract_name,
        compiled,
        constructor_parameters=constructor_arguments,
    )
    return typing.Address(to_canonical_address(contract_proxy.contract.address))
Exemple #16
0
def deploy_contract(
    web3: Web3,
    contracts_manager: ContractManager,
    contract_name: str,
    deployer_key: PrivateKey,
    args: Optional[List] = None,
) -> Contract:
    deployer_address = private_key_to_address(deployer_key.to_hex())
    json_contract = contracts_manager.get_contract(contract_name)
    contract = web3.eth.contract(abi=json_contract["abi"],
                                 bytecode=json_contract["bin"])
    tx_hash = contract.constructor(*args).call_and_transact(
        {"from": deployer_address})
    contract_address = web3.eth.getTransactionReceipt(tx_hash).contractAddress

    return contract(contract_address)
Exemple #17
0
def deploy_token(
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    initial_amount: TokenAmount,
    decimals: int,
    token_name: str,
    token_symbol: str,
    token_contract_name: str,
) -> Contract:
    contract_proxy, _ = deploy_client.deploy_single_contract(
        contract_name=token_contract_name,
        contract=contract_manager.get_contract(token_contract_name),
        constructor_parameters=(initial_amount, decimals, token_name,
                                token_symbol),
    )
    return contract_proxy
Exemple #18
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"]),
    )
class ContractTester:
    def __init__(self, generate_keys=0):
        self.tester = EthereumTester(PyEVMBackend())
        self.web3 = Web3(EthereumTesterProvider(self.tester))
        if generate_keys > 0:
            generated_keys = [urandom(32) for _ in range(generate_keys)]
            self.private_keys = [PrivateKey(key) for key in generated_keys]
            self.accounts = [
                self.tester.add_account(f'{encode_hex(key)}')
                for key in generated_keys
            ]
            for account in self.accounts:
                self.tester.send_transaction({
                    'from': self.tester.get_accounts()[0],
                    'to': account,
                    'value': 10 ** 21,
                    'gas': 21000,
                })
        else:
            self.accounts = self.tester.get_accounts()
        self.contract_manager = ContractManager(CONTRACTS_SOURCE_DIRS)
        self.name_to_creation_hash = dict()
        self.name_to_contract = dict()

    def deploy_contract(self, name, **kwargs):
        data = self.contract_manager.get_contract(name)
        contract = self.web3.eth.contract(abi=data['abi'], bytecode=data['bin'])
        transaction = contract.constructor(**kwargs).buildTransaction({
            'from': self.accounts[0],
            'gas': 5900000,
        })
        self.name_to_creation_hash[name] = self.web3.eth.sendTransaction(transaction)
        self.name_to_contract[name] = self.web3.eth.contract(
            address=self.contract_address(name),
            abi=data['abi'],
        )

    def contract_address(self, name):
        tx_hash = self.name_to_creation_hash[name]
        return self.web3.eth.getTransactionReceipt(tx_hash)['contractAddress']

    def call_transaction(self, contract, function, **kwargs):
        sender = kwargs.pop('sender', self.accounts[0])
        tx_hash = self.name_to_contract[contract].functions[function](**kwargs).transact({
            'from': sender,
        })
        return self.web3.eth.getTransactionReceipt(tx_hash)
Exemple #20
0
def deploy_contract_web3(
    contract_name: str,
    deploy_client: JSONRPCClient,
    num_confirmations: int = None,
    constructor_arguments: typing.Tuple[typing.Any, ...] = (),
) -> typing.Address:
    contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH)
    compiled = {
        contract_name: contract_manager.get_contract(contract_name),
    }
    contract_proxy = deploy_client.deploy_solidity_contract(
        contract_name,
        compiled,
        constructor_parameters=constructor_arguments,
        confirmations=num_confirmations,
    )
    return typing.Address(to_canonical_address(
        contract_proxy.contract.address))
Exemple #21
0
def deploy_one_to_n(
    user_deposit_deploy_result: Callable[[], UserDeposit],
    service_registry_deploy_result: Callable[[], ServiceRegistry],
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    proxy_manager: ProxyManager,
    chain_id: ChainID,
) -> OneToN:
    user_deposit_proxy = user_deposit_deploy_result()
    service_registry_proxy = service_registry_deploy_result()
    contract, receipt = deploy_client.deploy_single_contract(
        contract_name=CONTRACT_ONE_TO_N,
        contract=contract_manager.get_contract(CONTRACT_ONE_TO_N),
        constructor_parameters=[
            user_deposit_proxy.address,
            chain_id,
            service_registry_proxy.address,
        ],
    )
    return proxy_manager.one_to_n(
        OneToNAddress(to_canonical_address(contract.address)),
        BlockNumber(receipt["blockNumber"]))
Exemple #22
0
def get_token_network(web3: Web3, address: ChecksumAddress,
                      contracts_manager: ContractManager) -> Contract:
    json_contract = contracts_manager.get_contract(CONTRACT_TOKEN_NETWORK)

    return web3.eth.contract(abi=json_contract["abi"], address=address)
Exemple #23
0
def deploy_token():
    """Deploy a new token contract.

    ---
    parameters:
      - name: client_id
        in: query
        required: true
        schema:
          type: string

    post:
      description": "Deploy a new token contract."
      parameters:
        - name: constructor_args
          in: query
          required: true
          schema:
            type: object
            properties:
              decimals:
                type: integer
                format: int32
              name:
                type: string
              symbol:
                type: string

        - name: token_name
          in: query
          required: false
          schema:
            type: string

      responses:
        200:
          description: "Address and deployment block of the deployed contract."
          content:
            application/json:
              schema: {$ref: '#/components/schemas/TokenCreateSchema'}

    """
    with REDMetricsTracker():
        log.info("Processing Token Contract Deployment Request",
                 request=request)
        data = token_create_schema.validate_and_deserialize(request.get_json())
        rpc_client = data["client"]
        token_name = data.get("token_name") or data["constructor_args"][1]

        contract_manager = ContractManager(contracts_precompiled_path())

        constructor_args = data["constructor_args"]

        decimals, name, symbol = (
            constructor_args["decimals"],
            constructor_args["name"],
            constructor_args["symbol"],
        )

        log.info(
            "deploying contract",
            constructor_parameters=(1, decimals, name, symbol),
            client_id=rpc_client.client_id,
        )

        token_contract, receipt = rpc_client.deploy_single_contract(
            "CustomToken",
            contract_manager.get_contract("CustomToken"),
            constructor_parameters=(1, decimals, name, symbol),
        )

        contract_address = to_checksum_address(token_contract.contract_address)
        log.debug("Received deployment receipt",
                  receipt=receipt,
                  contract_address=contract_address)

        deployment_block = receipt["blockNumber"]
        dumped = token_create_schema.dump({
            "contract": {
                "address": contract_address,
                "name": token_name
            },
            "deployment_block": deployment_block,
        })
        log.info("Token Contract deployed", receipt=dumped)
        return jsonify(dumped)
def test_deprecation_executor(
    web3: Web3,
    contracts_manager: ContractManager,
    deploy_contract: Callable,
    secret_registry_contract: Contract,
    custom_token: Contract,
    channel_participant_deposit_limit: int,
    token_network_deposit_limit: int,
    get_accounts: Callable,
) -> None:
    """ A creates a TokenNetworkRegistry and B registers a TokenNetwork

    This test is mainly a happy-path scenario. One Ethereum account creates a
    TokenNetworkRegistry, registers a TokenNetwork. TokenNetworkRegistry emits
    events that shows the new TokenNetwork. The new TokenNetwork has the
    original account as the deprecation executor. During these, this test also
    tries to register more than one TokenNetworks and see a failure.
    """
    (deprecation_executor, B) = get_accounts(2)

    json_contract = contracts_manager.get_contract(
        CONTRACT_TOKEN_NETWORK_REGISTRY)
    token_network_registry = deploy_contract(
        web3,
        deprecation_executor,
        json_contract["abi"],
        json_contract["bin"],
        _secret_registry_address=secret_registry_contract.address,
        _chain_id=int(web3.version.network),
        _settlement_timeout_min=TEST_SETTLE_TIMEOUT_MIN,
        _settlement_timeout_max=TEST_SETTLE_TIMEOUT_MAX,
        _max_token_networks=1,
    )

    # Make sure deployer is deprecation_executor
    assert token_network_registry.functions.deprecation_executor().call(
    ) == deprecation_executor
    assert token_network_registry.functions.token_network_created().call() == 0

    # We can only deploy one TokenNetwork contract
    # It can be deployed by anyone
    tx_hash = token_network_registry.functions.createERC20TokenNetwork(
        custom_token.address, channel_participant_deposit_limit,
        token_network_deposit_limit).call_and_transact({"from": B})
    assert token_network_registry.functions.token_network_created().call() == 1

    # No other TokenNetworks can be deployed now
    with pytest.raises(TransactionFailed):
        token_network_registry.functions.createERC20TokenNetwork(
            custom_token.address, channel_participant_deposit_limit,
            token_network_deposit_limit).call({"from": B})
    with pytest.raises(TransactionFailed):
        token_network_registry.functions.createERC20TokenNetwork(
            custom_token.address, channel_participant_deposit_limit,
            token_network_deposit_limit).call({"from": deprecation_executor})

    tx_receipt = web3.eth.getTransactionReceipt(tx_hash)
    event_abi = contracts_manager.get_event_abi(
        CONTRACT_TOKEN_NETWORK_REGISTRY, EVENT_TOKEN_NETWORK_CREATED)
    event_data = get_event_data(event_abi, tx_receipt["logs"][0])
    token_network_address = event_data["args"]["token_network_address"]
    token_network = web3.eth.contract(
        abi=contracts_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK),
        address=token_network_address,
    )

    assert token_network.functions.deprecation_executor().call(
    ) == deprecation_executor
Exemple #25
0
def test_participant_deposit_amount_must_be_smaller_than_the_limit(
        raiden_network: List[App], contract_manager: ContractManager,
        retry_timeout: float) -> None:
    """The Python API must properly check the requested participant deposit
    will not exceed the smart contract limit.

    This is companion test for
    `test_deposit_amount_must_be_smaller_than_the_token_network_limit`. The
    participant deposit limit was introduced for the bug bounty with the PR
    https://github.com/raiden-network/raiden-contracts/pull/276/ , the limit is
    available since version 0.4.0 of the smart contract.
    """
    app1 = raiden_network[0]

    registry_address = app1.raiden.default_registry.address

    token_supply = 1_000_000
    contract_proxy, _ = app1.raiden.rpc_client.deploy_single_contract(
        contract_name=CONTRACT_HUMAN_STANDARD_TOKEN,
        contract=contract_manager.get_contract(CONTRACT_HUMAN_STANDARD_TOKEN),
        constructor_parameters=(token_supply, 2, "raiden", "Rd"),
    )
    token_address = TokenAddress(to_canonical_address(contract_proxy.address))

    api1 = RaidenAPI(app1.raiden)

    msg = "Token is not registered yet, it must not be in the token list."
    assert token_address not in api1.get_tokens_list(registry_address), msg

    # Wait until Raiden can start using the token contract.
    # Here, the block at which the contract was deployed should be confirmed by Raiden.
    # Therefore, until that block is received.
    waiting.wait_for_block(
        raiden=app1.raiden,
        block_number=BlockNumber(app1.raiden.get_block_number() +
                                 DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS + 1),
        retry_timeout=retry_timeout,
    )

    token_network_participant_deposit_limit = TokenAmount(100)
    api1.token_network_register(
        registry_address=registry_address,
        token_address=token_address,
        channel_participant_deposit_limit=
        token_network_participant_deposit_limit,
        token_network_deposit_limit=TokenAmount(UINT256_MAX),
    )

    exception = RuntimeError(
        "Did not see the token registration within 30 seconds")
    with gevent.Timeout(seconds=30, exception=exception):
        wait_for_state_change(
            app1.raiden,
            ContractReceiveNewTokenNetwork,
            {"token_network": {
                "token_address": token_address
            }},
            retry_timeout,
        )

    msg = "Token has been registered, yet must be available in the token list."
    assert token_address in api1.get_tokens_list(registry_address), msg

    partner_address = make_address()
    api1.channel_open(
        registry_address=app1.raiden.default_registry.address,
        token_address=token_address,
        partner_address=partner_address,
    )

    with pytest.raises(DepositOverLimit):
        api1.set_total_channel_deposit(
            registry_address=app1.raiden.default_registry.address,
            token_address=token_address,
            partner_address=partner_address,
            total_deposit=TokenAmount(token_network_participant_deposit_limit +
                                      1),
        )

        pytest.fail(
            "The deposit must fail if the requested deposit exceeds the participant deposit limit."
        )
Exemple #26
0
def test_deposit_amount_must_be_smaller_than_the_token_network_limit(
        raiden_network: List[App], contract_manager: ContractManager,
        retry_timeout: float) -> None:
    """The Python API must properly check the requested deposit will not exceed
    the token network deposit limit.

    This is a regression test for #3135.

    As of version `v0.18.1` (commit 786347b23), the proxy was not properly
    checking that the requested deposit amount was smaller than the smart
    contract deposit limit. This led to two errors:

    - The error message was vague and incorrect: "Deposit amount decreased"
    - The exception used was not handled and crashed the node.

    This test checks the limit is properly check from the REST API.
    """
    app1 = raiden_network[0]

    registry_address = app1.raiden.default_registry.address

    token_supply = 1_000_000
    contract_proxy, _ = app1.raiden.rpc_client.deploy_single_contract(
        contract_name=CONTRACT_HUMAN_STANDARD_TOKEN,
        contract=contract_manager.get_contract(CONTRACT_HUMAN_STANDARD_TOKEN),
        constructor_parameters=(token_supply, 2, "raiden", "Rd"),
    )
    token_address = TokenAddress(to_canonical_address(contract_proxy.address))

    # Wait until Raiden can start using the token contract.
    # Here, the block at which the contract was deployed should be confirmed by Raiden.
    # Therefore, until that block is received.
    waiting.wait_for_block(
        raiden=app1.raiden,
        block_number=BlockNumber(app1.raiden.get_block_number() +
                                 DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS + 1),
        retry_timeout=retry_timeout,
    )

    api1 = RaidenAPI(app1.raiden)

    msg = "Token is not registered yet, it must not be in the token list."
    assert token_address not in api1.get_tokens_list(registry_address), msg

    token_network_deposit_limit = TokenAmount(100)
    api1.token_network_register(
        registry_address=registry_address,
        token_address=token_address,
        channel_participant_deposit_limit=token_network_deposit_limit,
        token_network_deposit_limit=token_network_deposit_limit,
    )

    exception = RuntimeError(
        "Did not see the token registration within 30 seconds")
    with gevent.Timeout(seconds=30, exception=exception):
        wait_for_state_change(
            app1.raiden,
            ContractReceiveNewTokenNetwork,
            {"token_network": {
                "token_address": token_address
            }},
            retry_timeout,
        )

    msg = "Token has been registered, yet must be available in the token list."
    assert token_address in api1.get_tokens_list(registry_address), msg

    partner_address = make_address()
    api1.channel_open(
        registry_address=app1.raiden.default_registry.address,
        token_address=token_address,
        partner_address=partner_address,
    )

    with pytest.raises(DepositOverLimit):
        api1.set_total_channel_deposit(
            registry_address=app1.raiden.default_registry.address,
            token_address=token_address,
            partner_address=partner_address,
            total_deposit=TokenAmount(token_network_deposit_limit + 1),
        )

        pytest.fail(
            "The deposit must fail if the requested deposit exceeds the token "
            "network deposit limit.")
Exemple #27
0
class ContractDeployer:
    def __init__(
        self,
        web3: Web3,
        private_key: str,
        gas_limit: int,
        gas_price: int = 1,
        wait: int = 10,
        contracts_version: Optional[str] = None,
    ):
        # pylint: disable=E1101
        self.web3 = web3
        self.wait = wait
        self.owner = private_key_to_address(private_key)
        self.transaction = {'from': self.owner, 'gas': gas_limit}
        if gas_price != 0:
            self.transaction['gasPrice'] = gas_price * denoms.gwei

        self.contracts_version = contracts_version
        self.precompiled_path = contracts_precompiled_path(
            self.contracts_version)
        self.contract_manager = ContractManager(self.precompiled_path)
        self.web3.middleware_stack.add(
            construct_sign_and_send_raw_middleware(private_key), )

        # Check that the precompiled data matches the source code
        # Only for current version, because this is the only one with source code
        if self.contracts_version in [None, CONTRACTS_VERSION]:
            contract_manager_source = ContractSourceManager(
                contracts_source_path())
            contract_manager_source.checksum_contracts()
            contract_manager_source.verify_precompiled_checksums(
                self.precompiled_path)
        else:
            LOG.info(
                'Skipped checks against the source code because it is not available.'
            )

    def deploy(
        self,
        contract_name: str,
        args=None,
    ):
        if args is None:
            args = list()
        contract_interface = self.contract_manager.get_contract(
            contract_name, )

        # Instantiate and deploy contract
        contract = self.web3.eth.contract(
            abi=contract_interface['abi'],
            bytecode=contract_interface['bin'],
        )

        # Get transaction hash from deployed contract
        txhash = self.send_deployment_transaction(
            contract=contract,
            args=args,
        )

        # Get tx receipt to get contract address
        LOG.debug(
            f'Deploying {contract_name} txHash={encode_hex(txhash)}, '
            f'contracts version {self.contract_manager.contracts_version}', )
        (receipt, tx) = check_successful_tx(
            web3=self.web3,
            txid=txhash,
            timeout=self.wait,
        )
        if not receipt['contractAddress']:  # happens with Parity
            receipt = dict(receipt)
            receipt['contractAddress'] = tx['creates']
        LOG.info(
            '{0} address: {1}. Gas used: {2}'.format(
                contract_name,
                receipt['contractAddress'],
                receipt['gasUsed'],
            ), )
        return receipt

    def transact(
        self,
        contract_method: ContractFunction,
    ):
        """ A wrapper around to_be_called.transact() that waits until the transaction succeeds. """
        txhash = contract_method.transact(self.transaction)
        LOG.debug(f'Sending txHash={encode_hex(txhash)}')
        (receipt, _) = check_successful_tx(
            web3=self.web3,
            txid=txhash,
            timeout=self.wait,
        )
        return receipt

    def send_deployment_transaction(self, contract, args):
        txhash = None
        while txhash is None:
            try:
                txhash = contract.constructor(*args).transact(
                    self.transaction, )
            except ValueError as ex:
                # pylint: disable=E1126
                if ex.args[0]['code'] == -32015:
                    LOG.info(f'Deployment failed with {ex}. Retrying...')
                else:
                    raise ex

        return txhash

    def contract_version_string(self):
        return contract_version_string(self.contracts_version)
class ContractDeployer:
    def __init__(
        self,
        web3: Web3,
        private_key: str,
        gas_limit: int,
        gas_price: int=1,
        wait: int=10,
        contracts_version: Optional[str]=None,
    ):
        self.web3 = web3
        self.wait = wait
        self.owner = private_key_to_address(private_key)
        self.transaction = {'from': self.owner, 'gas': gas_limit}
        if gas_price != 0:
            self.transaction['gasPrice'] = gas_price * denoms.gwei

        self.contracts_version = contracts_version
        self.precompiled_path = contracts_precompiled_path(self.contracts_version)
        self.contract_manager = ContractManager(self.precompiled_path)
        self.web3.middleware_stack.add(
            construct_sign_and_send_raw_middleware(private_key),
        )

        # Check that the precompiled data matches the source code
        # Only for current version, because this is the only one with source code
        if self.contracts_version in [None, CONTRACTS_VERSION]:
            contract_manager_source = ContractManager(contracts_source_path())
            contract_manager_source.checksum_contracts()
            contract_manager_source.verify_precompiled_checksums(self.precompiled_path)
        else:
            log.info('Skipped checks against the source code because it is not available.')

    def deploy(
        self,
        contract_name: str,
        args=None,
    ):
        if args is None:
            args = list()
        contract_interface = self.contract_manager.get_contract(
            contract_name,
        )

        # Instantiate and deploy contract
        contract = self.web3.eth.contract(
            abi=contract_interface['abi'],
            bytecode=contract_interface['bin'],
        )

        # Get transaction hash from deployed contract
        txhash = self.send_deployment_transaction(contract, args)

        # Get tx receipt to get contract address
        log.debug(
            f'Deploying {contract_name} txHash={encode_hex(txhash)}, '
            f'contracts version {self.contract_manager.contracts_version}',
        )
        receipt = check_succesful_tx(self.web3, txhash, self.wait)
        log.info(
            '{0} address: {1}. Gas used: {2}'.format(
                contract_name,
                receipt['contractAddress'],
                receipt['gasUsed'],
            ),
        )
        return receipt

    def send_deployment_transaction(self, contract, args):
        txhash = None
        while txhash is None:
            try:
                txhash = contract.constructor(*args).transact(
                    self.transaction,
                )
            except ValueError as ex:
                if ex.args[0]['code'] == -32015:
                    log.info(f'Deployment failed with {ex}. Retrying...')
                else:
                    raise ex

        return txhash
class ContractDeployer:
    def __init__(
        self,
        web3: Web3,
        private_key: str,
        gas_limit: int,
        gas_price: int = 1,
        wait: int = 10,
        contracts_version: Optional[str] = None,
    ):
        self.web3 = web3
        self.private_key = private_key
        self.wait = wait
        self.owner = private_key_to_address(private_key)
        self.transaction = {'from': self.owner, 'gas_limit': gas_limit}
        if gas_price != 0:
            self.transaction['gasPrice'] = gas_price * denoms.gwei

        self.contracts_version = contracts_version
        self.precompiled_path = contracts_precompiled_path(
            self.contracts_version)
        self.contract_manager = ContractManager(self.precompiled_path)

        # Check that the precompiled data is correct
        self.contract_manager = ContractManager(contracts_source_path())
        self.contract_manager.checksum_contracts()
        self.contract_manager.verify_precompiled_checksums(
            self.precompiled_path)

    def deploy(
        self,
        contract_name: str,
        args=None,
    ):
        if args is None:
            args = list()
        contract_interface = self.contract_manager.get_contract(
            contract_name, )

        # Instantiate and deploy contract
        contract = self.web3.eth.contract(
            abi=contract_interface['abi'],
            bytecode=contract_interface['bin'],
        )
        contract = PrivateContract(contract)

        # Get transaction hash from deployed contract
        txhash = self.send_deployment_transaction(contract, args)

        # Get tx receipt to get contract address
        log.debug("Deploying %s txHash=%s" %
                  (contract_name, encode_hex(txhash)))
        receipt = check_succesful_tx(self.web3, txhash, self.wait)
        log.info(
            '{0} address: {1}. Gas used: {2}'.format(
                contract_name,
                receipt['contractAddress'],
                receipt['gasUsed'],
            ), )
        return receipt

    def send_deployment_transaction(self, contract, args):
        txhash = None
        while txhash is None:
            try:
                txhash = contract.constructor(*args).transact(
                    self.transaction,
                    private_key=self.private_key,
                )
            except ValueError as ex:
                if ex.args[0]['code'] == -32015:
                    log.info(f'Deployment failed with {ex}. Retrying...')
                else:
                    raise ex

        return txhash
Exemple #30
0
def deploy_smoketest_contracts(
    client: JSONRPCClient,
    chain_id: ChainID,
    contract_manager: ContractManager,
    token_address: AddressHex,
) -> Dict[str, Address]:
    if client.eth_node is EthClient.GETH:
        client.web3.geth.personal.unlockAccount(client.web3.eth.accounts[0],
                                                DEFAULT_PASSPHRASE)
    elif client.eth_node is EthClient.PARITY:
        client.web3.parity.personal.unlockAccount(client.web3.eth.accounts[0],
                                                  DEFAULT_PASSPHRASE)

    contract_proxy, _ = client.deploy_single_contract(
        contract_name=CONTRACT_SECRET_REGISTRY,
        contract=contract_manager.get_contract(CONTRACT_SECRET_REGISTRY),
        constructor_parameters=None,
    )
    secret_registry_address = Address(
        to_canonical_address(contract_proxy.address))

    secret_registry_constructor_arguments = (
        to_checksum_address(secret_registry_address),
        chain_id,
        TEST_SETTLE_TIMEOUT_MIN,
        TEST_SETTLE_TIMEOUT_MAX,
        UINT256_MAX,
    )

    contract_proxy, _ = client.deploy_single_contract(
        contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY,
        contract=contract_manager.get_contract(
            CONTRACT_TOKEN_NETWORK_REGISTRY),
        constructor_parameters=secret_registry_constructor_arguments,
    )
    token_network_registry_address = Address(
        to_canonical_address(contract_proxy.address))

    service_registry_constructor_arguments = (
        token_address,
        EMPTY_ADDRESS,
        int(500e18),
        6,
        5,
        180 * SECONDS_PER_DAY,
        1000,
        200 * SECONDS_PER_DAY,
    )
    service_registry_contract, _ = client.deploy_single_contract(
        contract_name=CONTRACT_SERVICE_REGISTRY,
        contract=contract_manager.get_contract(CONTRACT_SERVICE_REGISTRY),
        constructor_parameters=service_registry_constructor_arguments,
    )
    service_registry_address = Address(
        to_canonical_address(service_registry_contract.address))

    user_deposit_contract, _ = client.deploy_single_contract(
        contract_name=CONTRACT_USER_DEPOSIT,
        contract=contract_manager.get_contract(CONTRACT_USER_DEPOSIT),
        constructor_parameters=(token_address, UINT256_MAX),
    )
    user_deposit_address = Address(
        to_canonical_address(user_deposit_contract.address))

    monitoring_service_contract, _ = client.deploy_single_contract(
        contract_name=CONTRACT_MONITORING_SERVICE,
        contract=contract_manager.get_contract(CONTRACT_MONITORING_SERVICE),
        constructor_parameters=(
            token_address,
            service_registry_address,
            user_deposit_address,
            token_network_registry_address,
        ),
    )
    monitoring_service_address = Address(
        to_canonical_address(monitoring_service_contract.address))

    one_to_n_contract, _ = client.deploy_single_contract(
        contract_name=CONTRACT_ONE_TO_N,
        contract=contract_manager.get_contract(CONTRACT_ONE_TO_N),
        constructor_parameters=(user_deposit_address, chain_id,
                                service_registry_address),
    )
    one_to_n_address = Address(to_canonical_address(one_to_n_contract.address))

    proxy_manager = ProxyManager(
        rpc_client=client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )
    user_deposit_proxy = UserDeposit(
        jsonrpc_client=client,
        user_deposit_address=UserDepositAddress(
            to_canonical_address(user_deposit_contract.address)),
        contract_manager=contract_manager,
        proxy_manager=proxy_manager,
        block_identifier=BLOCK_ID_LATEST,
    )
    transaction_hash = user_deposit_proxy.init(
        monitoring_service_address=MonitoringServiceAddress(
            monitoring_service_address),
        one_to_n_address=OneToNAddress(one_to_n_address),
        given_block_identifier=BLOCK_ID_LATEST,
    )
    assert is_tx_hash_bytes(transaction_hash)

    addresses = {
        CONTRACT_SECRET_REGISTRY: secret_registry_address,
        CONTRACT_TOKEN_NETWORK_REGISTRY: token_network_registry_address,
        CONTRACT_SERVICE_REGISTRY: service_registry_address,
        CONTRACT_USER_DEPOSIT: user_deposit_address,
        CONTRACT_MONITORING_SERVICE: monitoring_service_address,
        CONTRACT_ONE_TO_N: one_to_n_address,
    }

    return addresses