def enable_claiming(general_config: GroupGeneralConfig, worklock_options: WorkLockOptions, force: bool, hw_wallet: bool, gas_limit: int): """Ensure correctness of WorkLock participants and enable allocation""" emitter, registry, blockchain = worklock_options.setup(general_config=general_config) bidder_address = worklock_options.get_bidder_address(emitter, registry) bidder = worklock_options.create_bidder(registry=registry, hw_wallet=hw_wallet) whales = bidder.get_whales() if whales: headers = ("Participants that require correction", "Current bonus") columns = (whales.keys(), map(prettify_eth_amount, whales.values())) emitter.echo(tabulate.tabulate(dict(zip(headers, columns)), headers=headers, floatfmt="fancy_grid")) if not force: click.confirm(f"Confirm force refund to at least {len(whales)} participants using {bidder_address}?", abort=True) force_refund_receipt = bidder.force_refund() emitter.echo(WHALE_WARNING.format(number=len(whales)), color='green') paint_receipt_summary(receipt=force_refund_receipt, emitter=emitter, chain_name=bidder.staking_agent.blockchain.client.chain_name, transaction_type=f"force-refund") else: emitter.echo(BIDS_VALID_NO_FORCE_REFUND_INDICATED, color='yellow') if not bidder.worklock_agent.bidders_checked(): confirmation = gas_limit and force while not confirmation: if not gas_limit: min_gas = 180000 gas_limit = click.prompt(PROMPT_BID_VERIFY_GAS_LIMIT.format(min_gas=min_gas), type=click.IntRange(min=min_gas)) bidders_per_transaction = bidder.worklock_agent.estimate_verifying_correctness(gas_limit=gas_limit) if not force: message = CONFIRM_BID_VERIFICATION.format(bidder_address=bidder_address, gas_limit=gas_limit, bidders_per_transaction=bidders_per_transaction) confirmation = click.confirm(message) gas_limit = gas_limit if confirmation else None else: emitter.echo(VERIFICATION_ESTIMATES.format(gas_limit=gas_limit, bidders_per_transaction=bidders_per_transaction)) confirmation = True verification_receipts = bidder.verify_bidding_correctness(gas_limit=gas_limit) emitter.echo(COMPLETED_BID_VERIFICATION, color='green') for iteration, receipt in verification_receipts.items(): paint_receipt_summary(receipt=receipt, emitter=emitter, chain_name=bidder.staking_agent.blockchain.client.chain_name, transaction_type=f"verify-correctness[{iteration}]") else: emitter.echo(BIDDERS_ALREADY_VERIFIED, color='yellow')
def test_enable_claiming(click_runner, mocker, mock_worklock_agent, surrogate_bidder, token_economics, mock_testerchain): # Spy on the corresponding CLI function we are testing mock_force_refund = mocker.spy(Bidder, 'force_refund') mock_verify = mocker.spy(Bidder, 'verify_bidding_correctness') mock_get_whales = mocker.spy(Bidder, 'get_whales') # Cancellation window is closed now = mock_testerchain.get_blocktime() sometime_later = now+(3600*30) mocker.patch.object(BlockchainInterface, 'get_blocktime', return_value=sometime_later) # Prepare bidders bidders = mock_testerchain.client.accounts[0:10] num_bidders = len(bidders) bonus_lot_value = token_economics.worklock_supply - token_economics.minimum_allowed_locked * num_bidders bids_before = [to_wei(50_000, 'ether')] min_bid_eth_value = to_wei(1, 'ether') max_bid_eth_value = to_wei(10, 'ether') for i in range(num_bidders - 1): bids_before.append(random.randrange(min_bid_eth_value, max_bid_eth_value)) bonus_eth_supply_before = sum(bids_before) - token_economics.worklock_min_allowed_bid * num_bidders bids_after = [min_bid_eth_value] * num_bidders bonus_eth_supply_after = 0 min_bid = min(bids_before) bidder_to_exclude = bids_before.index(min_bid) bidders_to_check = bidders.copy() del bidders_to_check[bidder_to_exclude] mock_worklock_agent.get_bonus_eth_supply.side_effect = [bonus_eth_supply_before, bonus_eth_supply_after, bonus_eth_supply_after] mock_worklock_agent.get_bonus_lot_value.return_value = bonus_lot_value mock_worklock_agent.get_bidders.return_value = bidders mock_worklock_agent.get_deposited_eth.side_effect = [*bids_before, *bids_after, *bids_after] mock_worklock_agent.bidders_checked.side_effect = [False, False, False, False, True] mock_worklock_agent.next_bidder_to_check.side_effect = [0, num_bidders // 2, num_bidders] mock_worklock_agent.estimate_verifying_correctness.side_effect = [3, 6] command = ('enable-claiming', '--participant-address', surrogate_bidder.checksum_address, '--provider', MOCK_PROVIDER_URI, '--signer', MOCK_PROVIDER_URI, '--network', TEMPORARY_DOMAIN) gas_limit_1 = 200000 gas_limit_2 = 300000 user_input = '\n'.join((INSECURE_DEVELOPMENT_PASSWORD, YES, str(gas_limit_1), NO, str(gas_limit_2), YES)) result = click_runner.invoke(worklock, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 confirmation = CONFIRM_BID_VERIFICATION.format(bidder_address=surrogate_bidder.checksum_address, gas_limit=gas_limit_1, bidders_per_transaction=3) assert confirmation in result.output confirmation = CONFIRM_BID_VERIFICATION.format(bidder_address=surrogate_bidder.checksum_address, gas_limit=gas_limit_2, bidders_per_transaction=6) assert confirmation in result.output # Bidder mock_force_refund.assert_called_once() mock_verify.assert_called_once() mock_get_whales.assert_called() assert_successful_transaction_echo(bidder_address=surrogate_bidder.checksum_address, cli_output=result.output) # Manual checking of force_refund tx because of unpredictable order of actual bidders_to_check array transaction_executions = mock_worklock_agent.force_refund.call_args_list assert len(transaction_executions) == 1 _agent_args, agent_kwargs = transaction_executions[0] checksum_address, addresses = agent_kwargs.values() assert checksum_address == surrogate_bidder.checksum_address assert sorted(addresses) == sorted(bidders_to_check) mock_worklock_agent.verify_bidding_correctness.assert_has_calls([ call(checksum_address=surrogate_bidder.checksum_address, gas_limit=gas_limit_2), call(checksum_address=surrogate_bidder.checksum_address, gas_limit=gas_limit_2) ]) mock_worklock_agent.assert_only_transactions([mock_worklock_agent.force_refund, mock_worklock_agent.verify_bidding_correctness]) # Calls mock_worklock_agent.estimate_verifying_correctness.assert_has_calls([ call(gas_limit=gas_limit_1), call(gas_limit=gas_limit_2) ]) mock_worklock_agent.get_bidders.assert_called() mock_worklock_agent.get_bonus_lot_value.assert_called() mock_worklock_agent.get_bonus_eth_supply.assert_called() mock_worklock_agent.next_bidder_to_check.assert_called() mock_worklock_agent.get_deposited_eth.assert_called()