bvs_vault_router/
msg.rs

1use crate::state::SlashingRequest;
2use bvs_library::slashing::SlashingRequestId;
3use cosmwasm_schema::{cw_serde, QueryResponses};
4use cosmwasm_std::{from_json, to_json_binary, Addr, Binary, Timestamp, Uint128, Uint64};
5
6#[cw_serde]
7pub struct MigrateMsg {
8    pub guardrail: String,
9}
10
11#[cw_serde]
12pub struct InstantiateMsg {
13    pub owner: String,
14    pub registry: String,
15    pub pauser: String,
16    pub guardrail: String,
17}
18
19#[cw_serde]
20#[derive(bvs_pauser::api::Display)]
21pub enum ExecuteMsg {
22    /// ExecuteMsg SetVault the vault contract in the router and whitelist (true/false) it.
23    /// Only the `owner` can call this message.
24    SetVault { vault: String, whitelisted: bool },
25
26    /// ExecuteMsg SetWithdrawalLockPeriod the lock period for withdrawal.
27    /// Only the `owner` can call this message.
28    SetWithdrawalLockPeriod(Uint64),
29
30    /// ExecuteMsg TransferOwnership
31    /// See [`bvs_library::ownership::transfer_ownership`] for more information on this field
32    TransferOwnership { new_owner: String },
33
34    /// ExecuteMsg RequestSlashing initiates a slashing request against an active operator of the service (info.sender).
35    ///
36    /// This ExecuteMsg allows a registered service to request a slash of an operator's staked tokens
37    /// as a penalty for violations or non-compliance. The slashing request must meet several criteria:
38    ///
39    /// - The service must be actively registered with the operator at the specified timestamp
40    /// - The slashing amount (in bips) must not exceed the max_slashing_bips set by the service
41    /// - The operator must have opted in to slashing at the specified timestamp
42    /// - The timestamp must be within the allowable slashing window (not too old or in the future)
43    /// - The service must not have another active slashing request against the same operator
44    /// - The reason provided in metadata must not exceed the maximum allowed length
45    ///
46    /// When successful, this creates a slashing request with an expiry time based on the
47    /// resolution_window parameter and returns a unique slashing request ID.
48    ///
49    /// #### Returns
50    /// On success, returns events with a data field set as [`RequestSlashingResponse`] containing the generated slashing request ID.
51    RequestSlashing(RequestSlashingPayload),
52
53    /// ExecuteMsg LockSlashing initiates the movement of slashed collateral from vaults to the
54    /// router which will later be finalized and handle according to the service slashing
55    /// rules.
56    LockSlashing(SlashingRequestId),
57
58    /// ExecuteMsg CancelSlashing cancels a resolved slashing request.
59    ///
60    /// The service (slash initiator) should cancel the slashing process if the operator
61    /// has resolved the issue. The definition of “resolved” is up to the service to define.
62    CancelSlashing(SlashingRequestId),
63
64    /// ExecuteMsg FinalizeSlashing moves the slashed collateral from the router to the destination
65    /// specified in the slashing parameters that were agreed upon by the service and operator.
66    ///
67    /// This is the final step in the slashing process
68    /// and should only be called after the request has been locked,
69    /// and the guardrail proposal has been voted on and passed.
70    FinalizeSlashing(SlashingRequestId),
71}
72
73#[cw_serde]
74pub struct RequestSlashingResponse(pub SlashingRequestId);
75
76impl From<RequestSlashingResponse> for Binary {
77    fn from(response: RequestSlashingResponse) -> Self {
78        to_json_binary(&response).unwrap()
79    }
80}
81
82impl From<Binary> for RequestSlashingResponse {
83    fn from(binary: Binary) -> Self {
84        from_json(&binary).unwrap()
85    }
86}
87
88#[cw_serde]
89pub struct RequestSlashingPayload {
90    /// The operator address to slash.
91    /// (service, operator) must have active registration at the timestamp.
92    pub operator: String,
93    /// The percentage of tokens to slash in basis points (1/100th of a percent).
94    /// Max bips to slash is set by the service slashing parameters at the timestamp and the operator
95    /// must have opted in.
96    pub bips: u16,
97    /// The timestamp at which the slashing condition occurred.
98    pub timestamp: Timestamp,
99    /// Additional contextual information about the slashing request.
100    pub metadata: SlashingMetadata,
101}
102
103#[cw_serde]
104pub struct SlashingMetadata {
105    /// The reason for the slashing request.
106    /// Must contain human-readable string.
107    /// Max length of 250 characters, empty string is allowed but not recommended.
108    pub reason: String,
109}
110
111#[cw_serde]
112#[derive(QueryResponses)]
113pub enum QueryMsg {
114    /// QueryMsg IsWhitelisted: returns true if the vault is whitelisted.
115    /// See [`ExecuteMsg::SetVault`]
116    #[returns(IsWhitelistedResponse)]
117    IsWhitelisted { vault: String },
118
119    /// QueryMsg IsValidating: returns true if the operator is validating services.
120    /// See BVS Registry for more information.
121    #[returns(IsValidatingResponse)]
122    IsValidating { operator: String },
123
124    /// QueryMsg ListVaults: returns a list of vaults.
125    /// You can provide `limit` and `start_after` to paginate the results.
126    /// The max `limit` is 100.
127    #[returns(VaultListResponse)]
128    ListVaults {
129        limit: Option<u32>,
130        start_after: Option<String>,
131    },
132
133    /// QueryMsg ListVaultsByOperator: returns a list of vaults managed by given operator.
134    /// You can provide `limit` and `start_after` to paginate the results.
135    /// The max `limit` is 100.
136    #[returns(VaultListResponse)]
137    ListVaultsByOperator {
138        operator: String,
139        limit: Option<u32>,
140        start_after: Option<String>,
141    },
142
143    /// QueryMsg WithdrawalLockPeriod: returns the withdrawal lock period.
144    #[returns(WithdrawalLockPeriodResponse)]
145    WithdrawalLockPeriod {},
146
147    #[returns(SlashingRequestIdResponse)]
148    SlashingRequestId { service: String, operator: String },
149
150    #[returns(SlashingRequestResponse)]
151    SlashingRequest(SlashingRequestId),
152
153    #[returns(SlashingLockedResponse)]
154    SlashingLocked {
155        slashing_request_id: SlashingRequestId,
156    },
157}
158
159/// The response to the `IsWhitelisted` query.
160/// Not exported.
161/// This is just a wrapper around `bool`, so that the schema can be generated.
162#[cw_serde]
163struct IsWhitelistedResponse(bool);
164
165/// The response to the `IsValidating` query.
166/// Not exported.
167/// This is just a wrapper around `bool`, so that the schema can be generated.
168#[cw_serde]
169struct IsValidatingResponse(bool);
170
171/// The response to the `ListVaults` query.
172/// For pagination, the `start_after` field is the last `vault` from the previous page.
173#[cw_serde]
174pub struct VaultListResponse(pub Vec<Vault>);
175
176#[cw_serde]
177pub struct Vault {
178    pub vault: Addr,
179    pub whitelisted: bool,
180}
181
182/// The response to the `WithdrawalLockPeriod` query.
183/// Not exported.
184/// This is just a wrapper around `Uint64`, so that the schema can be generated.
185#[cw_serde]
186struct WithdrawalLockPeriodResponse(Uint64);
187
188#[cw_serde]
189pub struct SlashingRequestIdResponse(pub Option<SlashingRequestId>);
190
191#[cw_serde]
192pub struct SlashingRequestResponse(pub Option<SlashingRequest>);
193
194#[cw_serde]
195pub struct SlashingLockedResponse(pub Vec<SlashingLockedResponseItem>);
196
197#[cw_serde]
198pub struct SlashingLockedResponseItem {
199    pub vault: Addr,
200    pub amount: Uint128,
201}