示例#1
0
def test_mfee3():
    """ Unit test for the fee calculation in the mfee3_only_imbalance_fees scenario """
    amount = 500_000_000_000_000_000
    deposit = TokenAmount(1_000_000_000_000_000_000)
    imbalance_penalty = calculate_imbalance_fees(deposit, ProportionalFeeAmount(10_000))
    fee_schedule = FeeScheduleState(imbalance_penalty=imbalance_penalty, cap_fees=False)
    channels = make_channel_pair(fee_schedule, deposit)

    # How much do we need to send so that the target receives `amount`? PFS-like calculation.
    fee_calculation = get_initial_amount_for_amount_after_fees(
        amount_after_fees=PaymentAmount(amount), channels=[channels]
    )
    assert fee_calculation
    amount_with_margin = calculate_safe_amount_with_fee(
        fee_calculation.amount_without_fees, FeeAmount(sum(fee_calculation.mediation_fees))
    )
    assert amount_with_margin == 480_850_038_799_922_400

    # print values for scenario
    print("{:_} {:_}".format(deposit - amount_with_margin, amount_with_margin))
    for med_fee in running_sum(fee_calculation.mediation_fees):
        print(
            "{:_} {:_}".format(
                deposit - amount_with_margin + med_fee, amount_with_margin - med_fee
            )
        )
