def test_correct_issue_amount_fee_less_than_0(self):
        icx_issue_amount = 1000
        prev_block_cumulative_fee = -1000
        over_issued_i_score = 0

        with pytest.raises(AssertionError):
            Regulator._correct_issue_amount(over_issued_i_score,
                                            icx_issue_amount,
                                            prev_block_cumulative_fee)
    def test_set_corrected_issue_data_end_of_period(self,
                                                    mocked_context_storage,
                                                    mocked_context_engine):
        # create dummy block
        block_height = 5
        block = self._create_dummy_block_by_height(block_height)
        self.context.block = block

        # set regulator_variable
        over_issued_i_score = 0
        current_calc_preiod_issued_icx = 50_000
        prev_calc_period_issued_icx = 5_000
        rv = RegulatorVariable(current_calc_preiod_issued_icx,
                               prev_calc_period_issued_icx,
                               over_issued_i_score)
        cumulative_fee = 0
        issue_amount = 10_000
        mocked_context_storage.icx.last_block.cumulative_fee = cumulative_fee
        mocked_context_engine.prep.term.sequence = 0
        mocked_context_storage.rc.get_calc_response_from_rc = Mock(
            return_value=(0, 0, None))
        mocked_context_storage.iiss.get_end_block_height_of_calc = Mock(
            return_value=block_height)
        mocked_context_storage.issue.get_regulator_variable = Mock(
            return_value=rv)
        regulator = Regulator(self.context, issue_amount)

        actual_current_icx = regulator._regulator_variable.current_calc_period_issued_icx
        actual_prev_icx = regulator._regulator_variable.prev_calc_period_issued_icx
        assert actual_current_icx == 0
        assert actual_prev_icx == issue_amount + current_calc_preiod_issued_icx
    def test_correct_issue_amount_on_calc_period_prev_icx_is_less_than_prev_i_score_additional_issuing(
            self):
        # success case: when need additional issuing
        prev_calc_period_issued_icx = 9_000
        prev_calc_period_issued_iscore = 10_000_325

        icx_issue_amount = 2_000
        over_issued_i_score = 100_321
        prev_block_cumulative_fee = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount_on_calc_period(prev_calc_period_issued_icx,
                                                           prev_calc_period_issued_iscore,
                                                           over_issued_i_score,
                                                           icx_issue_amount,
                                                           prev_block_cumulative_fee)

        expected_diff_without_fee = prev_calc_period_issued_icx * ISCORE_EXCHANGE_RATE - prev_calc_period_issued_iscore \
                                    + over_issued_i_score
        expected_covered_by_remain = -(expected_diff_without_fee //
                                       -ISCORE_EXCHANGE_RATE)
        assert covered_icx_by_fee == prev_block_cumulative_fee
        assert covered_icx_by_remain == expected_covered_by_remain
        assert corrected_icx_issue_amount == icx_issue_amount + (
            -expected_covered_by_remain)
        assert remain_over_issued_iscore == expected_diff_without_fee % -ISCORE_EXCHANGE_RATE
    def test_correct_issue_amount_on_calc_period_prev_icx_is_less_than_prev_i_score(
            self):
        # success case: when remain over issued icx overwhelm additional issuing amount.
        prev_calc_period_issued_icx = 9_000
        prev_calc_period_issued_iscore = 10_000_325

        icx_issue_amount = 2_000
        over_issued_i_score = 5_000_321
        prev_block_cumulative_fee = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount_on_calc_period(prev_calc_period_issued_icx,
                                                           prev_calc_period_issued_iscore,
                                                           over_issued_i_score,
                                                           icx_issue_amount,
                                                           prev_block_cumulative_fee)

        expected_diff_without_fee = prev_calc_period_issued_icx * ISCORE_EXCHANGE_RATE - prev_calc_period_issued_iscore \
                                    + over_issued_i_score

        assert covered_icx_by_remain == icx_issue_amount
        assert covered_icx_by_fee == prev_block_cumulative_fee
        assert corrected_icx_issue_amount == 0
        assert remain_over_issued_iscore == expected_diff_without_fee - (
            icx_issue_amount * ISCORE_EXCHANGE_RATE)
    def test_correct_issue_amount_on_calc_period_when_first_calc_period(self):
        # success case: when prev issued i score and prev issued icx data is zero, should return below
        #   covered_by_fee = 0
        #   covered_by_remain = 0
        #   remain_over_issued_icx = 0
        #   corrected_icx_issue_amount = icx_issue_amount

        icx_issue_amount = 1000
        over_issued_i_score = 0
        prev_block_cumulative_fee = 0
        prev_calc_period_issued_icx = 0
        prev_calc_period_issued_iscore = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount_on_calc_period(prev_calc_period_issued_icx,
                                                           prev_calc_period_issued_iscore,
                                                           over_issued_i_score,
                                                           icx_issue_amount,
                                                           prev_block_cumulative_fee)

        assert remain_over_issued_iscore == 0

        assert covered_icx_by_remain == 0
        assert covered_icx_by_fee == 0
        assert corrected_icx_issue_amount == icx_issue_amount
    def test_correct_issue_amount_on_calc_period_prev_icx_is_more_than_prev_i_score(
            self):
        # success case: when remain over issued icx + prev calc over issued icx < icx_issue amount
        # fee is excluded (i.e. set to zero) as tested before
        prev_calc_period_issued_icx = 10_000
        prev_calc_period_issued_iscore = 9_000_325
        over_issued_i_score = 500_400
        icx_issue_amount = 2_000
        prev_block_cumulative_fee = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount_on_calc_period(prev_calc_period_issued_icx,
                                                           prev_calc_period_issued_iscore,
                                                           over_issued_i_score,
                                                           icx_issue_amount,
                                                           prev_block_cumulative_fee)

        expected_diff_without_fee = prev_calc_period_issued_icx * ISCORE_EXCHANGE_RATE - prev_calc_period_issued_iscore \
                        + over_issued_i_score
        expected_covered_by_remain = (expected_diff_without_fee //
                                      ISCORE_EXCHANGE_RATE)

        assert covered_icx_by_fee == prev_block_cumulative_fee
        assert covered_icx_by_remain == expected_covered_by_remain
        assert corrected_icx_issue_amount == icx_issue_amount - expected_covered_by_remain - prev_block_cumulative_fee
        assert remain_over_issued_iscore == expected_diff_without_fee - expected_covered_by_remain * ISCORE_EXCHANGE_RATE

        # success case: when remain over issued icx + prev calc over issued icx > icx_issue amount
        over_issued_i_score = 5_000_300
        icx_issue_amount = 1_000
        prev_block_cumulative_fee = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount_on_calc_period(prev_calc_period_issued_icx,
                                                           prev_calc_period_issued_iscore,
                                                           over_issued_i_score,
                                                           icx_issue_amount,
                                                           prev_block_cumulative_fee)

        expected_diff_without_fee = prev_calc_period_issued_icx * ISCORE_EXCHANGE_RATE - prev_calc_period_issued_iscore \
                                    + over_issued_i_score

        assert covered_icx_by_fee == prev_block_cumulative_fee
        assert covered_icx_by_remain == icx_issue_amount
        assert corrected_icx_issue_amount == 0
        assert remain_over_issued_iscore == expected_diff_without_fee - covered_icx_by_remain * ISCORE_EXCHANGE_RATE
    def test_correct_issue_amount_over_issued_icx_is_0(self):
        icx_issue_amount = 1_000
        prev_block_cumulative_fee = 0
        over_issued_i_score = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount(over_issued_i_score, icx_issue_amount, prev_block_cumulative_fee)

        assert remain_over_issued_iscore == 0
        assert covered_icx_by_fee == 0
        assert covered_icx_by_remain == 0
        assert corrected_icx_issue_amount == icx_issue_amount
    def test_correct_issue_amount_over_issued_icx_is_more_then_icx_issue_amount(
            self):
        icx_issue_amount = 1_000
        over_issued_i_score = 10_000 * ISCORE_EXCHANGE_RATE
        prev_block_cumulative_fee = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount(over_issued_i_score, icx_issue_amount, prev_block_cumulative_fee)

        assert remain_over_issued_iscore == over_issued_i_score - icx_issue_amount * ISCORE_EXCHANGE_RATE + \
               (prev_block_cumulative_fee * ISCORE_EXCHANGE_RATE)
        assert covered_icx_by_fee == 0
        assert covered_icx_by_remain == icx_issue_amount
        assert corrected_icx_issue_amount == 0
    def test_correct_issue_amount_over_issued_icx_is_more_than_0_and_icx_issue_amount_is_0(
            self):
        icx_issue_amount = 0
        prev_block_cumulative_fee = 0
        over_issued_i_score = 1_000 * ISCORE_EXCHANGE_RATE
        over_issued_icx = over_issued_i_score // ISCORE_EXCHANGE_RATE

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount(over_issued_i_score, icx_issue_amount, prev_block_cumulative_fee)

        assert remain_over_issued_iscore == over_issued_icx * ISCORE_EXCHANGE_RATE + (
            prev_block_cumulative_fee * ISCORE_EXCHANGE_RATE)
        assert covered_icx_by_fee == 0
        assert covered_icx_by_remain == 0
        assert corrected_icx_issue_amount == 0
    def test_correct_issue_amount_on_calc_period_prev_icx_and_prev_i_score_is_same(
            self):
        # success case: when need additional issuing
        prev_calc_period_issued_icx = 10_000
        prev_calc_period_issued_iscore = 10_000_000

        icx_issue_amount = 0
        over_issued_i_score = 0
        prev_block_cumulative_fee = 0

        covered_icx_by_fee, covered_icx_by_remain, remain_over_issued_iscore, corrected_icx_issue_amount = \
            Regulator._correct_issue_amount_on_calc_period(prev_calc_period_issued_icx,
                                                           prev_calc_period_issued_iscore,
                                                           over_issued_i_score,
                                                           icx_issue_amount,
                                                           prev_block_cumulative_fee)

        assert covered_icx_by_remain == 0
        assert covered_icx_by_fee == 0
        assert corrected_icx_issue_amount == icx_issue_amount
        assert remain_over_issued_iscore == 0
    def test_set_negative_value_to_prev_calc_preiod_issued_icx(
            self, mocked_context_storage, mocked_context_engine):
        # success case: if 'prev_calc_preiod_issued_icx' is -1, should not regulate ICX even though
        # prev_calc_preiod_issued_iscore is exists

        # create dummy block
        block_height = 5
        block = self._create_dummy_block_by_height(block_height)
        self.context.block = block

        # set regulator_variable
        over_issued_i_score = 0
        current_calc_preiod_issued_icx = 50_000_000
        prev_calc_period_issued_icx = -1
        prev_calc_period_issued_iscore = 50_000_000_000_000
        rv = RegulatorVariable(current_calc_preiod_issued_icx,
                               prev_calc_period_issued_icx,
                               over_issued_i_score)
        cumulative_fee = 0
        issue_amount = 10_000_000

        mocked_context_storage.icx.last_block.cumulative_fee = cumulative_fee
        mocked_context_engine.prep.term.sequence = 0
        mocked_context_storage.rc.get_calc_response_from_rc = Mock(
            return_value=(prev_calc_period_issued_iscore, 0, None))
        mocked_context_storage.iiss.get_end_block_height_of_calc = Mock(
            return_value=block_height)
        mocked_context_storage.issue.get_regulator_variable = Mock(
            return_value=rv)
        regulator = Regulator(self.context, issue_amount)

        assert regulator._regulator_variable.prev_calc_period_issued_icx == issue_amount + current_calc_preiod_issued_icx
        assert regulator._regulator_variable.current_calc_period_issued_icx == 0
        assert regulator._regulator_variable.over_issued_iscore == 0
        assert regulator.corrected_icx_issue_amount == issue_amount
        assert regulator.covered_icx_by_over_issue == 0
    def test_reflect_difference_in_issuing(self):
        # success case: when input negative over_issued_icx, should return below
        #   covered_by_fee = cumulative_fee
        #   covered_by_remain = over_issued_icx (i.e. additional issue amount)
        #   remain_over_issued_icx = 0 if cumulative_fee over 1000, cumulative_fee - 1000
        #   icx_issue_amount = icx_issue_amount - over_issued_icx - cumulative_fee
        icx_issue_amount = 1_000
        over_issued_icx = -1_000

        max_covered_by_fee = icx_issue_amount - over_issued_icx
        for cumulative_fee in range(0, 2005):
            actual_covered_by_fee, actual_covered_by_remain, actual_remain_over_issued_icx, actual_corrected_icx_issue_amount = \
                Regulator._reflect_difference_in_issuing(icx_issue_amount,
                                                         over_issued_icx,
                                                         cumulative_fee)
            expected_cumulative_fee = 0 if cumulative_fee <= max_covered_by_fee else cumulative_fee - max_covered_by_fee
            assert actual_covered_by_fee == cumulative_fee if cumulative_fee <= max_covered_by_fee else max_covered_by_fee
            assert actual_covered_by_remain == over_issued_icx
            assert actual_remain_over_issued_icx == expected_cumulative_fee
            assert actual_corrected_icx_issue_amount == icx_issue_amount - over_issued_icx - cumulative_fee \
                if cumulative_fee <= max_covered_by_fee else max_covered_by_fee

        # success case: when over_issued_icx is more than icx_issue_amount, should return below
        #   covered_by_fee = 0
        #   covered_by_remain = icx_issue_amount (as all icx_issue amount is used to deduct over issued icx)
        #   remain_over_issued_icx = abs(corrected_icx_issue_amount) + cumulative_fee
        #   icx_issue_amount = 0
        icx_issue_amount = 1_000
        over_issued_icx = 10_000

        for cumulative_fee in range(0, 2000):
            actual_covered_by_fee, actual_covered_by_remain, actual_remain_over_issued_icx, actual_corrected_icx_issue_amount = \
                Regulator._reflect_difference_in_issuing(icx_issue_amount,
                                                         over_issued_icx,
                                                         cumulative_fee)
            assert actual_covered_by_fee == 0
            assert actual_covered_by_remain == icx_issue_amount
            assert actual_remain_over_issued_icx == abs(
                icx_issue_amount - over_issued_icx) + cumulative_fee
            assert actual_corrected_icx_issue_amount == 0

        # success case: when over_issued_icx is more than icx_issue_amount, should return below
        #   covered_by_fee = cumulative_fee if cumulative fee is under 1_000, if over, 1000
        #   covered_by_remain = over_issued_icx (as all over issued icx is deducted from the icx_issue_amount)
        #   remain_over_issued_icx = 0 (as all over issued icx is deducted)
        #   icx_issue_amount = icx_issue_amount - over_issued_icx
        icx_issue_amount = 2_000
        over_issued_icx = 1_000
        max_covered_by_fee = icx_issue_amount - over_issued_icx
        for cumulative_fee in range(0, 1005):
            actual_covered_by_fee, actual_covered_by_remain, actual_remain_over_issued_icx, actual_corrected_icx_issue_amount = \
                Regulator._reflect_difference_in_issuing(icx_issue_amount,
                                                         over_issued_icx,
                                                         cumulative_fee)
            assert actual_covered_by_fee == cumulative_fee \
                if cumulative_fee <= max_covered_by_fee else max_covered_by_fee
            assert actual_covered_by_remain == over_issued_icx
            assert actual_remain_over_issued_icx == 0 \
                if cumulative_fee <= max_covered_by_fee else cumulative_fee - max_covered_by_fee
            assert actual_corrected_icx_issue_amount == icx_issue_amount - over_issued_icx - cumulative_fee \
                if cumulative_fee <= max_covered_by_fee else max_covered_by_fee

        # success case: when input 0, should return below
        #   covered_by_fee = 0
        #   covered_by_remain = 0
        #   remain_over_issued_icx = cumulative_fee
        #   icx_issue_amount = 0
        icx_issue_amount = 0
        over_issued_icx = 0
        for cumulative_fee in range(0, 1005):
            actual_covered_by_fee, actual_covered_by_remain, actual_remain_over_issued_icx, actual_corrected_icx_issue_amount = \
                Regulator._reflect_difference_in_issuing(icx_issue_amount,
                                                         over_issued_icx,
                                                         cumulative_fee)

            assert actual_covered_by_fee == 0
            assert actual_covered_by_remain == 0
            assert actual_remain_over_issued_icx == cumulative_fee
            assert actual_corrected_icx_issue_amount == 0