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}