From c5e65de413c6fbe3e7233a2e262a37ddd525d3e3 Mon Sep 17 00:00:00 2001 From: Theo Butler Date: Mon, 25 Mar 2024 13:55:11 -0400 Subject: [PATCH] fix: use slashable GRT for economic security factor --- indexer-selection/src/lib.rs | 21 +++++++++++---------- indexer-selection/src/test.rs | 6 +++--- simulator/src/main.rs | 8 ++++---- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/indexer-selection/src/lib.rs b/indexer-selection/src/lib.rs index 8bc114f..af55135 100644 --- a/indexer-selection/src/lib.rs +++ b/indexer-selection/src/lib.rs @@ -24,7 +24,7 @@ pub struct Candidate { pub perf: ExpectedPerformance, pub fee: Normalized, pub seconds_behind: u32, - pub slashable_usd: u64, + pub slashable_grt: u64, pub subgraph_versions_behind: u8, pub zero_allocation: bool, } @@ -57,7 +57,7 @@ impl candidate_selection::Candidate for Candidate { score_latency(self.perf.latency_ms()), score_fee(self.fee), score_seconds_behind(self.seconds_behind), - score_slashable_usd(self.slashable_usd), + score_slashable_grt(self.slashable_grt), score_subgraph_versions_behind(self.subgraph_versions_behind), score_zero_allocation(self.zero_allocation), ] @@ -96,9 +96,9 @@ impl candidate_selection::Candidate for Candidate { .zip(&p) .map(|(x, p)| x as f64 * p.as_f64()) .sum::() as u32; - let slashable_usd = candidates + let slashable_grt = candidates .iter() - .map(|c| c.slashable_usd) + .map(|c| c.slashable_grt) .zip(&p) .map(|(x, p)| x as f64 * p.as_f64()) .sum::() as u64; @@ -115,7 +115,7 @@ impl candidate_selection::Candidate for Candidate { score_latency(latency), score_fee(fee), score_seconds_behind(seconds_behind), - score_slashable_usd(slashable_usd), + score_slashable_grt(slashable_grt), score_subgraph_versions_behind(subgraph_versions_behind), score_zero_allocation(p_zero_allocation), ] @@ -146,10 +146,11 @@ fn score_seconds_behind(seconds_behind: u32) -> Normalized { Normalized::new(1.0 - E.powf(-32.0 / seconds_behind.max(1) as f64)).unwrap() } -/// https://www.desmos.com/calculator/akqaa2gjrf -fn score_slashable_usd(slashable_usd: u64) -> Normalized { - let x = slashable_usd as f64; - let a = 2e-4; +/// https://www.desmos.com/calculator/iqhjcdnphv +fn score_slashable_grt(slashable_grt: u64) -> Normalized { + let x = slashable_grt as f64; + // Currently setting a minimum score of ~0.8 at the minimum stake requirement of 100,000 GRT. + let a = 1.6e-5; Normalized::new(1.0 - E.powf(-a * x)).unwrap() } @@ -196,7 +197,7 @@ mod tests { }, fee: Normalized::ONE, seconds_behind: 0, - slashable_usd: 0, + slashable_grt: 0, subgraph_versions_behind: 0, zero_allocation: false, }; diff --git a/indexer-selection/src/test.rs b/indexer-selection/src/test.rs index 9706c5a..bd9b311 100644 --- a/indexer-selection/src/test.rs +++ b/indexer-selection/src/test.rs @@ -45,7 +45,7 @@ prop_compose! { fee in Normalized::arbitrary(), subgraph_versions_behind in 0..=3_u8, seconds_behind: u16, - slashable_usd: u64, + slashable_grt: u64, zero_allocation: bool, avg_latency_ms: u16, avg_success_rate_percent in 0..=100_u8, @@ -68,7 +68,7 @@ prop_compose! { perf: performance.expected_performance(), fee, seconds_behind: seconds_behind as u32, - slashable_usd, + slashable_grt, subgraph_versions_behind, zero_allocation, } @@ -86,7 +86,7 @@ proptest! { println!("{:#?}", selections.iter().map(|c| c.indexer).collect::>()); let valid_candidate = |c: &Candidate| -> bool { - c.slashable_usd > 0 + c.slashable_grt > 0 }; let valid_selections = candidates.iter().filter(|c| valid_candidate(c)).count(); diff --git a/simulator/src/main.rs b/simulator/src/main.rs index 4a87cc4..7b26833 100644 --- a/simulator/src/main.rs +++ b/simulator/src/main.rs @@ -14,13 +14,13 @@ struct IndexerCharacteristics { latency_ms: u32, fee_usd: f64, seconds_behind: u32, - slashable_usd: u64, + slashable_grt: u64, zero_allocation: bool, } fn main() { let header = - "address,fee_usd,seconds_behind,latency_ms,success_rate,slashable_usd,zero_allocation"; + "address,fee_usd,seconds_behind,latency_ms,success_rate,slashable_grt,zero_allocation"; let characteristics: Vec = stdin() .lines() .filter_map(|line| { @@ -39,7 +39,7 @@ fn main() { .ok() .and_then(Normalized::new) .expect("success_rate"), - slashable_usd: fields[5].parse().expect("slashable_usd"), + slashable_grt: fields[5].parse().expect("slashable_grt"), zero_allocation: fields[6].parse().expect("zero_allocation"), }) }) @@ -90,7 +90,7 @@ fn main() { perf: perf.get(&c.address).unwrap().expected_performance(), fee: Normalized::new(c.fee_usd / budget).expect("invalid fee or budget"), seconds_behind: c.seconds_behind, - slashable_usd: c.slashable_usd, + slashable_grt: c.slashable_grt, subgraph_versions_behind: 0, zero_allocation: c.zero_allocation, })