-
Notifications
You must be signed in to change notification settings - Fork 3
/
booster.rs
96 lines (85 loc) · 3.91 KB
/
booster.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::*;
#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)]
#[serde(crate = "near_sdk::serde")]
pub struct BoosterInfo {
pub booster_decimal: u32,
/// <affected_seed_id, log_base>
pub affected_seeds: HashMap<SeedId, u32>,
}
impl BoosterInfo {
pub fn assert_valid(&self, booster_id: &SeedId) {
require!(self.affected_seeds.contains_key(booster_id) == false, E202_FORBID_SELF_BOOST);
require!(self.affected_seeds.len() <= MAX_NUM_SEEDS_PER_BOOSTER, E204_EXCEED_SEED_NUM_IN_BOOSTER);
}
}
#[near_bindgen]
impl Contract {
#[payable]
pub fn modify_booster(&mut self, booster_id: SeedId, booster_info: BoosterInfo) {
assert_one_yocto();
require!(self.is_owner_or_operators(), E002_NOT_ALLOWED);
require!(self.data().state == RunningState::Running, E004_CONTRACT_PAUSED);
require!(self.internal_get_seed(&booster_id).is_some(), E301_SEED_NOT_EXIST);
booster_info.assert_valid(&booster_id);
let mut config = self.data().config.get().unwrap();
require!(self.affected_farm_count(&booster_info) <= config.max_num_farms_per_booster, E203_EXCEED_FARM_NUM_IN_BOOST);
config.booster_seeds.insert(booster_id.clone(), booster_info);
self.data_mut().config.set(&config);
}
}
impl Contract {
fn affected_farm_count(&self, booster_info: &BoosterInfo) -> u32 {
booster_info.affected_seeds
.keys()
.map(|seed_id| self.data().seeds.get(seed_id).expect(E301_SEED_NOT_EXIST))
.map(|v| {
let seed: Seed = v.into();
seed.farms.len() as u32
})
.sum::<u32>()
}
pub fn assert_booster_affected_farm_num(&self) {
let config = self.internal_config();
for booster_info in config.booster_seeds.values() {
require!(self.affected_farm_count(booster_info) <= config.max_num_farms_per_booster, E203_EXCEED_FARM_NUM_IN_BOOST);
}
}
/// generate booster ratios map for a given seed
/// booster-ratio = ((booster_balance as f64) / (booster_base as f64)).log(log_base as f64)
/// where log_base if from Config.global_booster_seeds.get(seed_id).unwrap().get(self.seed_id).unwrap()
pub fn gen_booster_ratios(&self, seed_id: &SeedId, farmer: &Farmer) -> HashMap<SeedId, f64> {
let mut ratios = HashMap::new();
let log_bases = self.internal_config().get_boosters_from_seed(seed_id);
for (booster, booster_decimal, log_base) in &log_bases {
let booster_balance = farmer
.get_seed(booster)
.map(|v| v.get_basic_seed_power())
.unwrap_or(0_u128);
if booster_balance > 0 && log_base > &0 {
let booster_base = 10u128.pow(*booster_decimal);
let booster_amount = booster_balance as f64 / booster_base as f64;
let ratio = if booster_amount > 1f64 {
booster_amount.log(*log_base as f64)
} else {
0f64
};
ratios.insert(booster.clone(), ratio);
}
}
ratios
}
/// if seed_id is a booster, then update all impacted seed
pub fn update_impacted_seeds(&mut self, farmer: &mut Farmer, booster_id: &SeedId) {
if let Some(booster_info) = self.internal_config().get_affected_seeds_from_booster(booster_id) {
for seed_id in booster_info.affected_seeds.keys() {
// here we got each affected seed_id, then if the farmer has those seeds, should be updated on by one
if farmer.get_seed(seed_id).is_some() {
// first claim that farmer's current reward and update boost_ratios for the seed
let mut seed = self.internal_unwrap_seed(seed_id);
self.internal_do_farmer_claim(farmer, &mut seed);
self.internal_set_seed(seed_id, seed);
}
}
}
}
}