Skip to content

Commit

Permalink
Rebalancer fixes 0.1.7 (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
Art3miX authored Dec 5, 2024
1 parent 97e00c1 commit e2b8f1c
Show file tree
Hide file tree
Showing 35 changed files with 781 additions and 186 deletions.
File renamed without changes.
237 changes: 149 additions & 88 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ members = [
[workspace.package]
edition = "2021"
license = "BSL"
version = "0.1.6"
version = "0.1.7"
repository = "https://github.com/timewave-computer/valence-services"

rust-version = "1.66"
Expand Down
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,33 @@ The Rebalancer sends funds to be auctioned daily. If you are a market maker inte
- [untrn, newt] - `neutron1zvw9l8c82hnvwsntpuy89p86ztfmmudd9usfmnpa2tnqws74zsxq56sczm`
- [uusdc, newt] - `neutron1vu04szc78ae0nplwpuxjr6j592hn2d60zqtuts7w3ah6kajtxd2q2vfv59`

## Audits
## Neutron Testnet Contracts

Valence Services have been rigorously tested and audited. Find audits [here](./audits/)
[![Check Set-Up & Build](https://github.com/timewave-computer/valence-services/actions/workflows/check.yml/badge.svg)](https://github.com/timewave-computer/valence-services/actions/workflows/check.yml)

### Code ids

- auctions-manager - `5673`
- auction - `5679`
- services-manager - `5674`
- rebalancer - `8367`
- oracle - `8371`
- account - `5677`

### Addresses

- Services manager - `neutron13ncggwefau3xla04vlugy20meap7g7a9lf2d2sxwgwvgr9mnn3yqkpjzs6`
- Auctions manager - `neutron1669ftav8rv4hjuak89w04k7f0f7m9qq9564s00ld4m8dvhsr5hfsxy3x46`
- Rebalancer - `neutron1y9aurkegmqlqwhsnwctee4w4aja7n64yuat800p8yys509pyl0fsvrmydm`
- Oracle - `neutron1g4qcmk65nw57hmqlzk6cejnftg20zmctky0l2epdfz3npw3x2cmqprul6f`
- Account - `neutron1gc3tt3edg3drsc3aa22du9pa9f9s2gx6reu2hvq7s6yrdmy8zqjssfj52p`

### Auctions addresses

denom - `factory/neutron1phx0sz708k3t6xdnyc98hgkyhra4tp44et5s68/rebalancer-test`

- [untrn, test] - `neutron10p7d4ca0a5a3plx0d3dw0qmrnldfxwgq8q48205za6pgyhmqqzasg58fg4`
- [test, untrn] - `neutron1s859kh0cgte55fmgtksylw5khv8yxvhslpxmpqdy46fv8q7wxj8qtplru4`

## Security

Expand Down
2 changes: 1 addition & 1 deletion contracts/account/schema/valence-account.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"contract_name": "valence-account",
"contract_version": "0.1.5",
"contract_version": "0.1.7",
"idl_version": "1.0.0",
"instantiate": {
"$schema": "http://json-schema.org/draft-07/schema#",
Expand Down
2 changes: 1 addition & 1 deletion contracts/auction/auction/schema/auction.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"contract_name": "auction",
"contract_version": "0.1.5",
"contract_version": "0.1.7",
"idl_version": "1.0.0",
"instantiate": {
"$schema": "http://json-schema.org/draft-07/schema#",
Expand Down
21 changes: 14 additions & 7 deletions contracts/auction/auctions_manager/schema/auctions-manager.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"contract_name": "auctions-manager",
"contract_version": "0.1.5",
"contract_version": "0.1.7",
"idl_version": "1.0.0",
"instantiate": {
"$schema": "http://json-schema.org/draft-07/schema#",
Expand Down Expand Up @@ -185,12 +185,6 @@
"definitions": {
"AdminMsgs": {
"oneOf": [
{
"type": "string",
"enum": [
"cancel_admin_change"
]
},
{
"type": "object",
"required": [
Expand Down Expand Up @@ -488,6 +482,19 @@
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"cancel_admin_change"
],
"properties": {
"cancel_admin_change": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
}
]
},
Expand Down
65 changes: 64 additions & 1 deletion contracts/auction/price_oracle/schema/price-oracle.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"contract_name": "price-oracle",
"contract_version": "0.1.5",
"contract_version": "0.1.7",
"idl_version": "1.0.0",
"instantiate": {
"$schema": "http://json-schema.org/draft-07/schema#",
Expand Down Expand Up @@ -359,6 +359,27 @@
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"get_local_price"
],
"properties": {
"get_local_price": {
"type": "object",
"required": [
"pair"
],
"properties": {
"pair": {
"$ref": "#/definitions/Pair"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
Expand Down Expand Up @@ -522,6 +543,48 @@
}
}
},
"get_local_price": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Array_of_Price",
"type": "array",
"items": {
"$ref": "#/definitions/Price"
},
"definitions": {
"Decimal": {
"description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)",
"type": "string"
},
"Price": {
"type": "object",
"required": [
"price",
"time"
],
"properties": {
"price": {
"$ref": "#/definitions/Decimal"
},
"time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
},
"get_price": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Price",
Expand Down
76 changes: 58 additions & 18 deletions contracts/auction/price_oracle/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ use valence_package::event_indexing::{ValenceEvent, ValenceGenericEvent};

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use crate::state::{Config, PriceStep, ASTRO_PRICE_PATHS, CONFIG};
use crate::state::{Config, PriceStep, ASTRO_PRICE_PATHS, CONFIG, LOCAL_PRICES};

const CONTRACT_NAME: &str = "crates.io:oracle";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

const TWAP_PRICE_MAX_LEN: usize = 10;

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
Expand All @@ -47,7 +49,7 @@ pub fn instantiate(

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
mut deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
Expand All @@ -58,20 +60,22 @@ pub fn execute(

let config = CONFIG.load(deps.storage)?;

// We get the prices from the auction
let auction_addr = PAIRS
.query(
&deps.querier,
config.auction_manager_addr.clone(),
pair.clone(),
)?
.ok_or(ContractError::PairAuctionNotFound)?;
let twap_prices = TWAP_PRICES.query(&deps.querier, auction_addr)?;
let auction_twap_prices = TWAP_PRICES.query(&deps.querier, auction_addr)?;

let source;

let price = if can_update_price_from_auction(&config, &env, &twap_prices) {
// We get last price either form auction or astroport
let last_price = if can_update_price_from_auction(&config, &env, &auction_twap_prices) {
source = "auction";
get_avg_price(twap_prices)
auction_twap_prices[0].clone()
} else {
let steps = ASTRO_PRICE_PATHS
.load(deps.storage, pair.clone())
Expand All @@ -80,12 +84,17 @@ pub fn execute(
get_price_from_astroport(deps.as_ref(), &env, steps)?
};

let local_prices = update_local_price(deps.branch(), pair.clone(), last_price.clone())?;

// Calculate the average price
let avg_price = get_avg_price(local_prices);

// Save price
PRICES.save(deps.storage, pair.clone(), &price)?;
PRICES.save(deps.storage, pair.clone(), &avg_price)?;

let event = ValenceEvent::OracleUpdatePrice {
pair: pair.clone(),
price: price.price,
price: avg_price.price,
source: source.to_string(),
};

Expand Down Expand Up @@ -120,19 +129,21 @@ pub fn execute(
Err(_) => Ok(()),
}?;

let price = Price {
price,
time: env.block.time,
};
let local_prices = update_local_price(deps.branch(), pair.clone(), price.clone())?;

// Calculate the average price
let avg_price = get_avg_price(local_prices);

// Save price
PRICES.save(
deps.storage,
pair.clone(),
&Price {
price,
time: env.block.time,
},
)?;
PRICES.save(deps.storage, pair.clone(), &avg_price)?;

let event = ValenceEvent::OracleUpdatePrice {
pair,
price,
price: price.price,
source: "manual".to_string(),
};

Expand Down Expand Up @@ -248,6 +259,30 @@ fn can_update_price_from_auction(
true
}

fn update_local_price(
deps: DepsMut,
pair: Pair,
price: Price,
) -> Result<VecDeque<Price>, cosmwasm_std::StdError> {
// Update the oracle local prices and add last price
let mut local_prices = match LOCAL_PRICES.load(deps.storage, pair.clone()) {
Ok(prices) => prices,
Err(_) => VecDeque::new(),
};

// if we have the max amount of prices already, remove the last one first
if local_prices.len() >= TWAP_PRICE_MAX_LEN {
local_prices.pop_back();
}

// Push the last price into the vector
local_prices.push_front(price.clone());

// Save the new list of prices
LOCAL_PRICES.save(deps.storage, pair.clone(), &local_prices)?;
Ok(local_prices)
}

fn get_avg_price(vec: VecDeque<Price>) -> Price {
let (total_count, prices_sum) = vec.iter().fold(
(Decimal::zero(), Decimal::zero()),
Expand Down Expand Up @@ -288,8 +323,8 @@ fn get_price_from_astroport(
.checked_add(res.spread_amount)?,
0,
)?;
deps.api.debug(format!("res: {:?}", res).as_str());
deps.api.debug(format!("Price step: {:?}", price).as_str());
// deps.api.debug(format!("res: {:?}", res).as_str());
// deps.api.debug(format!("Price step: {:?}", price).as_str());

Ok(price)
},
Expand All @@ -314,6 +349,11 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, ContractErr

Ok(to_json_binary(&price)?)
}
QueryMsg::GetLocalPrice { pair } => {
let price: Vec<Price> = LOCAL_PRICES.load(deps.storage, pair)?.into();

Ok(to_json_binary(&price)?)
}
QueryMsg::GetAllPrices { from, limit } => {
let from = from.map(Bound::<Pair>::exclusive);
let prices = PRICES
Expand Down
2 changes: 2 additions & 0 deletions contracts/auction/price_oracle/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub enum QueryMsg {
/// Get the minimum amount users can auction
#[returns(Price)]
GetPrice { pair: Pair },
#[returns(Vec<Price>)]
GetLocalPrice { pair: Pair },
#[returns(Vec<(Pair, Price)>)]
GetAllPrices {
from: Option<Pair>,
Expand Down
6 changes: 5 additions & 1 deletion contracts/auction/price_oracle/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use auction_package::Pair;
use std::collections::VecDeque;

use auction_package::{Pair, Price};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use cw_storage_plus::{Item, Map};

pub const CONFIG: Item<Config> = Item::new("config");
pub const ASTRO_PRICE_PATHS: Map<Pair, Vec<PriceStep>> = Map::new("astro_price_paths");
/// Local last 10 prices to be calculated for the average
pub const LOCAL_PRICES: Map<Pair, VecDeque<Price>> = Map::new("local_prices");

#[cw_serde]
pub struct Config {
Expand Down
Loading

0 comments on commit e2b8f1c

Please sign in to comment.