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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use cosmwasm_std::{Coin, Decimal, Uint128};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use tg_utils::{Duration, Expiration};
pub use crate::claim::Claim;
use tg4::Member;
const fn default_auto_return_limit() -> u64 {
20
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct InstantiateMsg {
/// Denom of the token to stake
pub denom: String,
pub tokens_per_point: Uint128,
pub min_bond: Uint128,
/// Unbounding period in seconds
pub unbonding_period: u64,
// admin can only add/remove hooks and slashers, not change other parameters
pub admin: Option<String>,
// or you can simply pre-authorize a number of hooks (to be done in the following messages)
#[serde(default)]
pub preauths_hooks: u64,
// and you can pre-authorize a number of slashers the same way
#[serde(default)]
pub preauths_slashing: u64,
/// Limits how much claims would be automatically returned at end of block, 20 by default.
/// Setting this to 0 disables auto returning claims.
#[serde(default = "default_auto_return_limit")]
pub auto_return_limit: u64,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
/// Bond will bond all staking tokens sent with the message and update membership points.
/// The optional `vesting_tokens` will be staked (delegated) as well, if set.
Bond { vesting_tokens: Option<Coin> },
/// Unbond will start the unbonding process for the given number of tokens.
/// The sender immediately loses points from these tokens, and can claim them
/// back to his wallet after `unbonding_period`.
/// Tokens will be unbonded from the liquid stake first, and then from the vesting stake
/// if available.
Unbond { tokens: Coin },
/// Claim is used to claim your native tokens that you previously "unbonded"
/// after the contract-defined waiting period (eg. 1 week)
Claim {},
/// Change the admin
UpdateAdmin { admin: Option<String> },
/// Add a new hook to be informed of all membership changes. Must be called by Admin
AddHook { addr: String },
/// Remove a hook. Must be called by Admin
RemoveHook { addr: String },
/// Add a new slasher. Must be called by Admin
AddSlasher { addr: String },
/// Remove a slasher. Must be called by Admin
RemoveSlasher { addr: String },
Slash {
addr: String,
// between (0.0, 1.0]
portion: Decimal,
},
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
/// Returns config
Configuration {},
/// Claims shows the tokens in process of unbonding for this address
Claims {
address: String,
limit: Option<u32>,
start_after: Option<Expiration>,
},
/// Shows the number of liquid and vesting tokens currently staked by this address.
/// Returns StakedResponse.
Staked { address: String },
/// Returns the unbonding period of this contract.
/// Returns UnbondingPeriodResponse.
UnbondingPeriod {},
/// Return AdminResponse
Admin {},
/// Returns TotalPointsResponse. This is the amount of tokens bonded divided by
/// tokens_per_point.
TotalPoints {},
/// Returns MemberListResponse
ListMembers {
start_after: Option<String>,
limit: Option<u32>,
},
/// Returns MemberListResponse, sorted by points descending.
ListMembersByPoints {
start_after: Option<Member>,
limit: Option<u32>,
},
/// Returns MemberResponse
Member {
addr: String,
at_height: Option<u64>,
},
/// Shows all registered hooks. Returns HooksResponse.
Hooks {},
/// Return the current number of preauths. Returns PreauthResponse.
Preauths {},
/// Returns information (bool) about whether a given address is an active slasher
IsSlasher { addr: String },
/// Returns all active slashers as a vector of addresses.
ListSlashers {},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct StakedResponse {
pub liquid: Coin,
pub vesting: Coin,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct PreauthResponse {
pub preauths_hooks: u64,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct UnbondingPeriodResponse {
pub unbonding_period: Duration,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ClaimsResponse {
pub claims: Vec<Claim>,
}
#[cfg(test)]
mod tests {
use super::*;
use cosmwasm_std::to_vec;
use tg_utils::Duration;
#[test]
fn unbonding_period_serializes_in_seconds() {
let res = UnbondingPeriodResponse {
unbonding_period: Duration::new(12345),
};
let json = to_vec(&res).unwrap();
assert_eq!(&json, br#"{"unbonding_period":12345}"#);
}
}