コード例 #1
0
def test_exact_economics():
    """
    Formula for staking in one period:
    (totalSupply - currentSupply) * (lockedValue / totalLockedValue) * (k1 + allLockedPeriods) / d / k2

    d - Coefficient which modifies the rate at which the maximum issuance decays
    k1 - Numerator of the locking duration coefficient
    k2 - Denominator of the locking duration coefficient

    if allLockedPeriods > awarded_periods then allLockedPeriods = awarded_periods
    kappa * log(2) / halving_delay === (k1 + allLockedPeriods) / d / k2

    kappa = small_stake_multiplier + (1 - small_stake_multiplier) * min(T, T1) / T1
    where allLockedPeriods == min(T, T1)
    """

    #
    # Expected Output
    #

    # Supply
    expected_total_supply = 3885390081748248632541961138
    expected_supply_ratio = Decimal('3.885390081748248632541961138')
    expected_initial_supply = 1000000000000000000000000000
    expected_phase1_supply = 1829579800000000000000000000

    # Reward
    expected_reward_supply = 2885390081748248632541961138
    reward_saturation = 1

    # Staking 2 phase
    decay_half_life = 2
    multiplier = 0.5
    expected_lock_duration_coefficient_1 = 365
    expected_lock_duration_coefficient_2 = 2 * expected_lock_duration_coefficient_1
    expected_phase2_coefficient = 1053
    expected_minting_coefficient = expected_phase2_coefficient * expected_lock_duration_coefficient_2

    assert expected_lock_duration_coefficient_1 * decay_half_life == round(
        expected_minting_coefficient * log(2) * multiplier / 365)

    #
    # Sanity
    #

    # Sanity check ratio accuracy
    expected_scaled_ratio = str(expected_supply_ratio).replace('.', '')
    assert str(expected_total_supply) == expected_scaled_ratio

    # Sanity check denomination size
    expected_scale = 28
    assert len(str(expected_total_supply)) == expected_scale
    assert len(str(expected_initial_supply)) == expected_scale
    assert len(str(expected_reward_supply)) == expected_scale

    # Use same precision as economics class
    with localcontext() as ctx:
        ctx.prec = StandardTokenEconomics._precision

        # Sanity check expected testing outputs
        assert Decimal(expected_total_supply
                       ) / expected_initial_supply == expected_supply_ratio
        assert expected_reward_supply == expected_total_supply - expected_initial_supply
        assert reward_saturation * 365 * multiplier == expected_lock_duration_coefficient_1 * (
            1 - multiplier)
        assert int(365 ** 2 * reward_saturation * decay_half_life / log(2) / (1-multiplier) / expected_lock_duration_coefficient_2) == \
            expected_phase2_coefficient

    # After sanity checking, assemble expected test deployment parameters
    expected_deployment_parameters = (
        24,  # Hours in single period
        1053,  # Coefficient which modifies the rate at which the maximum issuance decays (d)
        365,  # Numerator of the locking duration coefficient (k1)
        730,  # Denominator of the locking duration coefficient (k2)
        365,  # Max periods that will be additionally rewarded (awarded_periods)
        2829579800000000000000000000,  # Total supply for the first phase
        1002509479452054794520547,  # Max possible reward for one period for all stakers in the first phase
        30,  # Min amount of periods during which tokens can be locked
        15000000000000000000000,  # min locked NuNits
        30000000000000000000000000,  # max locked NuNits
        2)  # Min worker periods
    #
    # Token Economics
    #

    # Check creation
    e = StandardTokenEconomics()

    with localcontext() as ctx:
        ctx.prec = StandardTokenEconomics._precision

        # Check that total_supply calculated correctly
        assert Decimal(
            e.erc20_total_supply) / e.initial_supply == expected_supply_ratio
        assert e.erc20_total_supply == expected_total_supply

        # Check reward rates for the second phase
        initial_rate = (e.erc20_total_supply - int(e.first_phase_total_supply)) * (e.lock_duration_coefficient_1 + 365) / \
                       (e.issuance_decay_coefficient * e.lock_duration_coefficient_2)
        assert int(initial_rate) == int(e.first_phase_max_issuance)
        assert Decimal(LOG2 / (e.token_halving * 365) *
                       (e.erc20_total_supply -
                        int(e.first_phase_total_supply))) == initial_rate

        initial_rate_small = (e.erc20_total_supply - int(e.first_phase_total_supply)) * e.lock_duration_coefficient_1 / \
                             (e.issuance_decay_coefficient * e.lock_duration_coefficient_2)
        assert int(initial_rate_small) == int(initial_rate / 2)

        # Check reward supply
        assert e.reward_supply == expected_total_supply - expected_initial_supply

        # Check deployment parameters
        assert e.staking_deployment_parameters == expected_deployment_parameters
        assert e.erc20_initial_supply == expected_initial_supply
        assert e.erc20_reward_supply == expected_reward_supply

        # Additional checks on supply
        assert e.token_supply_at_period(period=0) == expected_initial_supply
        assert e.cumulative_rewards_at_period(0) == 0

        # Check phase 1 doesn't overshoot
        switch_period = 5 * 365
        assert e.first_phase_final_period() == switch_period
        assert e.token_supply_at_period(
            period=switch_period
        ) == expected_phase1_supply + expected_initial_supply
        assert e.token_supply_at_period(
            period=switch_period) < e.token_supply_at_period(
                period=switch_period + 1)

        assert e.rewards_during_period(period=1) == round(
            e.first_phase_max_issuance)
        assert e.rewards_during_period(period=switch_period) == round(
            e.first_phase_max_issuance)
        assert e.rewards_during_period(period=switch_period + 1) < int(
            e.first_phase_max_issuance)

        # Last NuNit is minted after 188 years (or 68500 periods).
        # That's the year 2208, if token is launched in 2020.
        # 23rd century schizoid man!
        assert expected_total_supply == e.token_supply_at_period(period=68500)

        # After 1 year:
        assert 1_365_915_960_000000000000000000 == e.token_supply_at_period(
            period=365)
        assert 365_915_960_000000000000000000 == e.cumulative_rewards_at_period(
            period=365)
        assert e.erc20_initial_supply + e.cumulative_rewards_at_period(
            365) == e.token_supply_at_period(period=365)

        # Checking that the supply function is monotonic in phase 1
        todays_supply = e.token_supply_at_period(period=0)
        for t in range(68500):
            tomorrows_supply = e.token_supply_at_period(period=t + 1)
            assert tomorrows_supply >= todays_supply
            todays_supply = tomorrows_supply
