Skip to content

Commit aa7e964

Browse files
authored
feat(lst): automatic staking and rebasing (#5191)
2 parents 29dc9d5 + 3377a14 commit aa7e964

File tree

18 files changed

+772
-70
lines changed

18 files changed

+772
-70
lines changed

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ members = [
99
"cosmwasm/ibc-union/app/ucs06-funded-dispatch",
1010
"cosmwasm/multicall",
1111
"cosmwasm/lst",
12+
"cosmwasm/lst-staker",
1213

1314
"cosmwasm/ibc-union/core",
1415
"cosmwasm/ibc-union/core/msg",
@@ -390,7 +391,10 @@ ibc-union-msg = { path = "cosmwasm/ibc-union/core/msg", default-feature
390391

391392
frissitheto = { path = "lib/frissitheto", default-features = false }
392393

393-
access-manager = { path = "cosmwasm/access-manager", default-features = false }
394+
access-manager = { path = "cosmwasm/access-manager", default-features = false }
395+
396+
lst = { path = "cosmwasm/lst", default-features = false }
397+
394398
cw-account = { path = "cosmwasm/cw-account", default-features = false }
395399
cw-escrow-vault = { path = "cosmwasm/cw-escrow-vault", default-features = false }
396400
cw-unionversal-token = { path = "cosmwasm/cw-unionversal-token", default-features = false }

cosmwasm/cosmwasm.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,7 @@ _: {
10181018
cw-unionversal-token = crane.buildWasmContract "cosmwasm/cw-unionversal-token" { };
10191019

10201020
lst = crane.buildWasmContract "cosmwasm/lst" { };
1021+
lst-staker = crane.buildWasmContract "cosmwasm/lst-staker" { };
10211022

10221023
access-manager = crane.buildWasmContract "cosmwasm/access-manager" { };
10231024

@@ -1095,6 +1096,7 @@ _: {
10951096
cw-unionversal-token
10961097
lst
10971098
access-manager
1099+
lst-staker
10981100
;
10991101
cosmwasm-scripts =
11001102
{

cosmwasm/cw-account/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ hex-literal = { workspace = true }
3333

3434
[features]
3535
default = []
36+
library = []
3637
schemars = ["dep:schemars"]

cosmwasm/cw-account/src/lib.rs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use std::num::NonZeroU32;
22

33
use cosmwasm_std::{
4-
entry_point, from_json, Addr, CosmosMsg, Deps, DepsMut, Env, Event, MessageInfo, Order,
5-
Response, StdError,
4+
from_json, to_json_binary, Addr, Binary, CosmosMsg, Deps, DepsMut, Env, Event, MessageInfo,
5+
Order, Response, StdError,
66
};
77
use depolama::{self, StorageExt};
88
use frissitheto::{InitStateVersionError, UpgradeError, UpgradeMsg};
99
use ucs03_zkgmable::Zkgmable;
1010

1111
use crate::{
12-
msg::{ExecuteMsg, InitMsg, MigrateMsg},
12+
msg::{ExecuteMsg, InitMsg, MigrateMsg, QueryMsg},
1313
state::{Admins, Zkgm},
1414
types::{Admin, LocalAdmin, RemoteAdmin},
1515
};
@@ -21,27 +21,35 @@ pub mod types;
2121
#[cfg(test)]
2222
mod tests;
2323

24-
fn ensure_remote_admin(deps: Deps, info: &MessageInfo, admin: &RemoteAdmin) -> Result<(), Error> {
24+
pub fn ensure_remote_admin(
25+
deps: Deps,
26+
info: &MessageInfo,
27+
admin: &RemoteAdmin,
28+
) -> Result<(), ContractError> {
2529
// for remote admins, first ensure that info.sender is zkgm
2630
if info.sender
2731
!= deps
2832
.storage
2933
.maybe_read_item::<Zkgm>()?
30-
.ok_or(Error::ZkgmNotConfigured)?
34+
.ok_or(ContractError::ZkgmNotConfigured)?
3135
{
32-
return Err(Error::OnlyZkgm {
36+
return Err(ContractError::OnlyZkgm {
3337
sender: info.sender.clone(),
3438
});
3539
}
3640

3741
deps.storage
3842
.maybe_read::<Admins>(&Admin::Remote(admin.clone()))?
39-
.ok_or_else(|| Error::OnlyAdmin {
43+
.ok_or_else(|| ContractError::OnlyAdmin {
4044
sender: Admin::Remote(admin.clone()),
4145
})
4246
}
4347

44-
fn ensure_local_admin_or_self(deps: Deps, env: &Env, info: &MessageInfo) -> Result<String, Error> {
48+
pub fn ensure_local_admin_or_self(
49+
deps: Deps,
50+
env: &Env,
51+
info: &MessageInfo,
52+
) -> Result<String, ContractError> {
4553
// allow reentrant calls into this contract
4654
if info.sender != env.contract.address {
4755
let local_admin = Admin::Local(LocalAdmin {
@@ -50,7 +58,7 @@ fn ensure_local_admin_or_self(deps: Deps, env: &Env, info: &MessageInfo) -> Resu
5058

5159
deps.storage
5260
.maybe_read::<Admins>(&local_admin)?
53-
.ok_or_else(|| Error::OnlyAdmin {
61+
.ok_or_else(|| ContractError::OnlyAdmin {
5462
sender: Admin::Local(LocalAdmin {
5563
address: info.sender.to_string(),
5664
}),
@@ -62,7 +70,7 @@ fn ensure_local_admin_or_self(deps: Deps, env: &Env, info: &MessageInfo) -> Resu
6270
}
6371
}
6472

65-
fn init(deps: DepsMut, msg: InitMsg) -> Response {
73+
pub fn init(deps: DepsMut, msg: InitMsg) -> Response {
6674
match msg {
6775
InitMsg::Zkgm {
6876
zkgm,
@@ -93,25 +101,25 @@ fn init(deps: DepsMut, msg: InitMsg) -> Response {
93101
Response::default()
94102
}
95103

96-
#[entry_point]
104+
#[cfg_attr(not(feature = "library"), cosmwasm_std::entry_point)]
97105
pub fn instantiate(
98106
mut deps: DepsMut,
99107
_: Env,
100108
_: MessageInfo,
101109
msg: InitMsg,
102-
) -> Result<Response, Error> {
110+
) -> Result<Response, ContractError> {
103111
frissitheto::init_state_version(&mut deps, const { NonZeroU32::new(1).unwrap() })?;
104112

105113
Ok(init(deps, msg))
106114
}
107115

108-
#[entry_point]
116+
#[cfg_attr(not(feature = "library"), cosmwasm_std::entry_point)]
109117
pub fn execute(
110118
deps: DepsMut,
111119
env: Env,
112120
info: MessageInfo,
113121
msg: ExecuteMsg,
114-
) -> Result<Response, Error> {
122+
) -> Result<Response, ContractError> {
115123
match msg {
116124
ExecuteMsg::SetZkgm(zkgm) => {
117125
let actor = ensure_local_admin_or_self(deps.as_ref(), &env, &info)?;
@@ -155,7 +163,7 @@ pub fn execute(
155163
.collect::<Result<Vec<_>, _>>()?
156164
.is_empty()
157165
{
158-
Err(Error::OneAdminRequired)
166+
Err(ContractError::OneAdminRequired)
159167
} else {
160168
Ok(Response::new().add_events(maybe_event))
161169
}
@@ -184,16 +192,29 @@ pub fn execute(
184192
]))
185193
.add_messages(from_json::<Vec<CosmosMsg>>(&on_zkgm.message)?))
186194
}
187-
ExecuteMsg::Zkgmable(Zkgmable::OnIntentZkgm(_)) => Err(Error::IntentsNotSupported),
195+
ExecuteMsg::Zkgmable(Zkgmable::OnIntentZkgm(_)) => Err(ContractError::IntentsNotSupported),
188196
}
189197
}
190198

191-
#[entry_point]
199+
#[cfg_attr(not(feature = "library"), cosmwasm_std::entry_point)]
200+
pub fn query(deps: Deps, _: Env, msg: QueryMsg) -> Result<Binary, ContractError> {
201+
match msg {
202+
QueryMsg::Admins {} => Ok(to_json_binary(
203+
&deps
204+
.storage
205+
.iter::<Admins>(Order::Ascending)
206+
.map(|r| r.map(|(admin, _)| admin))
207+
.collect::<Result<Vec<_>, _>>()?,
208+
)?),
209+
}
210+
}
211+
212+
#[cfg_attr(not(feature = "library"), cosmwasm_std::entry_point)]
192213
pub fn migrate(
193214
deps: DepsMut,
194215
_: Env,
195216
msg: UpgradeMsg<InitMsg, MigrateMsg>,
196-
) -> Result<Response, Error> {
217+
) -> Result<Response, ContractError> {
197218
msg.run(
198219
deps,
199220
|deps, init_msg| {
@@ -205,7 +226,7 @@ pub fn migrate(
205226
}
206227

207228
#[derive(Debug, PartialEq, thiserror::Error)]
208-
pub enum Error {
229+
pub enum ContractError {
209230
#[error(transparent)]
210231
Std(#[from] StdError),
211232

@@ -215,7 +236,7 @@ pub enum Error {
215236
#[error("init state version error: {0}")]
216237
InitStateVersion(#[from] InitStateVersionError),
217238

218-
#[error("sender {sender} is a configured admin")]
239+
#[error("sender {sender} is not a configured admin")]
219240
OnlyAdmin { sender: Admin },
220241

221242
#[error("sender {sender} is not zkgm")]

cosmwasm/cw-account/src/msg.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ pub enum ExecuteMsg {
3232
Zkgmable(Zkgmable),
3333
}
3434

35+
#[derive(Debug, Serialize, Deserialize)]
36+
#[serde(deny_unknown_fields, rename_all = "snake_case")]
37+
pub enum QueryMsg {
38+
Admins {},
39+
}
40+
3541
#[derive(Debug, Serialize, Deserialize)]
3642
#[serde(deny_unknown_fields, rename_all = "snake_case")]
3743
pub struct MigrateMsg {}

cosmwasm/cw-account/src/tests.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ fn only_admin() {
133133
ExecuteMsg::Dispatch(vec![]),
134134
)
135135
.unwrap_err(),
136-
Error::OnlyAdmin {
136+
ContractError::OnlyAdmin {
137137
sender: Admin::Local(LocalAdmin {
138138
address: non_admin.to_string()
139139
})
@@ -150,7 +150,7 @@ fn only_admin() {
150150
})),
151151
)
152152
.unwrap_err(),
153-
Error::OnlyAdmin {
153+
ContractError::OnlyAdmin {
154154
sender: Admin::Local(LocalAdmin {
155155
address: non_admin.to_string()
156156
})
@@ -167,7 +167,7 @@ fn only_admin() {
167167
})),
168168
)
169169
.unwrap_err(),
170-
Error::OnlyAdmin {
170+
ContractError::OnlyAdmin {
171171
sender: Admin::Local(LocalAdmin {
172172
address: non_admin.to_string()
173173
})
@@ -182,7 +182,7 @@ fn only_admin() {
182182
ExecuteMsg::SetZkgm(Addr::unchecked(ZKGM)),
183183
)
184184
.unwrap_err(),
185-
Error::OnlyAdmin {
185+
ContractError::OnlyAdmin {
186186
sender: Admin::Local(LocalAdmin {
187187
address: non_admin.to_string()
188188
})
@@ -383,7 +383,7 @@ fn require_one_admin() {
383383
}))
384384
)
385385
.unwrap_err(),
386-
Error::OneAdminRequired
386+
ContractError::OneAdminRequired
387387
);
388388
}
389389

@@ -411,7 +411,7 @@ fn only_zkgm() {
411411
})),
412412
)
413413
.unwrap_err(),
414-
Error::OnlyZkgm {
414+
ContractError::OnlyZkgm {
415415
sender: relayer.clone()
416416
}
417417
);
@@ -435,7 +435,7 @@ fn only_zkgm() {
435435
})),
436436
)
437437
.unwrap_err(),
438-
Error::OnlyAdmin {
438+
ContractError::OnlyAdmin {
439439
sender: Admin::Remote(RemoteAdmin {
440440
address: b"uhoh".into(),
441441
channel_id: ChannelId!(1),
@@ -462,7 +462,7 @@ fn only_zkgm() {
462462
})),
463463
)
464464
.unwrap_err(),
465-
Error::IntentsNotSupported
465+
ContractError::IntentsNotSupported
466466
);
467467
}
468468

@@ -534,7 +534,7 @@ fn zkgmable_invalid_message() {
534534

535535
assert_eq!(
536536
res,
537-
Error::Std(StdError::parse_err(
537+
ContractError::Std(StdError::parse_err(
538538
"alloc::vec::Vec<cosmwasm_std::results::cosmos_msg::CosmosMsg>",
539539
"EOF while parsing a JSON value."
540540
))
@@ -636,6 +636,6 @@ fn ensure_remote_admin_fails_if_zkgm_not_set() {
636636
})),
637637
)
638638
.unwrap_err(),
639-
Error::ZkgmNotConfigured
639+
ContractError::ZkgmNotConfigured
640640
);
641641
}

cosmwasm/lst-staker/Cargo.toml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[package]
2+
name = "lst-staker"
3+
version = "0.0.0"
4+
5+
authors = { workspace = true }
6+
edition = { workspace = true }
7+
license-file = { workspace = true }
8+
publish = { workspace = true }
9+
repository = { workspace = true }
10+
11+
[lib]
12+
crate-type = ["cdylib", "rlib"]
13+
14+
[lints]
15+
workspace = true
16+
17+
[dependencies]
18+
bincode = { workspace = true, features = ["derive"] }
19+
cosmwasm-std = { workspace = true }
20+
cw-account = { workspace = true, features = ["library"] }
21+
cw-utils = { version = "2.0" }
22+
depolama = { workspace = true, features = ["iterator"] }
23+
embed-commit = { workspace = true }
24+
frissitheto = { workspace = true }
25+
lst = { workspace = true, features = ["library"] }
26+
schemars = { workspace = true, optional = true, features = ["derive"] }
27+
serde = { workspace = true, features = ["derive"] }
28+
thiserror = { workspace = true }
29+
unionlabs-encoding = { workspace = true, features = ["bincode"] }
30+
unionlabs-primitives = { workspace = true, features = ["bincode"] }
31+
32+
[dev-dependencies]
33+
hex-literal = { workspace = true }
34+
35+
[features]
36+
default = []
37+
schemars = ["dep:schemars"]

cosmwasm/lst-staker/README.md

Whitespace-only changes.

0 commit comments

Comments
 (0)