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 QueueWithdrawalTo assets from the vault.
19    /// Sender must have enough shares to queue the requested amount to the `controller`.
20    /// Once the withdrawal is queued,
21    /// the `controller` can redeem the withdrawal after the lock period.
22    /// Once the withdrawal is locked,
23    /// the `sender` cannot cancel the withdrawal.
24    /// The time-lock is enforced by the vault and cannot be changed retroactively.
25    ///
26    /// ### Lock Period Extension
27    /// New withdrawals will extend the lock period of any existing withdrawals.
28    /// You can queue the withdrawal to a different `controller` than the `sender` to avoid this.
29    QueueWithdrawalTo(QueueWithdrawalToParams),
30
31    /// ExecuteMsg RedeemWithdrawalTo all queued shares into assets from the vault for withdrawal.
32    /// After the lock period, the `sender` (must be the `controller` of the original withdrawal)
33    /// can redeem the withdrawal to the `recipient`
34    RedeemWithdrawalTo(RedeemWithdrawalToParams),
35
36    /// ExecuteMsg SlashLocked moves the assets from the vault to the `vault-router` contract for custody.
37    /// Part of the [https://build.satlayer.xyz/getting-started/slashing](Programmable Slashing) lifecycle.
38    /// This function can only be called by `vault-router`, and takes an absolute `amount` of assets to be moved.
39    /// The amount is calculated and enforced by the router.
40    /// Further utility of the assets, post-locked, is implemented and enforced on the router level.
41    SlashLocked(Amount),
42
43    /// ExecuteMsg ApproveProxy allows the `proxy`
44    /// to queue withdrawal and redeem withdrawal on behalf of the `owner`.
45    SetApproveProxy(SetApproveProxyParams),
46}
47
48#[cw_serde]
49/// This struct represents amount of assets.
50pub struct Amount(pub Uint128);
51
52impl Amount {
53    /// Validate the amount: [`Uint128`] field.
54    /// The amount must be greater than zero.
55    pub fn validate(&self, _api: &dyn Api) -> Result<(), VaultError> {
56        if self.0.is_zero() {
57            return Err(VaultError::zero("Amount cannot be zero"));
58        }
59        Ok(())
60    }
61}
62
63/// This struct is used to represent the controller and amount fields together.
64#[cw_serde]
65pub struct QueueWithdrawalToParams {
66    /// the controller is the address that can redeem the withdrawal after the lock period
67    pub controller: Addr,
68    /// the owner is the address that owns the shares being withdrawn
69    pub owner: Addr,
70    /// the amount is the amount of shares to be withdrawn
71    pub amount: Uint128,
72}
73
74impl QueueWithdrawalToParams {
75    /// Validate the controller: [`Addr`] and amount: [`Uint128`] fields.
76    /// The controller must be a valid [`Addr`], and the amount must be greater than zero.
77    pub fn validate(&self, api: &dyn Api) -> Result<(), VaultError> {
78        if self.amount.is_zero() {
79            return Err(VaultError::zero("Amount cannot be zero"));
80        }
81
82        api.addr_validate(self.controller.as_str())?;
83        api.addr_validate(self.owner.as_str())?;
84        Ok(())
85    }
86}
87
88/// This struct is used to represent the recipient and amount fields together.
89#[cw_serde]
90pub struct RecipientAmount {
91    pub recipient: Addr,
92    pub amount: Uint128,
93}
94
95impl RecipientAmount {
96    /// Validate the recipient: [`Addr`] and amount: [`Uint128`] fields.
97    /// The recipient must be a valid [`Addr`], and the amount must be greater than zero.
98    pub fn validate(&self, api: &dyn Api) -> Result<(), VaultError> {
99        if self.amount.is_zero() {
100            return Err(VaultError::zero("Amount cannot be zero"));
101        }
102
103        api.addr_validate(self.recipient.as_str())?;
104        Ok(())
105    }
106}
107
108/// This struct is used to represent a recipient for RedeemWithdrawalTo.
109#[cw_serde]
110pub struct RedeemWithdrawalToParams {
111    pub controller: Addr,
112    pub recipient: Addr,
113}
114
115impl RedeemWithdrawalToParams {
116    /// The recipient must be a valid [`Addr`].
117    /// The controller must be a valid [`Addr`].
118    pub fn validate(&self, api: &dyn Api) -> Result<(), VaultError> {
119        api.addr_validate(self.controller.as_str())?;
120        api.addr_validate(self.recipient.as_str())?;
121        Ok(())
122    }
123}
124
125#[cw_serde]
126pub struct SetApproveProxyParams {
127    /// The proxy address that is being approved.
128    pub proxy: Addr,
129    /// whether the proxy is approved or not.
130    pub approve: bool,
131}
132
133impl SetApproveProxyParams {
134    /// Validate the proxy: [`Addr`] field.
135    /// The proxy must be a valid [`Addr`].
136    pub fn validate(&self, api: &dyn Api) -> Result<(), VaultError> {
137        api.addr_validate(self.proxy.as_str())?;
138        Ok(())
139    }
140}
141
142#[cw_serde]
143#[derive(QueryResponses)]
144pub enum VaultQueryMsg {
145    /// QueryMsg Shares: get the shares of a staker.
146    #[returns(SharesResponse)]
147    Shares { staker: String },
148
149    /// QueryMsg Assets: get the assets of a staker, converted from shares.
150    #[returns(AssetsResponse)]
151    Assets { staker: String },
152
153    /// QueryMsg ConvertToAssets: convert shares to assets.
154    #[returns(ConvertToAssetsResponse)]
155    ConvertToAssets { shares: Uint128 },
156
157    /// QueryMsg ConvertToShares: convert assets to shares.
158    #[returns(ConvertToSharesResponse)]
159    ConvertToShares { assets: Uint128 },
160
161    /// QueryMsg TotalShares: get the total shares in circulation.
162    #[returns(TotalSharesResponse)]
163    TotalShares {},
164
165    /// QueryMsg TotalAssets: get the total assets under vault.
166    #[returns(TotalAssetsResponse)]
167    TotalAssets {},
168
169    /// QueryMsg QueuedWithdrawal: get the queued withdrawal and unlock timestamp under vault.
170    #[returns(QueuedWithdrawalResponse)]
171    QueuedWithdrawal { controller: String },
172
173    /// QueryMsg VaultInfo: get the vault information.
174    #[returns(VaultInfoResponse)]
175    VaultInfo {},
176}
177
178/// The response to the `Shares` query.
179/// This is just a wrapper around `Uint128`, so that the schema can be generated.
180#[cw_serde]
181pub struct SharesResponse(Uint128);
182
183/// The response to the `Assets` query.
184/// This is just a wrapper around `Uint128`, so that the schema can be generated.
185#[cw_serde]
186pub struct AssetsResponse(Uint128);
187
188/// The response to the `ConvertToAssets` query.
189/// This is just a wrapper around `Uint128`, so that the schema can be generated.
190#[cw_serde]
191pub struct ConvertToAssetsResponse(Uint128);
192
193/// The response to the `ConvertToShares` query.
194/// This is just a wrapper around `Uint128`, so that the schema can be generated.
195#[cw_serde]
196pub struct ConvertToSharesResponse(Uint128);
197
198/// The response to the `TotalShares` query.
199/// This is just a wrapper around `Uint128`, so that the schema can be generated.
200#[cw_serde]
201pub struct TotalSharesResponse(Uint128);
202
203/// The response to the `TotalAssets` query.
204/// This is just a wrapper around `Uint128`, so that the schema can be generated.
205#[cw_serde]
206pub struct TotalAssetsResponse(Uint128);
207
208/// The response to the `QueuedWithdrawal` query.
209/// This is just a wrapper around `QueuedWithdrawalInfo`, so that the schema can be generated.
210#[cw_serde]
211pub struct QueuedWithdrawalResponse(QueuedWithdrawalInfo);
212
213#[cw_serde]
214pub struct VaultInfoResponse {
215    /// The total shares in circulation
216    pub total_shares: Uint128,
217
218    /// The total assets under management
219    pub total_assets: Uint128,
220
221    /// The `vault-router` contract address
222    pub router: Addr,
223
224    /// The `pauser` contract address
225    pub pauser: Addr,
226
227    /// The `operator` that this vault is delegated to
228    pub operator: Addr,
229
230    /// Asset identifier, using the CAIP-19 format.
231    pub asset_id: String,
232
233    /// The asset type, either `AssetType::Cw20` or `AssetType::Bank`.
234    pub asset_type: AssetType,
235
236    /// The asset reference stores the cw20 contract address or the bank denom.
237    pub asset_reference: String,
238
239    /// The name of the vault contract, see [`cw2::set_contract_version`] for more information.
240    pub contract: String,
241
242    /// The version of the vault contract, see [`cw2::set_contract_version`] for more information.
243    pub version: String,
244}
245
246#[cw_serde]
247pub enum AssetType {
248    Cw20,
249    Bank,
250}