Skip to content

Commit

Permalink
Merge branch 'main' into feat/cii-15
Browse files Browse the repository at this point in the history
  • Loading branch information
ajansari95 authored Jul 19, 2024
2 parents 311c6c5 + 82e8de4 commit 9a56734
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 131 deletions.
10 changes: 10 additions & 0 deletions smart-contracts/contracts/cl-vault/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ use crate::reply::Replies;
#[allow(deprecated)]
use crate::state::CURRENT_BALANCE;
#[allow(deprecated)]
use crate::state::CURRENT_SWAP;
#[allow(deprecated)]
use crate::state::{
MigrationStatus, VaultConfig, MIGRATION_STATUS, OLD_VAULT_CONFIG, STRATEGIST_REWARDS,
VAULT_CONFIG,
Expand Down Expand Up @@ -289,6 +291,8 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, Co
OLD_POSITION.remove(deps.storage);
#[allow(deprecated)]
CURRENT_BALANCE.remove(deps.storage);
#[allow(deprecated)]
CURRENT_SWAP.remove(deps.storage);

Ok(response)
}
Expand Down Expand Up @@ -364,6 +368,8 @@ mod tests {
OLD_POSITION.remove(deps.storage);
#[allow(deprecated)]
CURRENT_BALANCE.remove(deps.storage);
#[allow(deprecated)]
CURRENT_SWAP.remove(deps.storage);

Ok(response)
}
Expand Down Expand Up @@ -418,6 +424,10 @@ mod tests {
#[allow(deprecated)]
let current_balance = CURRENT_BALANCE.may_load(deps.as_mut().storage).unwrap();
assert!(current_balance.is_none());

#[allow(deprecated)]
let current_swap = CURRENT_SWAP.may_load(deps.as_mut().storage).unwrap();
assert!(current_swap.is_none());
}

