Skip to content

Commit 8ae5285

Browse files
authored
Mp 2261 rr neutron (#366)
* Impl price source with rr and twap for staked assets. * Use TWAP for LSD price source. * Update schema. * Stride contract for testing. * Wasm LSD test cases. * Display LSD test case.
1 parent 65901a3 commit 8ae5285

File tree

22 files changed

+624
-84
lines changed

22 files changed

+624
-84
lines changed

Cargo.lock

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

contracts/oracle/base/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ doctest = false
1717
backtraces = ["cosmwasm-std/backtraces"]
1818

1919
[dependencies]
20+
cosmwasm-schema = { workspace = true }
2021
cosmwasm-std = { workspace = true }
2122
cw2 = { workspace = true }
2223
cw-storage-plus = { workspace = true }
24+
ica-oracle = { workspace = true }
2325
mars-owner = { workspace = true }
2426
mars-utils = { workspace = true }
2527
mars-types = { workspace = true }

contracts/oracle/base/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod error;
33
mod traits;
44

55
pub mod pyth;
6+
pub mod redemption_rate;
67

78
pub use contract::*;
89
pub use error::*;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use cosmwasm_schema::cw_serde;
2+
use cosmwasm_std::{to_json_binary, Addr, QuerierWrapper, QueryRequest, StdResult, WasmQuery};
3+
use ica_oracle::msg::{QueryMsg, RedemptionRateResponse};
4+
5+
use crate::{ContractError, ContractError::InvalidPrice};
6+
7+
#[cw_serde]
8+
pub struct RedemptionRate<T> {
9+
/// Contract addr
10+
pub contract_addr: T,
11+
12+
/// The maximum number of seconds since the last price was by an oracle, before
13+
/// rejecting the price as too stale
14+
pub max_staleness: u64,
15+
}
16+
17+
/// How much base_denom we get for 1 denom
18+
///
19+
/// Example:
20+
/// denom: stAtom, base_denom: Atom
21+
/// exchange_rate: 1.0211
22+
/// 1 stAtom = 1.0211 Atom
23+
pub fn query_redemption_rate(
24+
querier: &QuerierWrapper,
25+
contract_addr: Addr,
26+
denom: String,
27+
) -> StdResult<RedemptionRateResponse> {
28+
querier.query(&QueryRequest::Wasm(WasmQuery::Smart {
29+
contract_addr: contract_addr.into_string(),
30+
msg: to_json_binary(&QueryMsg::RedemptionRate {
31+
denom,
32+
params: None,
33+
})?,
34+
}))
35+
}
36+
37+
/// Redemption rate comes from different chain (Stride) and it can be greater than the current block time due to differences in block generation times,
38+
/// network latency, and the asynchronous nature of cross-chain data updates. We accept such case as valid RR.
39+
pub fn assert_rr_not_too_old(
40+
current_time: u64,
41+
rr_res: &RedemptionRateResponse,
42+
rr_config: &RedemptionRate<Addr>,
43+
) -> Result<(), ContractError> {
44+
if rr_res.update_time + rr_config.max_staleness < current_time {
45+
return Err(InvalidPrice {
46+
reason: format!(
47+
"redemption rate update time is too old/stale. last updated: {}, now: {}",
48+
rr_res.update_time, current_time
49+
),
50+
});
51+
}
52+
Ok(())
53+
}

contracts/oracle/osmosis/src/helpers.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use cosmwasm_std::{to_json_binary, Addr, QuerierWrapper, QueryRequest, StdResult, WasmQuery};
2-
use ica_oracle::msg::{QueryMsg, RedemptionRateResponse};
31
use mars_oracle_base::{ContractError, ContractResult};
42
use mars_osmosis::{
53
helpers::{CommonPoolData, Pool},
@@ -133,23 +131,3 @@ pub fn assert_osmosis_twap(
133131

134132
Ok(())
135133
}
136-
137-
/// How much base_denom we get for 1 denom
138-
///
139-
/// Example:
140-
/// denom: stAtom, base_denom: Atom
141-
/// exchange_rate: 1.0211
142-
/// 1 stAtom = 1.0211 Atom
143-
pub fn query_redemption_rate(
144-
querier: &QuerierWrapper,
145-
contract_addr: Addr,
146-
denom: String,
147-
) -> StdResult<RedemptionRateResponse> {
148-
querier.query(&QueryRequest::Wasm(WasmQuery::Smart {
149-
contract_addr: contract_addr.into_string(),
150-
msg: to_json_binary(&QueryMsg::RedemptionRate {
151-
denom,
152-
params: None,
153-
})?,
154-
}))
155-
}

contracts/oracle/osmosis/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@ pub mod msg;
55
mod price_source;
66

77
pub use price_source::{
8-
DowntimeDetector, OsmosisPriceSourceChecked, OsmosisPriceSourceUnchecked, RedemptionRate, Twap,
9-
TwapKind,
8+
DowntimeDetector, OsmosisPriceSourceChecked, OsmosisPriceSourceUnchecked, Twap, TwapKind,
109
};

contracts/oracle/osmosis/src/price_source.rs

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use cosmwasm_std::{
55
Addr, Decimal, Decimal256, Deps, Empty, Env, Isqrt, QuerierWrapper, StdResult, Uint128, Uint256,
66
};
77
use cw_storage_plus::Map;
8-
use ica_oracle::msg::RedemptionRateResponse;
98
use mars_oracle_base::{
9+
redemption_rate::{assert_rr_not_too_old, query_redemption_rate, RedemptionRate},
1010
ContractError::{self, InvalidPrice},
1111
ContractResult, PriceSourceChecked, PriceSourceUnchecked,
1212
};
@@ -19,7 +19,7 @@ use mars_utils::helpers::validate_native_denom;
1919
use osmosis_std::types::osmosis::downtimedetector::v1beta1::Downtime;
2020
use pyth_sdk_cw::PriceIdentifier;
2121

22-
use crate::helpers::{self, query_redemption_rate};
22+
use crate::helpers;
2323

2424
#[cw_serde]
2525
#[derive(Eq)]
@@ -243,16 +243,6 @@ impl Twap {
243243
}
244244
}
245245

246-
#[cw_serde]
247-
pub struct RedemptionRate<T> {
248-
/// Contract addr
249-
pub contract_addr: T,
250-
251-
/// The maximum number of seconds since the last price was by an oracle, before
252-
/// rejecting the price as too stale
253-
pub max_staleness: u64,
254-
}
255-
256246
pub type OsmosisPriceSourceUnchecked = OsmosisPriceSource<String>;
257247
pub type OsmosisPriceSourceChecked = OsmosisPriceSource<Addr>;
258248

@@ -734,7 +724,7 @@ impl OsmosisPriceSourceChecked {
734724
// Check if the redemption rate is not too old
735725
assert_rr_not_too_old(current_time, &rr, redemption_rate)?;
736726

737-
// min from geometric TWAP and exchange rate
727+
// min from TWAP and exchange rate
738728
let min_price = min(staked_price, rr.redemption_rate);
739729

740730
// use current price source
@@ -750,21 +740,3 @@ impl OsmosisPriceSourceChecked {
750740
min_price.checked_mul(transitive_price).map_err(Into::into)
751741
}
752742
}
753-
754-
/// Redemption rate comes from different chain (Stride) and it can be greater than the current block time due to differences in block generation times,
755-
/// network latency, and the asynchronous nature of cross-chain data updates. We accept such case as valid RR.
756-
fn assert_rr_not_too_old(
757-
current_time: u64,
758-
rr_res: &RedemptionRateResponse,
759-
rr_config: &RedemptionRate<Addr>,
760-
) -> Result<(), ContractError> {
761-
if rr_res.update_time + rr_config.max_staleness < current_time {
762-
return Err(InvalidPrice {
763-
reason: format!(
764-
"redemption rate update time is too old/stale. last updated: {}, now: {}",
765-
rr_res.update_time, current_time
766-
),
767-
});
768-
}
769-
Ok(())
770-
}

contracts/oracle/osmosis/tests/tests/test_price_source_fmt.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use cosmwasm_std::{Addr, Decimal};
2-
use mars_oracle_osmosis::{
3-
DowntimeDetector, OsmosisPriceSourceChecked, RedemptionRate, Twap, TwapKind,
4-
};
2+
use mars_oracle_base::redemption_rate::RedemptionRate;
3+
use mars_oracle_osmosis::{DowntimeDetector, OsmosisPriceSourceChecked, Twap, TwapKind};
54
use osmosis_std::types::osmosis::downtimedetector::v1beta1::Downtime;
65
use pyth_sdk_cw::PriceIdentifier;
76

contracts/oracle/osmosis/tests/tests/test_query_price.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use cosmwasm_std::{
77
};
88
use helpers::prepare_query_balancer_pool_response;
99
use ica_oracle::msg::RedemptionRateResponse;
10-
use mars_oracle_base::{pyth::scale_pyth_price, ContractError};
10+
use mars_oracle_base::{pyth::scale_pyth_price, redemption_rate::RedemptionRate, ContractError};
1111
use mars_oracle_osmosis::{
12-
contract::entry, DowntimeDetector, OsmosisPriceSourceUnchecked, RedemptionRate, Twap, TwapKind,
12+
contract::entry, DowntimeDetector, OsmosisPriceSourceUnchecked, Twap, TwapKind,
1313
};
1414
use mars_testing::{mock_env_at_block_time, MarsMockQuerier};
1515
use mars_types::oracle::{PriceResponse, QueryMsg};

contracts/oracle/osmosis/tests/tests/test_set_price_source.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use std::str::FromStr;
22

33
use cosmwasm_std::{testing::mock_env, Addr, Decimal};
4-
use mars_oracle_base::ContractError;
4+
use mars_oracle_base::{redemption_rate::RedemptionRate, ContractError};
55
use mars_oracle_osmosis::{
66
contract::entry::execute,
77
msg::{ExecuteMsg, PriceSourceResponse},
8-
DowntimeDetector, OsmosisPriceSourceChecked, OsmosisPriceSourceUnchecked, RedemptionRate, Twap,
9-
TwapKind,
8+
DowntimeDetector, OsmosisPriceSourceChecked, OsmosisPriceSourceUnchecked, Twap, TwapKind,
109
};
1110
use mars_owner::OwnerError::NotOwner;
1211
use mars_testing::mock_info;

0 commit comments

Comments
 (0)