bvs_vault_base/
msg.rs

1use crate::error::VaultError;
2use crate::shares::QueuedWithdrawalInfo;
3use cosmwasm_schema::{cw_serde, QueryResponses};
4use cosmwasm_std::{Addr, Api, Uint128};
5
6/// Vault `ExecuteMsg`, to be implemented by the vault contract.
7/// Callable by any `sender`, redeemable by any `recipient`.
8/// The `sender` can be the same as the `recipient` in some cases.
9#[cw_serde]
10#[derive(bvs_pauser::api::Display)]
11pub enum VaultExecuteMsg {
12    /// ExecuteMsg DepositFor assets into the vault.
13    /// Sender must transfer the assets to the vault contract (this is implementation agnostic).
14    /// The vault contract must mint shares to the `recipient`.
15    /// Vault must be whitelisted in the `vault-router` to accept deposits.
16    DepositFor(RecipientAmount),
17
18    /// ExecuteMsg WithdrawTo assets from the vault.
19    /// Sender must have enough shares to withdraw the requested amount to the `recipient`.
20    /// If the Vault is delegated to an `operator`, withdrawals must be queued.
21    /// Operator must not be validating any services for instant withdrawals.
22    WithdrawTo(RecipientAmount),
23
24    /// ExecuteMsg QueueWithdrawalTo assets from the vault.
25    /// Sender must have enough shares to queue the requested amount to the `recipient`.
26    /// Once the withdrawal is queued,
27    /// the `recipient` can redeem the withdrawal after the lock period.
28    /// Once the withdrawal is locked,
29    /// the `sender` cannot cancel the withdrawal.
30    /// The time-lock is enforced by the vault and cannot be changed retroactively.
31    ///
32    /// ### Lock Period Extension
33    /// New withdrawals will extend the lock period of any existing withdrawals.
34    /// You can queue the withdrawal to a different `recipient` than the `sender` to avoid this.
35    QueueWithdrawalTo(RecipientAmount),
36
37    /// ExecuteMsg RedeemWithdrawalTo all queued shares into assets from the vault for withdrawal.
38    /// After the lock period, the `sender` (must be the `recipient` of the original withdrawal)
39    /// can redeem the withdrawal.
40    RedeemWithdrawalTo(Recipient),
41
42    /// ExecuteMsg SlashLocked moves the assets from the vault to the `vault-router` contract for custody.
43    /// Part of the [https://build.satlayer.xyz/getting-started/slashing](Programmable Slashing) lifecycle.
44    /// This function can only be called by `vault-router`, and takes an absolute `amount` of assets to be moved.
45    /// The amount is calculated and enforced by the router.
46    /// Further utility of the assets, post-locked, is implemented and enforced on the router level.
47    SlashLocked(Amount),
48}
49
50#[cw_serde]
51/// This struct represents amount of assets.
52pub struct Amount(pub Uint128);
53
54impl Amount {
55    /// Validate the amount: [`Uint128`] field.
56    /// The amount must be greater than zero.
57    pub fn validate(&self, _api: &dyn Api) -> Result<(), VaultError> {
58        if self.0.is_zero() {
59            return Err(VaultError::zero("Amount cannot be zero"));
60        }
61        Ok(())
62    }
63}
64
65/// This struct is used to represent the recipient and amount fields together.
66#[cw_serde]
67pub struct RecipientAmount {
68    pub recipient: Addr,
69    pub amount: Uint128,
70}
71
72impl RecipientAmount {
73    /// Validate the recipient: [`Addr`] and amount: [`Uint128`] fields.
74    /// The recipient must be a valid [`Addr`], and the amount must be greater than zero.
75    pub fn validate(&self, api: &dyn Api) -> Result<(), VaultError> {
76        if self.amount.is_zero() {
77            return Err(VaultError::zero("Amount cannot be zero"));
78        }
79
80        api.addr_validate(self.recipient.as_str())?;
81        Ok(())
82    }
83}
84
85/// This struct is used to represent a recipient for RedeemWithdrawalTo.
86#[cw_serde]
87pub struct Recipient(pub Addr);
88
89impl Recipient {
90    /// Validate the recipient: [`Addr`] field.
91    /// The recipient must be a valid [`Addr`].
92    pub fn validate(&self, api: &dyn Api) -> Result<(), VaultError> {
93        api.addr_validate(self.0.as_str())?;
94        Ok(())
95    }
96}
97
98#[cw_serde]
99#[derive(QueryResponses)]
100pub enum VaultQueryMsg {
101    /// QueryMsg Shares: get the shares of a staker.
102    #[returns(SharesResponse)]
103    Shares { staker: String },
104
105    /// QueryMsg Assets: get the assets of a staker, converted from shares.
106    #[returns(AssetsResponse)]
107    Assets { staker: String },
108
109    /// QueryMsg ConvertToAssets: convert shares to assets.
110    #[returns(ConvertToAssetsResponse)]
111    ConvertToAssets { shares: Uint128 },
112
113    /// QueryMsg ConvertToShares: convert assets to shares.
114    #[returns(ConvertToSharesResponse)]
115    ConvertToShares { assets: Uint128 },
116
117    /// QueryMsg TotalShares: get the total shares in circulation.
118    #[returns(TotalSharesResponse)]
119    TotalShares {},
120
121    /// QueryMsg TotalAssets: get the total assets under vault.
122    #[returns(TotalAssetsResponse)]
123    TotalAssets {},
124
125    /// QueryMsg QueuedWithdrawal: get the queued withdrawal and unlock timestamp under vault.
126    #[returns(QueuedWithdrawalResponse)]
127    QueuedWithdrawal { staker: String },
128
129    /// QueryMsg VaultInfo: get the vault information.
130    #[returns(VaultInfoResponse)]
131    VaultInfo {},
132}
133
134/// The response to the `Shares` query.
135/// This is just a wrapper around `Uint128`, so that the schema can be generated.
136#[cw_serde]
137pub struct SharesResponse(Uint128);
138
139/// The response to the `Assets` query.
140/// This is just a wrapper around `Uint128`, so that the schema can be generated.
141#[cw_serde]
142pub struct AssetsResponse(Uint128);
143
144/// The response to the `ConvertToAssets` query.
145/// This is just a wrapper around `Uint128`, so that the schema can be generated.
146#[cw_serde]
147pub struct ConvertToAssetsResponse(Uint128);
148
149/// The response to the `ConvertToShares` query.
150/// This is just a wrapper around `Uint128`, so that the schema can be generated.
151#[cw_serde]
152pub struct ConvertToSharesResponse(Uint128);
153
154/// The response to the `TotalShares` query.
155/// This is just a wrapper around `Uint128`, so that the schema can be generated.
156#[cw_serde]
157pub struct TotalSharesResponse(Uint128);
158
159/// The response to the `TotalAssets` query.
160/// This is just a wrapper around `Uint128`, so that the schema can be generated.
161#[cw_serde]
162pub struct TotalAssetsResponse(Uint128);
163
164/// The response to the `QueuedWithdrawal` query.
165/// This is just a wrapper around `QueuedWithdrawalInfo`, so that the schema can be generated.
166#[cw_serde]
167pub struct QueuedWithdrawalResponse(QueuedWithdrawalInfo);
168
169#[cw_serde]
170pub struct VaultInfoResponse {
171    /// The total shares in circulation
172    pub total_shares: Uint128,
173
174    /// The total assets under management
175    pub total_assets: Uint128,
176
177    /// The `vault-router` contract address
178    pub router: Addr,
179
180    /// The `pauser` contract address
181    pub pauser: Addr,
182
183    /// The `operator` that this vault is delegated to
184    pub operator: Addr,
185
186    /// Asset identifier, using the CAIP-19 format.
187    pub asset_id: String,
188
189    /// The asset type, either `AssetType::Cw20` or `AssetType::Bank`.
190    pub asset_type: AssetType,
191
192    /// The asset reference stores the cw20 contract address or the bank denom.
193    pub asset_reference: String,
194
195    /// The name of the vault contract, see [`cw2::set_contract_version`] for more information.
196    pub contract: String,
197
198    /// The version of the vault contract, see [`cw2::set_contract_version`] for more information.
199    pub version: String,
200}
201
202#[cw_serde]
203pub enum AssetType {
204    Cw20,
205    Bank,
206}