示例#2
0
def test_mfee4():
    """ Unit test for the fee calculation in the mfee4_combined_fees scenario """
    amount = PaymentAmount(500_000_000_000_000_000)
    deposit = 1_000_000_000_000_000_000
    prop_fee = ppm_fee_per_channel(ProportionalFeeAmount(10_000))
    imbalance_penalty = calculate_imbalance_fees(
        TokenAmount(deposit * 2), ProportionalFeeAmount(20_000)
    )
    fee_schedule = FeeScheduleState(
        flat=FeeAmount(100 // 2),
        proportional=prop_fee,
        imbalance_penalty=imbalance_penalty,
        cap_fees=False,
    )
    channels = make_channel_pair(fee_schedule, deposit, deposit)

    # How much do we need to send so that the target receives `amount`? PFS-like calculation.
    fee_calculation = get_initial_amount_for_amount_after_fees(
        amount_after_fees=PaymentAmount(amount), channels=[channels, channels]
    )
    assert fee_calculation

    amount_with_margin = calculate_safe_amount_with_fee(
        amount, FeeAmount(sum(fee_calculation.mediation_fees))
    )

    # Calculate mediation fees for both mediators
    med_fees = []
    incoming_amount = amount_with_margin
    for _ in range(2):
        outgoing_amount = get_amount_without_fees(
            amount_with_fees=incoming_amount, channel_in=channels[0], channel_out=channels[1]
        )
        assert outgoing_amount
        med_fees.append(incoming_amount - outgoing_amount)
        incoming_amount = outgoing_amount

    assert amount_with_margin == 543_503_066_141_505_551

    # print values for scenario
    print("{:_} {:_}".format(deposit - amount_with_margin, deposit + amount_with_margin))
    for med_fee in running_sum(med_fees):
        print(
            "{:_} {:_}".format(
                deposit - amount_with_margin + med_fee, deposit + amount_with_margin - med_fee
            )
        )
示例#3
0
def test_get_initial_payment_for_final_target_amount(
    flat_fee: FeeAmount,
    prop_fee: ProportionalFeeAmount,
    balance: TokenAmount,
    final_amount: PaymentAmount,
    initial_amount: PaymentWithFeeAmount,
    expected_fees: List[FeeAmount],
):
    prop_fee = ppm_fee_per_channel(prop_fee)
    channel_set = make_channel_set([
        NettingChannelStateProperties(
            canonical_identifier=factories.create(
                CanonicalIdentifierProperties(
                    channel_identifier=ChannelID(1))),
            our_state=NettingChannelEndStateProperties(balance=TokenAmount(0)),
            partner_state=NettingChannelEndStateProperties(balance=balance),
            fee_schedule=FeeScheduleState(flat=flat_fee,
                                          proportional=prop_fee),
        ),
        NettingChannelStateProperties(
            canonical_identifier=factories.create(
                CanonicalIdentifierProperties(
                    channel_identifier=ChannelID(2))),
            our_state=NettingChannelEndStateProperties(balance=balance),
            partner_state=NettingChannelEndStateProperties(
                balance=TokenAmount(0)),
            fee_schedule=FeeScheduleState(flat=flat_fee,
                                          proportional=prop_fee),
        ),
    ])

    calculation = get_initial_amount_for_amount_after_fees(
        amount_after_fees=final_amount,
        channels=[(channel_set.channels[0], channel_set.channels[1])],
    )

    assert calculation is not None
    assert calculation.total_amount == initial_amount
    assert calculation.mediation_fees == expected_fees
示例#4
0
def test_mfee2():
    """ Unit test for the fee calculation in the mfee2_proportional_fees scenario """
    amount = 10_000
    deposit = 100_000
    prop_fee = ppm_fee_per_channel(ProportionalFeeAmount(10_000))
    fee_schedule = FeeScheduleState(proportional=ProportionalFeeAmount(prop_fee))
    channels = make_channel_pair(fee_schedule, deposit)

    # How much do we need to send so that the target receives `amount`? PFS-like calculation.
    fee_calculation = get_initial_amount_for_amount_after_fees(
        amount_after_fees=PaymentAmount(amount), channels=[channels, channels]
    )
    assert fee_calculation
    amount_with_margin = calculate_safe_amount_with_fee(
        fee_calculation.amount_without_fees, FeeAmount(sum(fee_calculation.mediation_fees))
    )
    assert amount_with_margin == 10_213

    # print values for scenario
    print(deposit - amount_with_margin, amount_with_margin)
    for med_fee in running_sum(fee_calculation.mediation_fees):
        print(deposit - amount_with_margin + med_fee, amount_with_margin - med_fee)
示例#5
0
def test_fee_round_trip(flat_fee, prop_fee, imbalance_fee, amount, balance1, balance2):
    """Tests mediation fee deduction.

    First we're doing a PFS-like calculation going backwards from the target
    amount to get the amount that the initiator has to send. Then we calculate
    the fees from a mediator's point of view and check if `amount_with_fees -
    fees = amount`.
    """
    # Find examples where there is a reasonable chance of succeeding
    amount = int(min(amount, balance1 * 0.95 - 1, balance2 * 0.95 - 1))
    assume(amount > 0)

    total_balance = TokenAmount(100_000_000_000_000_000_000)
    prop_fee_per_channel = ppm_fee_per_channel(ProportionalFeeAmount(prop_fee))
    imbalance_fee = calculate_imbalance_fees(
        channel_capacity=total_balance,
        proportional_imbalance_fee=ProportionalFeeAmount(imbalance_fee),
    )
    channel_in = factories.create(
        NettingChannelStateProperties(
            our_state=NettingChannelEndStateProperties(balance=total_balance - balance1),
            partner_state=NettingChannelEndStateProperties(balance=balance1),
            fee_schedule=FeeScheduleState(
                cap_fees=False,
                flat=FeeAmount(flat_fee),
                proportional=prop_fee_per_channel,
                imbalance_penalty=imbalance_fee,
            ),
        )
    )
    channel_out = factories.create(
        NettingChannelStateProperties(
            our_state=NettingChannelEndStateProperties(balance=balance2),
            partner_state=NettingChannelEndStateProperties(balance=total_balance - balance2),
            fee_schedule=FeeScheduleState(
                cap_fees=False,
                flat=FeeAmount(flat_fee),
                proportional=prop_fee_per_channel,
                imbalance_penalty=imbalance_fee,
            ),
        )
    )

    # How much do we need to send so that the target receives `amount`? PFS-like calculation.
    fee_calculation = get_initial_amount_for_amount_after_fees(
        amount_after_fees=PaymentAmount(amount), channels=[(channel_in, channel_out)]
    )
    assume(fee_calculation)  # There is not enough capacity for the payment in all cases
    assert fee_calculation

    # How much would a mediator send to the target? Ideally exactly `amount`.
    amount_without_margin_after_fees = get_amount_without_fees(
        amount_with_fees=fee_calculation.total_amount,
        channel_in=channel_in,
        channel_out=channel_out,
    )
    assume(amount_without_margin_after_fees)  # We might lack capacity for the payment
    assert abs(amount - amount_without_margin_after_fees) <= 1  # Equal except for rounding errors

    # If we add the fee margin, the mediator must always send at least `amount` to the target!
    amount_with_fee_and_margin = calculate_safe_amount_with_fee(
        fee_calculation.amount_without_fees, FeeAmount(sum(fee_calculation.mediation_fees))
    )
    amount_with_margin_after_fees = get_amount_without_fees(
        amount_with_fees=amount_with_fee_and_margin, channel_in=channel_in, channel_out=channel_out
    )
    assume(amount_with_margin_after_fees)  # We might lack capacity to add margins
    assert amount_with_margin_after_fees >= amount