Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

L1-291: Cherry pick inflation unit tests #1829

Merged
merged 6 commits into from
Oct 8, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions bin/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1604,4 +1604,158 @@ mod tests {

assert!(lhs < rhs);
}

const MILLISECS_PER_DAY: u64 = 24 * 60 * 60 * 1000;

struct EraPayoutInputs {
azero_cap: Balance,
horizon: u64,
total_issuance: Balance,
era_duration_millis: u64,
}

struct EraPayoutOutputs {
validators_payout: Balance,
rest: Balance,
}

fn assert_era_payout(inputs: EraPayoutInputs, outputs: EraPayoutOutputs) {
use sp_io::TestExternalities;
TestExternalities::default().execute_with(|| {
pallet_aleph::AzeroCap::<Runtime>::put(inputs.azero_cap);
pallet_aleph::ExponentialInflationHorizon::<Runtime>::put(inputs.horizon);
let (validators_payout, rest) =
ExponentialEraPayout::era_payout(inputs.total_issuance, inputs.era_duration_millis);
assert_eq!(validators_payout, outputs.validators_payout);
assert_eq!(rest, outputs.rest);
});
}

fn era_payout_multiple_eras(
inputs: EraPayoutInputs,
n_eras: usize,
) -> (Vec<EraPayoutOutputs>, Balance) {
use sp_io::TestExternalities;
let mut outputs = vec![];
let mut total_issuance = inputs.total_issuance;
for _ in 0..n_eras {
TestExternalities::default().execute_with(|| {
pallet_aleph::AzeroCap::<Runtime>::put(inputs.azero_cap);
pallet_aleph::ExponentialInflationHorizon::<Runtime>::put(inputs.horizon);
let (validators_payout, rest) =
ExponentialEraPayout::era_payout(total_issuance, inputs.era_duration_millis);
outputs.push(EraPayoutOutputs {
validators_payout,
rest,
});
total_issuance += validators_payout + rest;
});
}
(outputs, total_issuance)
}

#[test]
fn era_payout_standard_case() {
assert_era_payout(
EraPayoutInputs {
azero_cap: 100_000_000 * TOKEN,
horizon: 365 * MILLISECS_PER_DAY,
total_issuance: 50_000_000 * TOKEN,
era_duration_millis: MILLISECS_PER_DAY,
},
EraPayoutOutputs {
validators_payout: 123_118 * TOKEN + 920_000_000_000,
rest: 13_679 * TOKEN + 880_000_000_000,
},
);
}

#[test]
/// Simulate long run by calling `era_payout` multiple times,
/// and keeping track of `total_issuance` between calls.
/// After 3 * horizon milliseconds the gap should be reduced by ~95%.
fn era_payout_long_run() {
let (_, total_issuance) = era_payout_multiple_eras(
EraPayoutInputs {
azero_cap: 150_000_000 * TOKEN,
horizon: 365 * MILLISECS_PER_DAY,
total_issuance: 50_000_000 * TOKEN,
era_duration_millis: MILLISECS_PER_DAY,
},
3 * 365,
);
assert_eq!(total_issuance, 145_021_290 * TOKEN + 959_387_724_274);
}

#[test]
/// Era longer than horizon.
/// Perbill will saturate, (era_duration_millis / horizon) == 1,
/// even if horizon == 0.
/// The actual values do not matter, only the ratio is used.
/// We expect the gap to be reduced by ~63%.
fn era_payout_horizon_too_short() {
assert_era_payout(
EraPayoutInputs {
azero_cap: 100_000_000 * TOKEN,
horizon: 0,
total_issuance: 50_000_000 * TOKEN,
era_duration_millis: MILLISECS_PER_DAY,
},
EraPayoutOutputs {
validators_payout: 28_499_999 * TOKEN + 985_000_000_000,
rest: 3_166_666 * TOKEN + 665_000_000_000,
},
);
}

#[test]
/// AZERO cap equal to total issuance, we expect no payout.
fn era_payout_cap_reached() {
assert_era_payout(
EraPayoutInputs {
azero_cap: 100_000_000 * TOKEN,
horizon: 365 * MILLISECS_PER_DAY,
total_issuance: 100_000_000 * TOKEN,
era_duration_millis: MILLISECS_PER_DAY,
},
EraPayoutOutputs {
validators_payout: 0,
rest: 0,
},
);
}

#[test]
/// Total issuance larger than AZERO cap, we expect no payout.
fn era_payout_cap_exceeded() {
assert_era_payout(
EraPayoutInputs {
azero_cap: 50_000_000 * TOKEN,
horizon: 365 * MILLISECS_PER_DAY,
total_issuance: 100_000_000 * TOKEN,
era_duration_millis: MILLISECS_PER_DAY,
},
EraPayoutOutputs {
validators_payout: 0,
rest: 0,
},
);
}

#[test]
/// Zero-length era, we expect no payout (as it depends on era lenght).
fn era_payout_zero_lenght_era() {
assert_era_payout(
EraPayoutInputs {
azero_cap: 100_000_000 * TOKEN,
horizon: 365 * MILLISECS_PER_DAY,
total_issuance: 50_000_000 * TOKEN,
era_duration_millis: 0,
},
EraPayoutOutputs {
validators_payout: 0,
rest: 0,
},
);
}
}
Loading