コード例 #2
0
def test_exact_economics():
    """
    Formula for staking in one period:
    (totalSupply - currentSupply) * (lockedValue / totalLockedValue) * (k1 + allLockedPeriods) / k2

    K2 - Staking coefficient
    K1 - Locked periods coefficient

    if allLockedPeriods > awarded_periods then allLockedPeriods = awarded_periods
    kappa * log(2) / halving_delay === (k1 + allLockedPeriods) / k2

    kappa = small_stake_multiplier + (1 - small_stake_multiplier) * min(T, T1) / T1
    where allLockedPeriods == min(T, T1)
    """

    #
    # Expected Output
    #

    # Supply
    expected_total_supply = 3885390081777926911255691439
    expected_supply_ratio = Decimal('3.885390081777926911255691439')
    expected_initial_supply = 1000000000000000000000000000

    # Reward
    expected_reward_supply = 2885390081777926911255691439
    reward_saturation = 1

    # Staking
    halving = 2
    multiplier = 0.5
    expected_locked_periods_coefficient = 365
    expected_staking_coefficient = 768812

    assert expected_locked_periods_coefficient * halving == round(expected_staking_coefficient * log(2) * multiplier / 365)

    #
    # Sanity
    #

    # Sanity check ratio accuracy
    expected_scaled_ratio = str(expected_supply_ratio).replace('.', '')
    assert str(expected_total_supply) == expected_scaled_ratio

    # Sanity check denomination size
    expected_scale = 28
    assert len(str(expected_total_supply)) == expected_scale
    assert len(str(expected_initial_supply)) == expected_scale
    assert len(str(expected_reward_supply)) == expected_scale

    # Use same precision as economics class
    with localcontext() as ctx:
        ctx.prec = StandardTokenEconomics._precision

        # Sanity check expected testing outputs
        assert Decimal(expected_total_supply) / expected_initial_supply == expected_supply_ratio
        assert expected_reward_supply == expected_total_supply - expected_initial_supply
        assert reward_saturation * 365 * multiplier == expected_locked_periods_coefficient * (1 - multiplier)
        assert int(365 ** 2 * reward_saturation * halving / log(2) / (1-multiplier)) == expected_staking_coefficient

    # After sanity checking, assemble expected test deployment parameters
    expected_deployment_parameters = (24,       # Hours in single period
                                      768812,   # Staking coefficient (k2)
                                      365,      # Locked periods coefficient (k1)
                                      365,      # Max periods that will be additionally rewarded (awarded_periods)
                                      30,       # Min amount of periods during which tokens can be locked
                                      15000000000000000000000,    # min locked NuNits
                                      4000000000000000000000000,  # max locked NuNits
                                      2)        # Min worker periods
    #
    # Token Economics
    #

    # Check creation
    e = StandardTokenEconomics()

    with localcontext() as ctx:
        ctx.prec = StandardTokenEconomics._precision

        # Check that total_supply calculated correctly
        assert Decimal(e.erc20_total_supply) / e.initial_supply == expected_supply_ratio
        assert e.erc20_total_supply == expected_total_supply

        # Check reward rates
        initial_rate = Decimal((e.erc20_total_supply - e.initial_supply) * (e.locked_periods_coefficient + 365) / e.staking_coefficient)
        assert initial_rate == Decimal((e.initial_inflation * e.initial_supply) / 365)

        initial_rate_small = (e.erc20_total_supply - e.initial_supply) * e.locked_periods_coefficient / e.staking_coefficient
        assert Decimal(initial_rate_small) == Decimal(initial_rate / 2)

        # Check reward supply
        assert Decimal(LOG2 / (e.token_halving * 365) * (e.erc20_total_supply - e.initial_supply)) == initial_rate
        assert e.reward_supply == expected_total_supply - expected_initial_supply

        # Check deployment parameters
        assert e.staking_deployment_parameters == expected_deployment_parameters
        assert e.erc20_initial_supply == expected_initial_supply
        assert e.erc20_reward_supply == expected_reward_supply

        # Additional checks on supply
        assert e.token_supply_at_period(period=0) == expected_initial_supply
        assert e.cumulative_rewards_at_period(0) == 0

        # Last NuNit is mined after 184 years (or 67000 periods).
        # That's the year 2203, if token is launched in 2019.
        # 23rd century schizoid man!
        assert expected_total_supply == e.token_supply_at_period(period=67000)

        # After 1 year:
        assert 1_845_111_188_584347879497984668 == e.token_supply_at_period(period=365)
        assert 845_111_188_584347879497984668 == e.cumulative_rewards_at_period(365)
        assert e.erc20_initial_supply + e.cumulative_rewards_at_period(365) == e.token_supply_at_period(period=365)

        # Checking that the supply function is monotonic
        todays_supply = e.token_supply_at_period(period=0)
        for t in range(67000):
            tomorrows_supply = e.token_supply_at_period(period=t + 1)
            assert tomorrows_supply >= todays_supply
            todays_supply = tomorrows_supply