tg4_engagement/
state.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use crate::i128::Int128;
5use cosmwasm_std::{Addr, Timestamp, Uint128};
6use cw_storage_plus::{Item, Map};
7use tg_utils::Duration;
8pub use tg_utils::{PREAUTH_SLASHING, SLASHERS};
9
10#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
11pub struct Halflife {
12    /// if set to None then there's no half life
13    pub halflife: Option<Duration>,
14
15    pub last_applied: Timestamp,
16}
17
18impl Halflife {
19    pub fn should_apply(&self, t: Timestamp) -> bool {
20        if let Some(halflife) = self.halflife {
21            halflife.after_time(self.last_applied).is_expired_time(t)
22        } else {
23            false
24        }
25    }
26}
27
28/// How much points is the worth of single token in rewards distribution.
29/// The scaling is performed to have better precision of fixed point division.
30/// This value is not actually the scaling itself, but how much bits value should be shifted
31/// (for way more efficient division).
32///
33/// `32, to have those 32 bits, but it reduces how much tokens may be handled by this contract
34/// (it is now 96-bit integer instead of 128). In original ERC2222 it is handled by 256-bit
35/// calculations, but I256 is missing and it is required for this.
36pub const SHARES_SHIFT: u8 = 32;
37
38pub const HALFLIFE: Item<Halflife> = Item::new("halflife");
39
40#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
41pub struct Distribution {
42    /// Tokens can be distributed by this denom.
43    pub denom: String,
44    /// How many shares is single point worth
45    pub shares_per_point: Uint128,
46    /// Shares which were not fully distributed on previous distributions, and should be redistributed
47    pub shares_leftover: u64,
48    /// Total rewards distributed by this contract.
49    pub distributed_total: Uint128,
50    /// Total rewards not yet withdrawn.
51    pub withdrawable_total: Uint128,
52}
53
54#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)]
55pub struct WithdrawAdjustment {
56    /// How much points should be added/removed from calculated funds while withdrawal.
57    pub shares_correction: Int128,
58    /// How much funds addresses already withdrawn.
59    pub withdrawn_rewards: Uint128,
60    /// User delegated for funds withdrawal
61    pub delegated: Addr,
62}
63
64/// Rewards distribution data
65pub const DISTRIBUTION: Item<Distribution> = Item::new("distribution");
66/// Information how to exactly adjust rewards while withdrawal
67pub const WITHDRAW_ADJUSTMENT: Map<&Addr, WithdrawAdjustment> = Map::new("withdraw_adjustment");
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn halflife_should_apply() {
75        let epoch = 123456789;
76        let hf = Halflife {
77            halflife: None,
78            last_applied: Timestamp::from_seconds(epoch),
79        };
80        assert!(!hf.should_apply(Timestamp::from_seconds(epoch)));
81
82        let hf = Halflife {
83            halflife: Some(Duration::new(epoch + 1)),
84            last_applied: Timestamp::from_seconds(epoch),
85        };
86        assert!(!hf.should_apply(Timestamp::from_seconds(epoch)));
87
88        let hf = Halflife {
89            halflife: Some(Duration::new(epoch + 1)),
90            last_applied: Timestamp::from_seconds(epoch),
91        };
92        // because halflife + last_applied + 1 = one second after half life is expected to be met
93        assert!(hf.should_apply(Timestamp::from_seconds(epoch * 2 + 1)));
94
95        let hf = Halflife {
96            halflife: Some(Duration::new(epoch + 1)),
97            last_applied: Timestamp::from_seconds(epoch + 2),
98        };
99        assert!(!hf.should_apply(Timestamp::from_seconds(epoch + 2)));
100
101        let hf = Halflife {
102            halflife: Some(Duration::new(epoch + 1)),
103            last_applied: Timestamp::from_seconds(epoch + 2),
104        };
105        assert!(hf.should_apply(Timestamp::from_seconds(epoch * 2 + 3)));
106    }
107}