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")
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"]), )
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"]), )
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"]), )
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']))
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"])
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']
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)
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))
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
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))
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))
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)
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
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)
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))
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"]))
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)
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
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." )
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.")
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
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