Skip to main content

pfc_steak/
hub.rs

1use std::str::FromStr;
2
3use cosmwasm_std::{
4    to_json_binary, Addr, Binary, Coin, CosmosMsg, Decimal, Empty, StdResult, Uint128, WasmMsg,
5};
6use cw20::Cw20ReceiveMsg;
7use cw20_base::msg::InstantiateMarketingInfo as Cw20InstantiateMarketingInfo;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10
11#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
12pub enum Cw20HookMsg {
13    Distribute {},
14    Transfer {},
15}
16
17#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
18pub enum EnterpriseCw20HookMsg {
19    Distribute {},
20}
21
22#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
23pub struct InstantiateMsg {
24    /// Code ID of the CW20 token contract
25    pub cw20_code_id: u64,
26    /// Account who can call certain privileged functions
27    pub owner: String,
28    /// Name of the liquid staking token
29    pub name: String,
30    /// Symbol of the liquid staking token
31    pub symbol: String,
32    /// Number of decimals of the liquid staking token
33    pub decimals: u8,
34    /// How often the unbonding queue is to be executed, in seconds
35    pub epoch_period: u64,
36    /// The staking module's unbonding time, in seconds
37    pub unbond_period: u64,
38    /// Initial set of validators who will receive the delegations
39    pub validators: Vec<String>,
40    /// denomination of coins to steak (uXXXX)
41    pub denom: String,
42    /// type of fee account
43    pub fee_account_type: String,
44    /// Fee Account to send fees too
45    pub fee_account: String,
46    /// Fee "1.00 = 100%"
47    pub fee_amount: Decimal,
48    /// Max Fee "1.00 = 100%"
49    pub max_fee_amount: Decimal,
50    /// label for the CW20 token we create
51    pub label: Option<String>,
52    /// Marketing info for the CW20 we create
53    pub marketing: Option<Cw20InstantiateMarketingInfo>,
54    pub dust_collector: Option<String>,
55}
56
57#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
58#[serde(rename_all = "snake_case")]
59pub enum ExecuteMsg {
60    /// Implements the Cw20 receiver interface
61    Receive(Cw20ReceiveMsg),
62    /// Bond specified amount of Luna
63    Bond {
64        receiver: Option<String>,
65        exec_msg: Option<Binary>,
66    },
67    /// Bond specified amount of Luna, just minting it directly (cw-20 version only)
68    BondEx {
69        receiver: Option<String>,
70    },
71    /// Withdraw Luna that have finished unbonding in previous batches
72    WithdrawUnbonded {
73        receiver: Option<String>,
74    },
75    /// Withdraw Luna that has finished unbonding in previous batches, for given address
76    WithdrawUnbondedAdmin {
77        address: String,
78    },
79    /// Add a validator to the whitelist; callable by the owner
80    AddValidator {
81        validator: String,
82    },
83    /// Remove a validator from the whitelist; callable by the owner
84    RemoveValidator {
85        validator: String,
86    },
87    /// Remove a validator from the whitelist; callable by the owner. Does not undelegate. use for
88    /// typos
89    RemoveValidatorEx {
90        validator: String,
91    },
92
93    /// Pause a validator from accepting new delegations
94    PauseValidator {
95        validator: String,
96    },
97    /// Unpause a validator from accepting new delegations
98    UnPauseValidator {
99        validator: String,
100    },
101
102    /// Transfer ownership to another account; will not take effect unless the new owner accepts
103    TransferOwnership {
104        new_owner: String,
105    },
106    /// Accept an ownership transfer
107    AcceptOwnership {},
108    /// Claim staking rewards, swap all for Luna, and restake
109    Harvest {},
110    /// Use redelegations to balance the amounts of Luna delegated to validators
111    Rebalance {
112        minimum: Uint128,
113    },
114    /// redelegate stake from one validator to another
115    Redelegate {
116        validator_from: String,
117        validator_to: String,
118    },
119    /// Update Luna amounts in unbonding batches to reflect any slashing or rounding errors
120    Reconcile {},
121    /// Submit the current pending batch of unbonding requests to be unbonded
122    SubmitBatch {},
123    /// Set unbond period
124    SetUnbondPeriod {
125        unbond_period: u64,
126    },
127
128    /// Transfer Fee collection account to another account
129    TransferFeeAccount {
130        fee_account_type: String,
131        new_fee_account: String,
132    },
133    /// Update fee collection amount
134    UpdateFee {
135        new_fee: Decimal,
136    },
137    /// Callbacks; can only be invoked by the contract itself
138    Callback(CallbackMsg),
139    // Set The Duster.
140    SetDustCollector {
141        dust_collector: Option<String>,
142    },
143    /// Collect the Dust
144    CollectDust {
145        max_tokens: u32,
146    },
147    /// Return the Dust in shiny 'base denom'
148    ReturnDenom {},
149}
150
151#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
152#[serde(rename_all = "snake_case")]
153pub enum ReceiveMsg {
154    /// Submit an unbonding request to the current unbonding queue; automatically invokes `unbond`
155    /// if `epoch_time` has elapsed since when the last unbonding queue was executed.
156    QueueUnbond {
157        receiver: Option<String>,
158    },
159}
160
161#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
162#[serde(rename_all = "snake_case")]
163pub enum CallbackMsg {
164    /// Following the swaps, stake the Luna acquired to the whitelisted validators
165    Reinvest {},
166}
167
168impl CallbackMsg {
169    pub fn into_cosmos_msg(&self, contract_addr: &Addr) -> StdResult<CosmosMsg> {
170        Ok(CosmosMsg::Wasm(WasmMsg::Execute {
171            contract_addr: contract_addr.to_string(),
172            msg: to_json_binary(&ExecuteMsg::Callback(self.clone()))?,
173            funds: vec![],
174        }))
175    }
176}
177
178#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
179#[serde(rename_all = "snake_case")]
180pub enum QueryMsg {
181    /// The contract's configurations. Response: `ConfigResponse`
182    Config {},
183    /// The contract's current state. Response: `StateResponse`
184    State {},
185    /// The current batch on unbonding requests pending submission. Response: `PendingBatch`
186    PendingBatch {},
187    /// Query an individual batch that has previously been submitted for unbonding but have not yet
188    /// fully withdrawn. Response: `Batch`
189    PreviousBatch(u64),
190    /// Enumerate all previous batches that have previously been submitted for unbonding but have
191    /// not yet fully withdrawn. Response: `Vec<Batch>`
192    PreviousBatches {
193        start_after: Option<u64>,
194        limit: Option<u32>,
195    },
196    /// Enumerate all outstanding unbonding requests in a given batch. Response:
197    /// `Vec<UnbondRequestsResponseByBatchItem>`
198    UnbondRequestsByBatch {
199        id: u64,
200        start_after: Option<String>,
201        limit: Option<u32>,
202    },
203    /// Enumerate all outstanding unbonding requests from given a user. Response:
204    /// `Vec<UnbondRequestsByUserResponseItem>`
205    UnbondRequestsByUser {
206        user: String,
207        start_after: Option<u64>,
208        limit: Option<u32>,
209    },
210}
211
212#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
213pub struct ConfigResponse {
214    /// Account who can call certain privileged functions
215    pub owner: String,
216    /// Pending ownership transfer, awaiting acceptance by the new owner
217    pub new_owner: Option<String>,
218    /// Address of the Steak token
219    pub steak_token: String,
220    /// How often the unbonding queue is to be executed, in seconds
221    pub epoch_period: u64,
222    /// The staking module's unbonding time, in seconds
223    pub unbond_period: u64,
224    /// denomination of coins to steak (uXXXX)
225    pub denom: String,
226    /// type of account to send the fees too
227    pub fee_type: String,
228    /// Fee Account to send fees too
229    pub fee_account: String,
230    /// Fee "1.00 = 100%"
231    pub fee_rate: Decimal,
232    /// Max Fee "1.00 = 100%"
233    pub max_fee_rate: Decimal,
234    /// Set of validators who will receive the delegations
235    pub validators: Vec<String>,
236    pub paused_validators: Vec<String>,
237    pub dust_collector: Option<String>,
238    pub token_factory: Option<String>,
239}
240
241#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
242pub struct StateResponse {
243    /// Total supply to the Steak token
244    pub total_usteak: Uint128,
245    /// Total amount of native staked
246    pub total_native: Uint128,
247    /// The exchange rate between usteak and native, in terms of native per usteak
248    pub exchange_rate: Decimal,
249    /// Staking rewards currently held by the contract that are ready to be reinvested
250    pub unlocked_coins: Vec<Coin>,
251}
252
253#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
254pub struct PendingBatch {
255    /// ID of this batch
256    pub id: u64,
257    /// Total amount of `usteak` to be burned in this batch
258    pub usteak_to_burn: Uint128,
259    /// Estimated time when this batch will be submitted for unbonding
260    pub est_unbond_start_time: u64,
261}
262
263#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
264pub struct Batch {
265    /// ID of this batch
266    pub id: u64,
267    /// Whether this batch has already been reconciled
268    pub reconciled: bool,
269    /// Total amount of shares remaining this batch. Each `usteak` burned = 1 share
270    pub total_shares: Uint128,
271    /// Amount of `denom` in this batch that have not been claimed
272    pub amount_unclaimed: Uint128,
273    /// Estimated time when this batch will finish unbonding
274    pub est_unbond_end_time: u64,
275}
276
277#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
278pub struct UnbondRequest {
279    /// ID of the batch
280    pub id: u64,
281    /// The user's address
282    pub user: Addr,
283    /// The user's share in the batch
284    pub shares: Uint128,
285}
286
287#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
288pub struct UnbondRequestsByBatchResponseItem {
289    /// The user's address
290    pub user: String,
291    /// The user's share in the batch
292    pub shares: Uint128,
293}
294
295impl From<UnbondRequest> for UnbondRequestsByBatchResponseItem {
296    fn from(s: UnbondRequest) -> Self {
297        Self {
298            user: s.user.into(),
299            shares: s.shares,
300        }
301    }
302}
303
304#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)]
305pub struct UnbondRequestsByUserResponseItem {
306    /// ID of the batch
307    pub id: u64,
308    /// The user's share in the batch
309    pub shares: Uint128,
310}
311
312impl From<UnbondRequest> for UnbondRequestsByUserResponseItem {
313    fn from(s: UnbondRequest) -> Self {
314        Self {
315            id: s.id,
316            shares: s.shares,
317        }
318    }
319}
320
321pub type MigrateMsg = Empty;
322
323#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Copy, JsonSchema)]
324pub enum FeeType {
325    Wallet,
326    FeeSplit,
327}
328
329impl FromStr for FeeType {
330    type Err = ();
331
332    fn from_str(s: &str) -> Result<Self, Self::Err> {
333        match s {
334            "Wallet" => Ok(FeeType::Wallet),
335            "FeeSplit" => Ok(FeeType::FeeSplit),
336            _ => Err(()),
337        }
338    }
339}
340
341impl ToString for FeeType {
342    fn to_string(&self) -> String {
343        match &self {
344            FeeType::Wallet => String::from("Wallet"),
345            FeeType::FeeSplit => String::from("FeeSplit"),
346        }
347    }
348}