def test_deploy_data_all(version: Optional[str], chain_id: ChainID) -> None: data_all = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.ALL) data_default = get_contracts_deployment_info(chain_id, version) assert data_all assert data_all == data_default for name in RAIDEN_CONTRACT_NAMES + SERVICE_CONTRACT_NAMES: deployed = data_all["contracts"][name] reasonable_deployment_of_a_contract(deployed)
def _verify_singleton_contract( chain_id: ChainID, apikey: str, source_module: DeploymentModule, contract_name: str, ) -> None: """ Calls Etherscan API for verifying the Solidity source of a contract. This function can only be used to verify contracts which are only deployed once. E.g. `TokenNetworkRegistry`, but not `TokenNetwork`. Args: chain_id: EIP-155 chain id of the Ethereum chain apikey: key for calling Etherscan API source_module: a module name to look up contracts_source_path() contract_name: 'TokenNetworkRegistry', 'SecretRegistry' etc. """ deployment_info = get_contracts_deployment_info(chain_id=chain_id, module=source_module) assert deployment_info contract_manager = ContractManager(contracts_precompiled_path()) metadata = json.loads(contract_manager.contracts[contract_name]["metadata"]) constructor_args = get_constructor_args( deployment_info=deployment_info, contract_name=contract_name, contract_manager=contract_manager, ) contract_deploy_info = deployment_info["contracts"][contract_name] etherscan_verify_contract( chain_id=chain_id, apikey=apikey, address=contract_deploy_info["address"], contract_name=contract_name, metadata=metadata, constructor_args=constructor_args, )
def setup_contracts_or_exit(config: Dict[str, Any], network_id: int) -> Dict[str, Any]: """Sets the contract deployment data depending on the network id and environment type If an invalid combination of network id and environment type is provided, exits the program with an error """ environment_type = config["environment_type"] check_raiden_environment(network_id, environment_type) contracts: Dict[str, Any] = dict() contracts_version = environment_type_to_contracts_version(environment_type) config["contracts_path"] = contracts_precompiled_path(contracts_version) if network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[ network_id] != "smoketest": deployment_data = get_contracts_deployment_info( chain_id=network_id, version=contracts_version) if not deployment_data: return contracts contracts = deployment_data["contracts"] return contracts
def __init__(self, runner: scenario_runner.ScenarioRunner, config: Any, parent: Task = None) -> None: super().__init__(runner, config, parent) required_keys = {"channel_info_key"} if not required_keys.issubset(config.keys()): raise ScenarioError( f'Not all required keys provided. Required: {", ".join(required_keys)}' ) self.web3 = self._runner.client.web3 self.contract_name = CONTRACT_MONITORING_SERVICE # get the MS contract address contract_data = get_contracts_deployment_info( chain_id=self._runner.definition.settings.chain_id, version=RAIDEN_CONTRACT_VERSION, development_environment=self._runner.environment. development_environment, ) assert contract_data try: contract_info = contract_data["contracts"][self.contract_name] self.contract_address = contract_info["address"] except KeyError: raise ScenarioError(f"Unknown contract name: {self.contract_name}")
def verify_deployed_service_contracts_in_filesystem( self, token_address: HexAddress, user_deposit_whole_balance_limit: int, token_network_registry_address: HexAddress, ) -> None: chain_id = ChainID(self.web3.eth.chain_id) deployment_data = get_contracts_deployment_info( chain_id=chain_id, version=self.contract_manager.contracts_version, module=DeploymentModule.SERVICES, ) deployment_file_path = contracts_deployed_path( chain_id=chain_id, version=self.contract_manager.contracts_version, services=True) if deployment_data is None: raise RuntimeError( f"Deployment data cannot be found at {deployment_file_path}") if self.verify_service_contracts_deployment_data( token_address=token_address, user_deposit_whole_balance_limit= user_deposit_whole_balance_limit, deployed_contracts_info=deployment_data, token_network_registry_address=token_network_registry_address, ): print( f"Deployment info from {deployment_file_path} has been verified " "and it is CORRECT.")
def get_udc_and_token(runner) -> Tuple[Optional[ContractProxy], Optional[ContractProxy]]: """ Return contract proxies for the UserDepositContract and associated token """ from scenario_player.runner import ScenarioRunner assert isinstance(runner, ScenarioRunner) udc_config = runner.yaml.settings.services.udc if not udc_config.enable: return None, None udc_address = udc_config.address if udc_address is None: contracts = get_contracts_deployment_info( chain_id=runner.chain_id, version=DEVELOPMENT_CONTRACT_VERSION ) udc_address = contracts["contracts"][CONTRACT_USER_DEPOSIT]["address"] udc_abi = runner.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT) udc_proxy = runner.client.new_contract_proxy(udc_abi, udc_address) ud_token_address = udc_proxy.contract.functions.token().call() # FIXME: We assume the UD token is a CustomToken (supporting the `mint()` function) custom_token_abi = runner.contract_manager.get_contract_abi(CONTRACT_CUSTOM_TOKEN) ud_token_proxy = runner.client.new_contract_proxy(custom_token_abi, ud_token_address) return udc_proxy, ud_token_proxy
def get_token_network_registry_from_dependencies( settings: SettingsConfig, proxy_manager: ProxyManager, development_environment: ContractDevEnvironment, smoketest_deployment_data: DeployedContracts = None, ) -> TokenNetworkRegistry: """Return contract proxies for the UserDepositContract and associated token. This will return a proxy to the `UserDeposit` contract as determined by the **local** Raiden dependency. """ chain_id = settings.chain_id assert chain_id, "Missing configuration, either set udc_address or the chain_id" if chain_id != CHAINNAME_TO_ID["smoketest"]: contracts = get_contracts_deployment_info( chain_id, version=RAIDEN_CONTRACT_VERSION, development_environment=development_environment, ) else: contracts = smoketest_deployment_data msg = f"invalid chain_id, {chain_id} is not available for version {RAIDEN_CONTRACT_VERSION}" assert contracts, msg token_network_address = contracts["contracts"][CONTRACT_TOKEN_NETWORK_REGISTRY]["address"] token_network_proxy = proxy_manager.token_network_registry( TokenNetworkRegistryAddress(to_canonical_address(token_network_address)), "latest", ) return token_network_proxy
def _run(self, *args, **kwargs): # pylint: disable=unused-argument # get the correct contract address # this has to be done in `_run`, otherwise `_runner` is not initialized yet contract_data = get_contracts_deployment_info( chain_id=self._runner.chain_id, version=DEVELOPMENT_CONTRACT_VERSION, ) if self.contract_name == CONTRACT_TOKEN_NETWORK: self.contract_address = self._runner.token_network_address else: try: contract_info = contract_data['contracts'][self.contract_name] self.contract_address = contract_info['address'] except KeyError: raise ScenarioError(f'Unknown contract name: {self.contract_name}') events = query_blockchain_events( web3=self.web3, contract_manager=self._runner.contract_manager, contract_address=self.contract_address, contract_name=self.contract_name, topics=[], from_block=BlockNumber(self._runner.token_deployment_block), to_block=BlockNumber(self.web3.eth.blockNumber), ) # Filter matching events events = [e for e in events if e['event'] == self.event_name] # Raise exception when events do not match if not self.num_events == len(events): raise ScenarioAssertionError( f'Expected number of events ({self.num_events}) did not match the number ' f'of events found ({len(events)})', )
def __init__( self, runner: ScenarioRunner, config: Any, parent: 'Task' = None, abort_on_fail: bool = True, ) -> None: super().__init__(runner, config, parent, abort_on_fail) required_keys = {'channel_info_key'} if not required_keys.issubset(config.keys()): raise ScenarioError( f'Not all required keys provided. Required: {", ".join(required_keys)}', ) self.web3 = self._runner.client.web3 self.contract_name = CONTRACT_MONITORING_SERVICE # get the MS contract address contract_data = get_contracts_deployment_info( chain_id=self._runner.chain_id, version=DEVELOPMENT_CONTRACT_VERSION, ) try: contract_info = contract_data['contracts'][self.contract_name] self.contract_address = contract_info['address'] except KeyError: raise ScenarioError(f'Unknown contract name: {self.contract_name}')
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 _run(self, *args, **kwargs) -> Dict[str, Any]: # pylint: disable=unused-argument # get the correct contract address # this has to be done in `_run`, otherwise `_runner` is not initialized yet contract_data = get_contracts_deployment_info( chain_id=self._runner.definition.settings.chain_id, version=RAIDEN_CONTRACT_VERSION, development_environment=self._runner.environment. development_environment, ) if self.contract_name == CONTRACT_TOKEN_NETWORK: self.contract_address = self._runner.token_network_address else: try: assert contract_data contract_info = contract_data["contracts"][self.contract_name] self.contract_address = to_checksum_address( contract_info["address"]) except KeyError: raise ScenarioError( f"Unknown contract name: {self.contract_name}") assert self.contract_address, "Contract address not set" events = query_blockchain_events( web3=self.web3, contract_manager=self._runner.contract_manager, contract_address=to_canonical_address(self.contract_address), contract_name=self.contract_name, topics=[], from_block=BlockNumber(self._runner.block_execution_started), to_block=BlockNumber(self.web3.eth.blockNumber), ) # Filter matching events events = [e for e in events if e["event"] == self.event_name] if self.event_args: for key, value in self.event_args.items(): if "participant" in key: if isinstance(value, int) or (isinstance(value, str) and value.isnumeric()): # Replace node index with eth address self.event_args[key] = self._runner.get_node_address( int(value)) event_args_items = self.event_args.items() # Filter the events by the given event args. # `.items()` produces a set like object which supports intersection (`&`) events = [ e for e in events if e["args"] and event_args_items & e["args"].items() ] # Raise exception when events do not match if not self.num_events == len(events): raise ScenarioAssertionError( f"Expected number of events ({self.num_events}) did not match the number " f"of events found ({len(events)})") return {"events": events}
def get_contract_address(chain_id, contract_name): try: network_contracts = get_contracts_deployment_info(chain_id) assert network_contracts return network_contracts["contracts"][contract_name]["address"] except (TypeError, AssertionError) as exc: log.warn(str(exc)) return "0x0"
def test_can_get_contract_address(self): udc_address = get_contract_address(1, CONTRACT_USER_DEPOSIT) deployment_info = get_contracts_deployment_info(ChainID(1)) assert deployment_info expected_udc_address = to_canonical_address( deployment_info["contracts"][CONTRACT_USER_DEPOSIT]["address"] ) self.assertEqual(udc_address, expected_udc_address)
def test_deploy_data_has_fields_services(version: Optional[str], chain_id: ChainID) -> None: data = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.SERVICES) assert data assert data["contracts_version"] == version if version else CONTRACTS_VERSION assert data["chain_id"] == chain_id contracts = data["contracts"] for name in SERVICE_CONTRACT_NAMES: deployed = contracts[name] reasonable_deployment_of_a_contract(deployed)
def register_token_network( self, token_registry_abi: ABI, token_registry_address: ChecksumAddress, token_address: ChecksumAddress, channel_participant_deposit_limit: int, token_network_deposit_limit: int, ) -> Dict[str, Any]: """Register token with a TokenNetworkRegistry contract.""" token_network_registry = self.web3.eth.contract( abi=token_registry_abi, address=token_registry_address) command = token_network_registry.functions.createERC20TokenNetwork( token_address, channel_participant_deposit_limit, token_network_deposit_limit) self.transact(command) LOG.debug("Collecting constructor parameters for later verification") chain_id = ChainID(self.web3.eth.chain_id) deployment_data = get_contracts_deployment_info( chain_id=chain_id, version=self.contract_manager.contracts_version, module=DeploymentModule.RAIDEN, ) assert deployment_data secret_registry = self.contract_instance_from_deployment_data( deployment_data, CONTRACT_SECRET_REGISTRY) token_network_registry = self.contract_instance_from_deployment_data( deployment_data, CONTRACT_TOKEN_NETWORK_REGISTRY) settle_timeout_min = token_network_registry.functions.settlement_timeout_min( ).call() settle_timeout_max = token_network_registry.functions.settlement_timeout_max( ).call() constructor_arguments = dict( _token_address=token_address, _secret_registry=secret_registry.address, _chain_id=chain_id, _settlement_timeout_min=settle_timeout_min, _settlement_timeout_max=settle_timeout_max, _controller=self.owner, _channel_participant_deposit_limit= channel_participant_deposit_limit, _token_network_deposit_limit=token_network_deposit_limit, ) LOG.debug("Getting address of new token network") token_network_address = "0x0" while int(token_network_address, 16) == 0: token_network_address = token_network_registry.functions.token_to_token_networks( token_address).call() time.sleep(2) LOG.debug(f"TokenNetwork address: {token_network_address}") return dict( token_network_address=token_network_address, constructor_arguments=constructor_arguments, )
def get_contract_address(chain_id, contract_name) -> Address: try: network_contracts = get_contracts_deployment_info(chain_id) assert network_contracts return to_canonical_address( network_contracts["contracts"][contract_name]["address"]) except (TypeError, AssertionError, KeyError) as exc: log.warn(str(exc)) raise ValueError( f"{contract_name} does not exist on chain id {chain_id}") from exc
def _get_contract(w3: Web3, contract_name: str): chain_id = int(w3.net.version) manager = ContractManager(contracts_precompiled_path()) contract_data = get_contracts_deployment_info(chain_id) assert contract_data address = contract_data["contracts"][contract_name]["address"] abi = manager.get_contract_abi(contract_name) return w3.eth.contract(abi=abi, address=address)
def test_deploy_data_all( version: Optional[str], chain_id: int, ): data_services = get_contracts_deployed(chain_id, version, services=True) data_raiden = get_contracts_deployed(chain_id, version, services=False) data_all_computed = merge_deployment_data(data_services, data_raiden) data_all = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.ALL) data_default = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.ALL) assert data_all == data_all_computed assert data_all == data_default for name in RAIDEN_CONTRACT_NAMES + SERVICE_CONTRACT_NAMES: deployed = data_all['contracts'][name] reasonable_deployment_of_a_contract(deployed)
def get_token_network_registry_contract(w3: Web3): chain_id = int(w3.net.version) manager = ContractManager(contracts_precompiled_path()) contract_data = get_contracts_deployment_info(ChainID(chain_id)) assert contract_data address = contract_data["contracts"][CONTRACT_TOKEN_NETWORK_REGISTRY]["address"] abi = manager.get_contract_abi(CONTRACT_TOKEN_NETWORK_REGISTRY) return w3.eth.contract(abi=abi, address=address)
def test_deploy_data_has_fields_raiden(version: Optional[str], chain_id: int): data = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.RAIDEN) assert data assert data[ "contracts_version"] == version if version else CONTRACTS_VERSION assert data["chain_id"] == chain_id contracts = data["contracts"] for name in RAIDEN_CONTRACT_NAMES: deployed = contracts[name] reasonable_deployment_of_a_contract(deployed)
def get_contract_addresses_and_start_block( chain_id: ChainID, contracts: List[str], address_overwrites: Dict[str, Address], development_environment: ContractDevEnvironment = ContractDevEnvironment. DEMO, contracts_version: Optional[str] = None, ) -> Tuple[Dict[str, Address], BlockNumber]: """Returns contract addresses and start query block for a given chain and contracts version. The default contracts can be overwritten by the additional parameters. Args: chain_id: The chain id to look for deployed contracts. contracts: The list of contracts which should be considered address_overwrites: Dict of addresses which should be used instead of the ones in the requested deployment. contracts_version: The version of the contracts to use. Returns: A dictionary with the contract addresses and start block for the given information """ contract_data = get_contracts_deployment_info( chain_id=chain_id, version=contracts_version, development_environment=development_environment, ) if not contract_data: log.error( "No deployed contracts were found at the default registry", contracts_version=contracts_version, ) sys.exit(1) # Get deployed addresses for those contracts which have no overwrites addresses = { c: (address_overwrites.get(c) or to_canonical_address(contract_data["contracts"][c]["address"])) for c in contracts } # Set start block to zero if any contract addresses are overwritten if any(address_overwrites.values()): start_block = BlockNumber(0) else: start_block = BlockNumber( max( 0, min(contract_data["contracts"][c]["block_number"] for c in contracts))) return addresses, start_block
def test_deploy_data_has_fields_services( version: Optional[str], chain_id: int, ): data = get_contracts_deployed(chain_id, version, services=True) data2 = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.SERVICES) assert data2 == data assert data[ 'contracts_version'] == version if version else CONTRACTS_VERSION assert data['chain_id'] == chain_id contracts = data['contracts'] for name in SERVICE_CONTRACT_NAMES: deployed = contracts[name] reasonable_deployment_of_a_contract(deployed)
def get_contract_addresses_and_start_block( chain_id: ChainID, contracts: List[str], address_overwrites: Dict[str, Address], contracts_version: str = None, ) -> Tuple[Dict[str, Address], BlockNumber]: """ Returns contract addresses and start query block for a given chain and contracts version. The default contracts can be overwritten by the additional parameters. Args: chain_id: The chain id to look for deployed contracts. contracts: The list of contracts which should be considered address_overwrites: Dict of addresses which should be used instead of the ones in the requested deployment. contracts_version: The version of the contracts to use. Returns: A dictionary with the contract addresses and start block for the given information """ try: contract_data = get_contracts_deployment_info( chain_id=chain_id, version=contracts_version) except ValueError: log.error( 'No deployed contracts were found at the default registry', contracts_version=contracts_version, ) sys.exit(1) # Get deployed addresses for those contracts which have no overwrites addresses = { c: address_overwrites.get( c, Address(contract_data['contracts'][c]['address'])) for c in contracts } # Set start block to zero if any contract addresses are overwritten if any(address_overwrites.values()): start_block = BlockNumber(0) else: start_block = BlockNumber( max( 0, min(contract_data['contracts'][c]['block_number'] for c in contracts))) return addresses, start_block
def verify_deployed_contracts_in_filesystem(self) -> None: chain_id = ChainID(self.web3.eth.chain_id) deployment_data = get_contracts_deployment_info( chain_id=chain_id, version=self.contract_manager.contracts_version, module=DeploymentModule.RAIDEN, ) deployment_file_path = contracts_deployed_path( chain_id=chain_id, version=self.contract_manager.contracts_version) if deployment_data is None: raise RuntimeError( f"Deployment data cannot be found at {deployment_file_path}") if self.verify_deployment_data(deployment_data): print( f"Deployment info from {deployment_file_path} has been verified " "and it is CORRECT.")
def setup_contracts_or_exit( config: Dict[str, Any], network_id: int, ) -> Tuple[Dict[str, Any], bool]: """Sets the contract deployment data depending on the network id and environment type If an invalid combination of network id and environment type is provided, exits the program with an error """ environment_type = config['environment_type'] not_allowed = ( # for now we only disallow mainnet with test configuration network_id == 1 and environment_type == Environment.DEVELOPMENT) if not_allowed: click.secho( f'The chosen network ({ID_TO_NETWORKNAME[network_id]}) is not a testnet, ' f'but the "development" environment was selected.\n' f'This is not allowed. Please start again with a safe environment setting ' f'(--environment production).', fg='red', ) sys.exit(1) contracts = dict() contract_addresses_known = False contracts_version = environment_type_to_contracts_version(environment_type) config['contracts_path'] = contracts_precompiled_path(contracts_version) if network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[ network_id] != 'smoketest': try: deployment_data = get_contracts_deployment_info( chain_id=network_id, version=contracts_version, ) except ValueError: return contracts, False contracts = deployment_data['contracts'] contract_addresses_known = True return contracts, contract_addresses_known
def load_deployed_contracts_data(config: RaidenConfig, network_id: ChainID) -> Dict[str, Any]: """Sets the contract deployment data depending on the network id and environment type If an invalid combination of network id and environment type is provided, exits the program with an error """ check_raiden_environment(network_id, config.environment_type) deployed_contracts_data: Dict[str, Any] = dict() contracts_version = RAIDEN_CONTRACT_VERSION config.contracts_path = contracts_precompiled_path(contracts_version) if network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[network_id] != "smoketest": deployment_data = get_contracts_deployment_info( chain_id=network_id, version=contracts_version ) if not deployment_data: return deployed_contracts_data deployed_contracts_data = deployment_data["contracts"] return deployed_contracts_data
def test_deploy_data_not_deployed() -> None: assert ( get_contracts_deployment_info(ChainID(1), "0.8.0", module=DeploymentModule.RAIDEN) is None )
def test_service_deploy_data_for_redeyes_fail(chain_id: ChainID) -> None: """get_contracts_deployment_info() on RedEyes version should return a non-empty dictionary""" with pytest.raises(ValueError): assert get_contracts_deployment_info(chain_id, "0.4.0", DeploymentModule.SERVICES)
def test_deploy_data_for_alderaan_exist(chain_id: ChainID) -> None: """get_contracts_deployment_info() on Alderaan version should have data""" assert get_contracts_deployment_info(chain_id, ALDERAAN_VERSION) assert get_contracts_deployment_info(chain_id, ALDERAAN_VERSION, DeploymentModule.SERVICES)
def test_deploy_data_for_redeyes_succeed(chain_id: ChainID) -> None: """get_contracts_deployment_info() on RedEyes version should return a non-empty dictionary""" assert get_contracts_deployment_info(chain_id, "0.4.0")