Skip to content

Commit

Permalink
Fix bugs (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
Art3miX authored Jun 18, 2024
1 parent f87089a commit 3325710
Show file tree
Hide file tree
Showing 25 changed files with 1,197 additions and 125 deletions.
310 changes: 266 additions & 44 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ valence-macros = { path = "packages/valence-macros" }
valence-package = { path = "packages/valence-package" }
auction-package = { path = "packages/auction-package" }

cosmwasm-schema = "1.5.4"
cosmwasm-std = { version = "1.5.4", features = ["ibc3"] }
cosmwasm-schema = "1.5.5"
cosmwasm-std = { version = "1.5.5", features = ["ibc3"] }
cw-storage-plus = "1.2.0"
cw-utils = "1.0.3"
cw2 = "1.1.2"
Expand All @@ -61,5 +61,5 @@ thiserror = "1.0.31"
schemars = "0.8.10"

# dev-dependencies
cw-multi-test = "1.1.0"
cw-multi-test = "1.2.0"
anyhow = { version = "1.0.51" }
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

## Code ids

- auctions manager = `1263`
- auction = `1262`
- oracle = `1261`
- rebalancer = `1260`
- services manager = `1259`
- account = `1258`
- auctions manager = `1404`
- auction = `1408`
- oracle = `1446`
- rebalancer = `1442`
- services manager = `1405`
- account = `1403`

## Owner / Admin

Expand Down
6 changes: 3 additions & 3 deletions contracts/auction/auction/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ mod admin {

// Verify the amount of funds we have to auction, is more then the start auction min amount
let manager_addr = ADMIN.load(deps.storage)?;
let min_start_acution = MIN_AUCTION_AMOUNT
let min_start_auction = MIN_AUCTION_AMOUNT
.query(&deps.querier, manager_addr, config.pair.0.clone())?
.unwrap_or_default()
.start_auction;
Expand All @@ -251,12 +251,12 @@ mod admin {
AUCTION_IDS.save(deps.storage, &auction_ids)?;

// if its less, refund the funds to the users
if total_funds < min_start_acution {
if total_funds < min_start_auction {
return do_refund(
deps,
auction_ids.curr,
config.pair.0.clone(),
min_start_acution,
min_start_auction,
total_funds,
);
}
Expand Down
16 changes: 14 additions & 2 deletions contracts/auction/price_oracle/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ use auction_package::helpers::{
approve_admin_change, cancel_admin_change, start_admin_change, verify_admin,
};
use auction_package::states::{ADMIN, PAIRS, PRICES, TWAP_PRICES};
use auction_package::Price;
use auction_package::{Pair, Price};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{to_json_binary, Binary, Decimal, Deps, DepsMut, Env, MessageInfo, Response};
use cosmwasm_std::{
to_json_binary, Binary, Decimal, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
};
use cw2::set_contract_version;
use cw_storage_plus::Bound;
use valence_package::event_indexing::{ValenceEvent, ValenceGenericEvent};

use crate::error::ContractError;
Expand Down Expand Up @@ -311,6 +314,15 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, ContractErr

Ok(to_json_binary(&price)?)
}
QueryMsg::GetAllPrices { from, limit } => {
let from = from.map(Bound::<Pair>::exclusive);
let prices = PRICES
.range(deps.storage, from, None, cosmwasm_std::Order::Ascending)
.take(limit.unwrap_or(10) as usize)
.collect::<StdResult<Vec<_>>>()?;

Ok(to_json_binary(&prices)?)
}
QueryMsg::GetConfig => {
let config = CONFIG.load(deps.storage)?;
Ok(to_json_binary(&config)?)
Expand Down
9 changes: 7 additions & 2 deletions contracts/auction/price_oracle/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use auction_package::{helpers::GetPriceResponse, Pair};
use auction_package::{Pair, Price};

Check warning on line 1 in contracts/auction/price_oracle/src/msg.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `Price`
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Decimal};
use cw_utils::Expiration;
Expand Down Expand Up @@ -46,8 +46,13 @@ pub enum ExecuteMsg {
#[derive(QueryResponses)]
pub enum QueryMsg {
/// Get the minimum amount users can auction
#[returns(GetPriceResponse)]
#[returns(Price)]
GetPrice { pair: Pair },
#[returns(Vec<(Pair, Price)>)]
GetAllPrices {
from: Option<Pair>,
limit: Option<u32>,
},
#[returns(Config)]
GetConfig,
#[returns(Addr)]
Expand Down
7 changes: 7 additions & 0 deletions contracts/services/rebalancer/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use valence_package::helpers::{approve_admin_change, verify_services_manager, Op
use valence_package::services::rebalancer::{
PauseData, RebalancerExecuteMsg, SystemRebalanceStatus,
};
use valence_package::signed_decimal::SignedDecimal;
use valence_package::states::{QueryFeeAction, ADMIN, SERVICES_MANAGER, SERVICE_FEE_CONFIG};

use crate::error::ContractError;
Expand Down Expand Up @@ -302,6 +303,12 @@ pub fn execute(

if let Some(pid) = data.pid {
config.pid = pid.into_parsed()?;

// If PID is updated, we reset the last calculation because they are no longer valid
config.targets.iter_mut().for_each(|t| {
t.last_input = None;
t.last_i = SignedDecimal::zero();
});
}

if let Some(max_limit_option) = data.max_limit_bps {
Expand Down
2 changes: 1 addition & 1 deletion contracts/services/rebalancer/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub struct TargetHelper {
/// can either be to sell or to buy, depends on the calculation
pub value_to_trade: Decimal,
/// The minimum value we can send to the auction
pub auction_min_amount: Decimal,
pub auction_min_send_value: Decimal,
}

#[cw_serde]
Expand Down
75 changes: 46 additions & 29 deletions contracts/services/rebalancer/src/rebalance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,16 +258,22 @@ pub fn do_rebalance(
env.block.time.seconds() - config.last_rebalance.seconds(),
0,
)?;
(diff / Decimal::from_atomics(cycle_period, 0)?).min(Decimal::new(MAX_PID_DT_VALUE.into()))
(diff.checked_div(Decimal::from_atomics(cycle_period, 0)?))?
.min(Decimal::from_atomics(MAX_PID_DT_VALUE, 0)?)
};

let (mut to_sell, to_buy) = do_pid(total_value, &mut target_helpers, config.pid.clone(), dt)?;

// Save targets to our config
config.targets = target_helpers
.iter_mut()
.map(|th| th.target.clone())
.collect();
// Update targets in config only the last data we need for the next rebalance calculation
for target in config.targets.iter_mut() {
if let Some(target_helper) = target_helpers
.iter()
.find(|th| th.target.denom == target.denom)
{
target.last_i = target_helper.target.last_i;
target.last_input = target_helper.target.last_input;
}
}

// get minimum amount we can send to each auction
set_auction_min_amounts(deps, auction_manager, &mut to_sell, min_amount_limits)?;
Expand Down Expand Up @@ -326,8 +332,8 @@ pub(crate) fn set_auction_min_amounts(
.find(|min_amount| min_amount.0 == sell_token.target.denom)
{
Some(min_amount) => {
sell_token.auction_min_amount =
Decimal::from_atomics(min_amount.1, 0)? / sell_token.price;
sell_token.auction_min_send_value =
Decimal::from_atomics(min_amount.1, 0)?.checked_div(sell_token.price)?;
}
None => {
match MIN_AUCTION_AMOUNT.query(
Expand All @@ -339,8 +345,9 @@ pub(crate) fn set_auction_min_amounts(
send: min_send_amount,
..
}) => {
sell_token.auction_min_amount =
Decimal::from_atomics(min_send_amount, 0)? / sell_token.price;
sell_token.auction_min_send_value =
Decimal::from_atomics(min_send_amount, 0)?
.checked_div(sell_token.price)?;
min_amount_limits.push((sell_token.target.denom.clone(), min_send_amount));
Ok(())
}
Expand Down Expand Up @@ -420,7 +427,8 @@ fn get_inputs(
// Get current balance of the target, and calculate the value
// safe if balance is 0, 0 / price = 0
let current_balance = deps.querier.query_balance(account, target.denom.clone())?;
let balance_value = Decimal::from_atomics(current_balance.amount, 0)? / price;
let balance_value =
Decimal::from_atomics(current_balance.amount, 0)?.checked_div(price)?;

total_value += balance_value;
targets_helpers.push(TargetHelper {
Expand All @@ -429,7 +437,7 @@ fn get_inputs(
price,
balance_value,
value_to_trade: Decimal::zero(),
auction_min_amount: Decimal::zero(),
auction_min_send_value: Decimal::zero(),
});

Ok((total_value, targets_helpers))
Expand Down Expand Up @@ -470,6 +478,7 @@ fn do_pid(
Some(last_input) => signed_input - last_input.into(),
None => SignedDecimal::zero(),
};

d = d * signed_d / signed_dt;

let output = p + i - d;
Expand Down Expand Up @@ -509,7 +518,7 @@ pub fn verify_targets(
// Safe to unwrap here, because we only enter the function is there is a min_balance target
// and we error out if we don't find the target above.
let min_balance = Decimal::from_atomics(target.target.min_balance.unwrap(), 0)?;
let min_balance_target = min_balance * target.price;
let min_balance_target = min_balance / target.price;
let real_target = total_value * target.target.percentage;

// if the target is below the minimum balance target
Expand All @@ -520,7 +529,7 @@ pub fn verify_targets(
let (new_target_perc, mut leftover_perc) = if min_balance_target >= total_value {
(Decimal::one(), Decimal::zero())
} else {
let perc = min_balance_target / total_value;
let perc = min_balance_target.checked_div(total_value)?;
(perc, Decimal::one() - perc)
};

Expand All @@ -529,23 +538,23 @@ pub fn verify_targets(

let updated_targets = targets
.into_iter()
.map(|mut t| {
.map(|mut t| -> Result<TargetHelper, ContractError> {
// If our target is the min_balance target, we update perc, and return t.
if t.target.denom == target.target.denom {
t.target.percentage = new_target_perc;
return t;
return Ok(t);
};

// If leftover perc is 0, we set the perc as zero for this target
if leftover_perc.is_zero() {
t.target.percentage = Decimal::zero();
return t;
return Ok(t);
}

// Calc new perc based on chosen strategy and new min_balance perc
match config.target_override_strategy {
TargetOverrideStrategy::Proportional => {
let old_perc = t.target.percentage / old_leftover_perc;
let old_perc = t.target.percentage.checked_div(old_leftover_perc)?;
t.target.percentage = old_perc * leftover_perc;
}
TargetOverrideStrategy::Priority => {
Expand All @@ -559,9 +568,9 @@ pub fn verify_targets(
}

new_total_perc += t.target.percentage;
t
Ok(t)
})
.collect();
.collect::<Result<Vec<_>, ContractError>>()?;

// If the new percentage is smaller then 0.9999 or higher then 1, we have something wrong in calculation
if new_total_perc > Decimal::one()
Expand Down Expand Up @@ -642,26 +651,26 @@ fn generate_trades_msgs(
// check if the amount we intent to buy, is lower than min_amount of the sell token
// if its not, it will be handled correctly by the main loop.
// but if it is, it means we need to sell other token more then we intent to
if token_buy.value_to_trade < token_sell.auction_min_amount {
if token_buy.value_to_trade < token_sell.auction_min_send_value {
// If the amount we try to sell, is below the auction_min_amount, we need to set it to zero
// else we reduce the auction_min_amount value
if token_sell.value_to_trade < token_sell.auction_min_amount {
if token_sell.value_to_trade < token_sell.auction_min_send_value {
token_sell.value_to_trade = Decimal::zero();
} else {
token_sell.value_to_trade -= token_sell.auction_min_amount;
token_sell.value_to_trade -= token_sell.auction_min_send_value;
}

let pair = Pair::from((
token_sell.target.denom.clone(),
token_buy.target.denom.clone(),
));
let amount = (token_sell.auction_min_amount * token_sell.price).to_uint_ceil();
let amount = (token_sell.auction_min_send_value * token_sell.price).to_uint_ceil();
let trade = RebalanceTrade::new(pair, amount);

token_buy.value_to_trade = Decimal::zero();

if let Ok(msg) = construct_msg(deps, auction_manager.clone(), trade.clone()) {
max_sell -= token_sell.auction_min_amount;
max_sell -= token_sell.auction_min_send_value;
msgs.push(msg);
};
}
Expand Down Expand Up @@ -697,6 +706,10 @@ fn generate_trades_msgs(
// If our sell results in less then min_balance, we sell the difference to hit min_balance
let diff = token_sell.balance_amount - min_balance;

if diff.is_zero() {
return;
}

// Unwrap should be safe here because diff should be a small number
// and directly related to users balance
token_sell.value_to_trade =
Expand All @@ -705,18 +718,20 @@ fn generate_trades_msgs(
}

// If we intent to sell less then our minimum, we set to_trade to be 0 and continue
if token_sell.value_to_trade < token_sell.auction_min_amount {
if token_sell.value_to_trade < token_sell.auction_min_send_value {
token_sell.value_to_trade = Decimal::zero();
return;
}

// If our buy value is lower then our sell min_send value, we do nothing and continue.
if token_buy.value_to_trade < token_sell.auction_min_send_value {
return;
}

// If we hit our max sell limit, we only sell the limit left
// otherwise, we keep track of how much we already sold
if token_sell.value_to_trade > max_sell {
token_sell.value_to_trade = max_sell;
max_sell = Decimal::zero();
} else {
max_sell -= token_sell.value_to_trade;
}

let pair = Pair::from((
Expand All @@ -733,6 +748,7 @@ fn generate_trades_msgs(
token_buy.value_to_trade = Decimal::zero();

let Ok(msg) = construct_msg(deps, auction_manager.clone(), trade.clone()) else {
max_sell -= token_buy.value_to_trade;
return;
};

Expand All @@ -747,6 +763,7 @@ fn generate_trades_msgs(
token_sell.value_to_trade = Decimal::zero();

let Ok(msg) = construct_msg(deps, auction_manager.clone(), trade.clone()) else {
max_sell -= token_sell.value_to_trade;
return;
};

Expand Down
2 changes: 1 addition & 1 deletion contracts/services/rebalancer/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) const DENOM_WHITELIST: Item<HashSet<String>> = Item::new("token_white
/// Base denom whitelist
pub(crate) const BASE_DENOM_WHITELIST: Item<HashSet<BaseDenom>> = Item::new("base_token_whitelist");
/// Storage to keep all configs of all registered accounts
pub(crate) const CONFIGS: Map<Addr, RebalancerConfig> = Map::new("configs");
pub const CONFIGS: Map<Addr, RebalancerConfig> = Map::new("configs");
/// Storage to keep the current status of the system rebalance
pub(crate) const SYSTEM_REBALANCE_STATUS: Item<SystemRebalanceStatus> =
Item::new("system_rebalance_status");
Expand Down
4 changes: 2 additions & 2 deletions devtools/optimize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ if [[ $(uname -m) =~ "arm64" ]]; then \
docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/optimizer-arm64:0.15.0
cosmwasm/optimizer-arm64:0.16.0

else
docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/optimizer:0.15.1
cosmwasm/optimizer:0.16.0
fi
Loading

0 comments on commit 3325710

Please sign in to comment.