#[test]
Expand Down
10 changes: 0 additions & 10 deletions smart-contracts/contracts/cl-vault/src/helpers/getters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,6 @@ pub fn get_single_sided_deposit_0_to_1_swap_amount(
current_tick: i64,
upper_tick: i64,
) -> Result<Uint128, ContractError> {
// TODO error here if this condition holds
// if current_tick < lower_tick {
// return ;
// }

let lower_price = tick_to_price(lower_tick)?;
let current_price = tick_to_price(current_tick)?;
let upper_price = tick_to_price(upper_tick)?;
Expand All @@ -157,11 +152,6 @@ pub fn get_single_sided_deposit_0_to_1_swap_amount(
let lower_price_sqrt = lower_price.sqrt();
let upper_price_sqrt = upper_price.sqrt();

// let pool_metadata_constant: Decimal256 = cur_price_sqrt
// .checked_mul(lower_price_sqrt)?
// .checked_mul(cur_price_sqrt.checked_sub(lower_price_sqrt)?)?
// .checked_div(upper_price_sqrt.checked_sub(cur_price_sqrt)?)?;

let pool_metadata_constant: Decimal256 = (upper_price_sqrt
.checked_mul(cur_price_sqrt)?
.checked_mul(cur_price_sqrt.checked_sub(lower_price_sqrt)?))?
Expand Down
4 changes: 3 additions & 1 deletion smart-contracts/contracts/cl-vault/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub const USER_REWARDS: Map<Addr, CoinList> = Map::new("user_rewards");
#[deprecated]
pub const CURRENT_BALANCE: Item<(Uint128, Uint128)> = Item::new("current_balance"); // CURRENT_BALANCE is intended as CURRENT_SWAP_BALANCE

#[deprecated]
pub const CURRENT_SWAP: Item<(SwapDirection, Uint128)> = Item::new("current_swap");

/// metadata useful for display purposes
#[cw_serde]
pub struct Metadata {
Expand Down Expand Up @@ -134,7 +137,6 @@ pub enum RewardsStatus {
}

/// Swap helper states
pub const CURRENT_SWAP: Item<(SwapDirection, Uint128)> = Item::new("current_swap");
pub const CURRENT_SWAP_ANY_DEPOSIT: Item<(SwapDirection, Uint128, Addr, (Uint128, Uint128))> =
Item::new("current_swap_any_deposit");

Expand Down
192 changes: 72 additions & 120 deletions smart-contracts/contracts/cl-vault/src/vault/range.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
helpers::{
assert::assert_range_admin,
generic::extract_attribute_value_by_ty_and_key,
getters::{
get_single_sided_deposit_0_to_1_swap_amount,
get_single_sided_deposit_1_to_0_swap_amount, get_tokens_provided, get_twap_price,
Expand All @@ -13,7 +12,7 @@ use crate::{
msg::{ExecuteMsg, MergePositionMsg},
reply::Replies,
state::{
ModifyRangeState, Position, SwapDepositMergeState, CURRENT_SWAP, MODIFY_RANGE_STATE,
ModifyRangeState, PoolConfig, Position, SwapDepositMergeState, MODIFY_RANGE_STATE,
POOL_CONFIG, POSITION, SWAP_DEPOSIT_MERGE_STATE,
},
vault::{
Expand All @@ -24,12 +23,11 @@ use crate::{
};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{
attr, to_json_binary, Coin, Decimal, Decimal256, DepsMut, Env, Fraction, MessageInfo, Response,
attr, to_json_binary, Decimal, Decimal256, DepsMut, Env, Fraction, MessageInfo, Response,
SubMsg, SubMsgResult, Uint128,
};
use osmosis_std::types::osmosis::{
concentratedliquidity::v1beta1::{MsgCreatePositionResponse, MsgWithdrawPosition},
gamm::v1beta1::MsgSwapExactAmountInResponse,
poolmanager::v1beta1::SwapAmountInRoute,
};
use std::str::FromStr;
Expand Down Expand Up @@ -284,9 +282,13 @@ pub fn do_swap_deposit_merge(
},
)?;

let pool_config = POOL_CONFIG.load(deps.storage)?;
let pool_details = get_cl_pool_info(&deps.querier, pool_config.pool_id)?;
let swap_calc_result = calculate_swap_amount(
deps,
env,
&pool_config,
pool_details.current_tick,
position_id,
balance0,
balance1,
Expand Down Expand Up @@ -327,28 +329,27 @@ pub fn do_swap_deposit_merge(
fn calculate_swap_amount(
deps: DepsMut,
env: Env,
pool_config: &PoolConfig,
current_tick: i64,
position_id: Option<u64>,
balance0: Uint128,
balance1: Uint128,
target_lower_tick: i64,
target_upper_tick: i64,
twap_window_seconds: u64,
) -> Result<Option<SwapCalculationResult>, ContractError> {
let pool_config = POOL_CONFIG.load(deps.storage)?;
let pool_details = get_cl_pool_info(&deps.querier, pool_config.pool_id)?;

//TODO: further optimizations can be made by increasing the swap amount by half of our expected slippage,
// to reduce the total number of non-deposited tokens that we will then need to refund
let (token_in_amount, swap_direction) = if !balance0.is_zero() {
(
// range is above current tick
if pool_details.current_tick > target_upper_tick {
if current_tick > target_upper_tick {
balance0
} else {
get_single_sided_deposit_0_to_1_swap_amount(
balance0,
target_lower_tick,
pool_details.current_tick,
current_tick,
target_upper_tick,
)?
},
Expand All @@ -357,13 +358,13 @@ fn calculate_swap_amount(
} else if !balance1.is_zero() {
(
// current tick is above range
if pool_details.current_tick < target_lower_tick {
if current_tick < target_lower_tick {
balance1
} else {
get_single_sided_deposit_1_to_0_swap_amount(
balance1,
target_lower_tick,
pool_details.current_tick,
current_tick,
target_upper_tick,
)?
},
Expand Down Expand Up @@ -392,34 +393,29 @@ fn calculate_swap_amount(

// TODO: check that this math is right with spot price (numerators, denominators) if taken by legacy gamm module instead of poolmanager
let twap_price = get_twap_price(deps.storage, &deps.querier, &env, twap_window_seconds)?;
let (token_in_denom, token_out_denom, token_out_ideal_amount, left_over_amount) =
match swap_direction {
SwapDirection::ZeroToOne => (
&pool_config.token0,
&pool_config.token1,
token_in_amount
.checked_multiply_ratio(twap_price.numerator(), twap_price.denominator()),
balance0.checked_sub(token_in_amount)?,
),
SwapDirection::OneToZero => (
&pool_config.token1,
&pool_config.token0,
token_in_amount
.checked_multiply_ratio(twap_price.denominator(), twap_price.numerator()),
balance1.checked_sub(token_in_amount)?,
),
};

CURRENT_SWAP.save(deps.storage, &(swap_direction, left_over_amount))?;
let (token_in_denom, token_out_denom, token_out_ideal_amount) = match swap_direction {
SwapDirection::ZeroToOne => (
&pool_config.token0,
&pool_config.token1,
token_in_amount
.checked_multiply_ratio(twap_price.numerator(), twap_price.denominator()),
),
SwapDirection::OneToZero => (
&pool_config.token1,
&pool_config.token0,
token_in_amount
.checked_multiply_ratio(twap_price.denominator(), twap_price.numerator()),
),
};

let mrs = MODIFY_RANGE_STATE.load(deps.storage)?.unwrap();
let token_out_min_amount = token_out_ideal_amount?
.checked_multiply_ratio(mrs.max_slippage.numerator(), mrs.max_slippage.denominator())?;

if !pool_config.pool_contains_token(token_in_denom) {
return Err(ContractError::BadTokenForSwap {
base_token: pool_config.token0,
quote_token: pool_config.token1,
base_token: pool_config.token0.clone(),
quote_token: pool_config.token1.clone(),
});
}

Expand Down Expand Up @@ -452,99 +448,55 @@ pub fn handle_swap_reply(
data: SubMsgResult,
) -> Result<Response, ContractError> {
match data.clone() {
SubMsgResult::Ok(msg) => {
let resp: Result<MsgSwapExactAmountInResponse, _> = data.try_into();
let tokens_out: Result<String, ContractError> = match resp {
Ok(msg) => Ok(msg.token_out_amount),
Err(_) => {
let tokens_out_opt = extract_attribute_value_by_ty_and_key(
&msg.events,
"token_swapped",
"tokens_out",
);

match tokens_out_opt {
Some(tokens_out) => {
let token_out_coin = Coin::from_str(&tokens_out);
Ok(token_out_coin?.amount.to_string())
}
None => {
return Err(ContractError::SwapFailed {
message: "No tokens_out attribute found in swap response"
.to_string(),
})
}
}
}
SubMsgResult::Ok(_) => {
let swap_deposit_merge_state = match SWAP_DEPOSIT_MERGE_STATE.may_load(deps.storage)? {
Some(swap_deposit_merge) => swap_deposit_merge,
None => return Err(ContractError::SwapDepositMergeStateNotFound {}),
};
handle_swap_success_reply(deps, env, tokens_out?)

let pool_config = POOL_CONFIG.load(deps.storage)?;
let unused_pair_balances = get_unused_pair_balances(&deps, &env, &pool_config)?;
let tokens_provided =
get_tokens_provided(unused_pair_balances.0, unused_pair_balances.1, &pool_config)?;

let create_position_msg = create_position(
deps,
&env,
swap_deposit_merge_state.target_lower_tick,
swap_deposit_merge_state.target_upper_tick,
tokens_provided,
Uint128::zero(),
Uint128::zero(),
)?;

Ok(Response::new()
.add_submessage(SubMsg::reply_on_success(
create_position_msg,
Replies::RangeIterationCreatePosition.into(),
))
.add_attribute("method", "reply")
.add_attribute("action", "handle_swap_success")
.add_attribute(
"lower_tick",
swap_deposit_merge_state.target_lower_tick.to_string(),
)
.add_attribute(
"upper_tick",
swap_deposit_merge_state.target_upper_tick.to_string(),
)
.add_attribute(
"token0",
format!("{:?}{:?}", unused_pair_balances.0, pool_config.token0),
)
.add_attribute(
"token1",
format!("{:?}{:?}", unused_pair_balances.1, pool_config.token1),
))
}
SubMsgResult::Err(msg) => Err(ContractError::SwapFailed { message: msg }),
}
}

fn handle_swap_success_reply(
deps: DepsMut,
env: Env,
tokens_out: String,
) -> Result<Response, ContractError> {
let swap_deposit_merge_state = match SWAP_DEPOSIT_MERGE_STATE.may_load(deps.storage)? {
Some(swap_deposit_merge) => swap_deposit_merge,
None => return Err(ContractError::SwapDepositMergeStateNotFound {}),
};
let (swap_direction, left_over_amount) = CURRENT_SWAP.load(deps.storage)?;

let pool_config = POOL_CONFIG.load(deps.storage)?;
let _modify_range_state = MODIFY_RANGE_STATE.load(deps.storage)?.unwrap();

// get post swap balances to create positions with
let (balance0, balance1): (Uint128, Uint128) = match swap_direction {
SwapDirection::ZeroToOne => (left_over_amount, Uint128::new(tokens_out.parse()?)),
SwapDirection::OneToZero => (Uint128::new(tokens_out.parse()?), left_over_amount),
};
// Create the position after swapped the leftovers based on swap direction
let mut coins_to_send = vec![];
if !balance0.is_zero() {
coins_to_send.push(Coin {
denom: pool_config.token0.clone(),
amount: balance0,
});
}
if !balance1.is_zero() {
coins_to_send.push(Coin {
denom: pool_config.token1.clone(),
amount: balance1,
});
}
let create_position_msg = create_position(
deps,
&env,
swap_deposit_merge_state.target_lower_tick,
swap_deposit_merge_state.target_upper_tick,
coins_to_send,
Uint128::zero(),
Uint128::zero(),
)?;

Ok(Response::new()
.add_submessage(SubMsg::reply_on_success(
create_position_msg,
Replies::RangeIterationCreatePosition.into(),
))
.add_attribute("method", "reply")
.add_attribute("action", "handle_swap_success")
.add_attribute(
"lower_tick",
format!("{:?}", swap_deposit_merge_state.target_lower_tick),
)
.add_attribute(
"upper_tick",
format!("{:?}", swap_deposit_merge_state.target_upper_tick),
)
.add_attribute("token0", format!("{:?}{:?}", balance0, pool_config.token0))
.add_attribute("token1", format!("{:?}{:?}", balance1, pool_config.token1)))
}

// do merge position & exit
pub fn handle_iteration_create_position_reply(
deps: DepsMut,
Expand All @@ -568,7 +520,7 @@ pub fn handle_iteration_create_position_reply(
ExecuteMsg::VaultExtension(crate::msg::ExtensionExecuteMsg::Merge(MergePositionMsg {
position_ids: swap_deposit_merge_state.target_range_position_ids.clone(),
}));
// merge our position with the main position

let merge_submsg = SubMsg::reply_on_success(
cosmwasm_std::WasmMsg::Execute {
contract_addr: env.contract.address.to_string(),
Expand Down

0 comments on commit 9a56734

Please sign in to comment.