Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/swap opt cw dex 040 #619

Merged
merged 46 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
57f9c3b
cw dex impl refactor after 0.4.0 upstream v bump
magiodev Jun 20, 2024
55393ba
minor bumps, not stable due to uknown Pool osmosis variant
magiodev Jun 20, 2024
e3698fd
add cw-dex-router to monorepo
LaurensKubat Jun 21, 2024
5ac27a5
add cw-dex-router to workspace
LaurensKubat Jun 21, 2024
a21a33d
optimizer v16
magiodev Jun 24, 2024
a16c582
Merge remote-tracking branch 'origin/feat/swap_opt_cw_dex_040' into f…
magiodev Jun 24, 2024
92fa456
Add dex router
lubkoll Jun 24, 2024
43aa5a3
Enable Basic CI
lubkoll Jun 24, 2024
be9762e
Fix error naming and remove redundant into()
lubkoll Jun 24, 2024
2627e8c
Remove unused code
lubkoll Jun 25, 2024
f2ff77a
Remove id for storing paths
lubkoll Jun 25, 2024
fdab6a2
Reenable query of best path
lubkoll Jun 25, 2024
1474520
Improve naming
lubkoll Jun 25, 2024
7a5a0b1
Replace assets with denoms, add set_path checks and enable finding of…
lubkoll Jun 25, 2024
f19dc3d
Renaming, improve feedback when query fails due to missing path
lubkoll Jun 25, 2024
96b05d1
Fix keys for paths
lubkoll Jun 25, 2024
81ff39e
Address linter complaints
lubkoll Jun 25, 2024
538459a
Rename dex-router to dex-router-osmosis
lubkoll Jun 25, 2024
57c9f25
Improve checks for set_path
lubkoll Jun 25, 2024
e5adc68
Add event to set_path
lubkoll Jun 25, 2024
f248b79
Merge remote-tracking branch 'origin/feat/dex-router' into feat/swap_…
magiodev Jun 26, 2024
987a1b8
half dex-router impl
magiodev Jun 26, 2024
f4b153b
more dex-router changes refaactor
magiodev Jun 26, 2024
e107e85
helpers msgs creation for swap
magiodev Jun 26, 2024
d17e6f0
compiling contract
magiodev Jun 26, 2024
ddf9ed9
test refactor
magiodev Jun 26, 2024
21f1441
test refactor
magiodev Jun 26, 2024
7c21cf3
test compiling
magiodev Jun 26, 2024
e0df2d2
range middleware adjustments
magiodev Jun 26, 2024
96687c0
Add RemovePath msg
lubkoll Jun 26, 2024
0d54709
Add event to remove_path and remove println
lubkoll Jun 26, 2024
9939301
artifact path
magiodev Jun 26, 2024
e92cec2
Merge branch 'feat/dex-router' into feat/swap_opt_cw_dex_040
magiodev Jun 26, 2024
d66f824
Workaround for Balancer pools
lubkoll Jun 26, 2024
909ffe6
Get denoms from total pool liquidity query instead of pool query
lubkoll Jun 26, 2024
3a69566
Merge branch 'feat/dex-router' into feat/swap_opt_cw_dex_040
magiodev Jun 26, 2024
44a5e13
Add note to README that current implementation is restricted to pools…
lubkoll Jun 26, 2024
2575a77
fix build
magiodev Jun 26, 2024
3824f02
working test tube
magiodev Jun 27, 2024
3f23762
Make path in Swap msg an option
lubkoll Jun 27, 2024
5939818
polishing struct swapassets to swapoperation
magiodev Jun 27, 2024
dadd28c
swap non vauult funds test case with forced routes
magiodev Jun 27, 2024
2b02e1d
Merge branch 'feat/dex-router' into feat/swap_opt_cw_dex_040
magiodev Jun 27, 2024
c2e9050
fix msg option
magiodev Jun 27, 2024
7ab9180
forced swap route rerange
magiodev Jun 27, 2024
2abf924
fmt
magiodev Jun 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
577 changes: 413 additions & 164 deletions smart-contracts/Cargo.lock

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions smart-contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [
"contracts/cl-vault",
"contracts/merkle-incentives",
"contracts/range-middleware",
"contracts/dex-router-osmosis"
]

[workspace.dependencies]
Expand All @@ -31,13 +32,15 @@ cw20 = "1.1.2"
cw20-base = {version = "1.1.2", features = ["library"]}
cw20-staking = "0.11.1"
apollo-cw-asset = "0.1.2"
cw-dex = {git = "https://github.com/quasar-finance/cw-dex", branch = "feat/deprecate-osmo-gamm"}
mars-owner = "2.0.0"
quasar-types = { path = "packages/quasar-types" }
dex-router-osmosis = { path = "contracts/dex-router-osmosis", features = ["library"] }

# SDK
cosmos-sdk-proto = {version = "0.21.1", default-features = false}

# Osmosis
osmosis-std = "0.24.0"
osmosis-std = "0.25.0"
osmosis-std-derive = "0.20.1"

# Serialization & Tools
Expand All @@ -52,6 +55,6 @@ num_enum = "0.7.2"
base64 = "0.22.0"

# Testing
cw-multi-test = "1.1.0" # {git = "https://github.com/njerschow/cw-multi-test.git"}
osmosis-test-tube = "24.0.1"
cw-multi-test = "1.2.0"
osmosis-test-tube = "25.0.0"
proptest = "1.2.0"
2 changes: 1 addition & 1 deletion smart-contracts/contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ In the smart contracts directory, run:
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/workspace-optimizer:0.15.0
cosmwasm/workspace-optimizer:0.16.0
```
this builds all contracts in the contracts directory and places the wasm files in `smart-contracts/artifacts`.
We need to use the workspace optimizer because we have a separate directory where our packages reside.
Expand Down
7 changes: 3 additions & 4 deletions smart-contracts/contracts/cl-vault/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ library = []
optimize = """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/rust-optimizer:0.15.0
cosmwasm/rust-optimizer:0.16.0
"""

[dependencies]
Expand All @@ -53,11 +53,10 @@ cw-utils = { workspace = true }
cw2 = { workspace = true }
num_enum = { workspace = true }
apollo-cw-asset = { workspace = true }
dex-router-osmosis = {workspace = true}
# cw-dex-osmosis = {workspace = true}

## todo update this in dex router code first as this has been deprecated
cw-dex = { workspace = true }

cw-dex-router = {git = "https://github.com/quasar-finance/cw-dex-router", branch = "feat/deprecate-osmo-gamm", features = ["library", "osmosis"]}
cw-vault-multi-standard = {git = "https://github.com/quasar-finance/cw-vault-standard", branch ="master", features = ["lockup", "force-unlock"]}

[dev-dependencies]
Expand Down
13 changes: 5 additions & 8 deletions smart-contracts/contracts/cl-vault/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ pub fn execute(
max_slippage,
ratio_of_swappable_funds_to_use,
twap_window_seconds,
recommended_swap_route,
force_swap_route,
forced_swap_route,
claim_after,
}) => prepend_claim_msg(
&env,
Expand All @@ -127,15 +126,13 @@ pub fn execute(
max_slippage,
ratio_of_swappable_funds_to_use,
twap_window_seconds,
recommended_swap_route,
force_swap_route,
forced_swap_route,
claim_after,
)?,
),
crate::msg::ExtensionExecuteMsg::SwapNonVaultFunds {
force_swap_route,
swap_routes,
} => execute_swap_non_vault_funds(deps, env, info, force_swap_route, swap_routes),
crate::msg::ExtensionExecuteMsg::SwapNonVaultFunds { swap_operations } => {
execute_swap_non_vault_funds(deps, env, info, swap_operations)
}
crate::msg::ExtensionExecuteMsg::CollectRewards {} => {
execute_collect_rewards(deps, env)
}
Expand Down
4 changes: 2 additions & 2 deletions smart-contracts/contracts/cl-vault/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ pub enum ContractError {
#[error("Cannot force a recommended route if recommended route is passed in as None")]
TryForceRouteWithoutRecommendedSwapRoute {},

#[error("Auto compound swap list is empty")]
EmptyCompoundAssetList {},
#[error("Swap operations for non vault funds swap cannot be empty")]
EmptySwapOperations {},

#[error("Migration status is closed")]
MigrationStatusClosed {},
Expand Down
1 change: 0 additions & 1 deletion smart-contracts/contracts/cl-vault/src/helpers/getters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ pub fn get_depositable_tokens(

// let liquidity_y = delta_y.checked_div(denominator)?;

// // todo: check this is what we want
// Ok((
// liquidity_x.atomics().try_into()?,
// liquidity_y.atomics().try_into()?,
Expand Down
94 changes: 20 additions & 74 deletions smart-contracts/contracts/cl-vault/src/helpers/msgs.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
use apollo_cw_asset::AssetInfo;
use cosmwasm_std::{
attr, to_json_binary, Addr, Attribute, BankMsg, Coin, CosmosMsg, Deps, DepsMut, Env, Uint128,
WasmMsg,
};
use cw_dex_router::{
msg::{
BestPathForPairResponse, ExecuteMsg as DexRouterExecuteMsg, QueryMsg as DexRouterQueryMsg,
},
operations::SwapOperationsListUnchecked,
};
use dex_router_osmosis::msg::ExecuteMsg as DexRouterExecuteMsg;
use osmosis_std::types::{
cosmos::base::v1beta1::Coin as OsmoCoin,
osmosis::{
Expand Down Expand Up @@ -89,77 +83,28 @@ pub fn swap_msg(deps: &DepsMut, env: &Env, params: SwapParams) -> Result<CosmosM

// we know we have a dex_router, so we can unwrap
let dex_router_address = dex_router.clone().unwrap();
let offer_asset = AssetInfo::Native(params.token_in_denom.to_string());
let native = AssetInfo::Native(params.token_out_denom.to_string());
let ask_asset = native;

let recommended_out: Uint128 = match params.recommended_swap_route.clone() {
Some(operations) => deps.querier.query_wasm_smart(
dex_router_address.to_string(),
&DexRouterQueryMsg::SimulateSwapOperations {
offer_amount: params.token_in_amount,
operations,
},
)?,
None => 0u128.into(),
};
let best_path: Option<BestPathForPairResponse> = deps.querier.query_wasm_smart(
dex_router_address.to_string(),
&DexRouterQueryMsg::BestPathForPair {
offer_asset: offer_asset.into(),
ask_asset: ask_asset.into(),
exclude_paths: None,
offer_amount: params.token_in_amount,
},
)?;
let best_out = match best_path.clone() {
Some(best_path) => best_path.return_amount,
None => 0u128.into(),
};

// if we need to force the route
if params.force_swap_route {
match params.recommended_swap_route {
Some(recommended_swap_route) => cw_dex_execute_swap_operations_msg(
if params.forced_swap_route.is_some() {
match params.forced_swap_route {
Some(forced_swap_route) => cw_dex_execute_swap_operations_msg(
&dex_router_address,
recommended_swap_route,
params.token_out_min_amount,
&params.token_in_denom.to_string(),
forced_swap_route,
params.token_in_denom.to_string(),
params.token_in_amount,
params.token_out_denom.to_string(),
params.token_out_min_amount,
),
None => Err(ContractError::TryForceRouteWithoutRecommendedSwapRoute {}),
}
} else if best_out.is_zero() && recommended_out.is_zero() {
Ok(osmosis_swap_exact_amount_in_msg(
env,
pool_route,
params.token_in_amount,
&params.token_in_denom.to_string(),
params.token_out_min_amount,
))
} else if best_out.ge(&recommended_out) {
let operations = best_path
.ok_or(ContractError::MissingBestPath {})?
.operations
.into();
cw_dex_execute_swap_operations_msg(
&dex_router_address,
operations,
params.token_out_min_amount,
&params.token_in_denom.to_string(),
params.token_in_amount,
)
} else {
// recommended_out > best_out
let recommended_swap_route = params
.recommended_swap_route
.ok_or(ContractError::MissingRecommendedSwapRoute {})?;
cw_dex_execute_swap_operations_msg(
&dex_router_address,
recommended_swap_route, // will be some here
params.token_out_min_amount,
&params.token_in_denom.to_string(),
vec![], // will be None here, should it be None?
params.token_in_denom.to_string(),
params.token_in_amount,
params.token_out_denom.to_string(),
params.token_out_min_amount,
)
}
}
Expand All @@ -185,21 +130,22 @@ fn osmosis_swap_exact_amount_in_msg(

fn cw_dex_execute_swap_operations_msg(
dex_router_address: &Addr,
operations: SwapOperationsListUnchecked,
token_out_min_amount: Uint128,
token_in_denom: &String,
path: Vec<SwapAmountInRoute>,
token_in_denom: String,
token_in_amount: Uint128,
token_out_denom: String,
token_out_min_amount: Uint128,
) -> Result<CosmosMsg, ContractError> {
let swap_msg: CosmosMsg = WasmMsg::Execute {
contract_addr: dex_router_address.to_string(),
msg: to_json_binary(&DexRouterExecuteMsg::ExecuteSwapOperations {
operations,
msg: to_json_binary(&DexRouterExecuteMsg::Swap {
path: Some(path),
out_denom: token_out_denom,
minimum_receive: Some(token_out_min_amount),
to: None,
offer_amount: None,
})?,
funds: vec![Coin {
denom: token_in_denom.to_string(),
denom: token_in_denom,
amount: token_in_amount,
}],
}
Expand Down
24 changes: 14 additions & 10 deletions smart-contracts/contracts/cl-vault/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Decimal, Uint128};
use cw_dex_router::operations::SwapOperationsListUnchecked;
use cw_vault_multi_standard::{VaultStandardExecuteMsg, VaultStandardQueryMsg};
use osmosis_std::types::osmosis::poolmanager::v1beta1::SwapAmountInRoute;

use crate::{
query::{
AssetsBalanceResponse, PoolResponse, PositionResponse, RangeAdminResponse,
UserSharesBalanceResponse, VerifyTickCacheResponse,
},
state::{Metadata, VaultConfig},
vault::autocompound::SwapAsset,
};

/// Extension execute messages for an apollo autocompounding vault
Expand All @@ -31,10 +30,7 @@ pub enum ExtensionExecuteMsg {
/// MigrationStep
MigrationStep { amount_of_users: Uint128 },
/// SwapNonVaultFunds
SwapNonVaultFunds {
force_swap_route: bool,
swap_routes: Vec<SwapAsset>,
},
SwapNonVaultFunds { swap_operations: Vec<SwapOperation> },
}

/// Extension messages for Authz. This interface basically reexports certain vault functionality
Expand Down Expand Up @@ -90,10 +86,8 @@ pub struct ModifyRangeMsg {
pub ratio_of_swappable_funds_to_use: Decimal,
/// twap window to use in seconds
pub twap_window_seconds: u64,
/// recommended swap route to take
pub recommended_swap_route: Option<SwapOperationsListUnchecked>,
/// whether or not to force the swap route
pub force_swap_route: bool,
/// forced swap route to take
pub forced_swap_route: Option<Vec<SwapAmountInRoute>>,
/// claim_after optional field, if we off chain computed that incentives have some forfeit duration. this will be persisted in POSITION state
pub claim_after: Option<u64>,
}
Expand All @@ -103,6 +97,16 @@ pub struct MergePositionMsg {
pub position_ids: Vec<u64>,
}

// struct used by swap.rs on swap non vault funds
#[cw_serde]
pub struct SwapOperation {
pub token_in_denom: String,
pub pool_id_0: u64, // the osmosis pool_id as mandatory to have at least the chance to swap on CL pools
pub pool_id_1: u64, // the osmosis pool_id as mandatory to have at least the chance to swap on CL pools
pub forced_swap_route_token_0: Option<Vec<SwapAmountInRoute>>,
pub forced_swap_route_token_1: Option<Vec<SwapAmountInRoute>>,
}

/// Extension query messages for an apollo autocompounding vault
#[cw_serde]
pub enum ExtensionQueryMsg {
Expand Down
9 changes: 3 additions & 6 deletions smart-contracts/contracts/cl-vault/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::{
};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Decimal, Decimal256, Uint128};
use cw_dex_router::operations::SwapOperationsListUnchecked;
use cw_storage_plus::{Deque, Item, Map};
use osmosis_std::types::osmosis::poolmanager::v1beta1::SwapAmountInRoute;

/// metadata useful for display purposes
#[cw_serde]
Expand All @@ -28,7 +28,7 @@ pub struct VaultConfig {
pub performance_fee: Decimal,
/// Account to receive fee payments
pub treasury: Addr,
/// swap max slippage // TODO: This is unused. This should be used on any swap operations where we pass an offchain computed slippage parameter
/// swap max slippage
pub swap_max_slippage: Decimal,
/// Dex router address
pub dex_router: Addr,
Expand Down Expand Up @@ -61,7 +61,6 @@ pub const MIGRATION_STATUS: Item<MigrationStatus> = Item::new("migration_status"
#[cw_serde]
pub struct PoolConfig {
pub pool_id: u64,
// todo: Verify in instantiate message
pub token0: String,
pub token1: String,
}
Expand Down Expand Up @@ -150,9 +149,7 @@ pub struct ModifyRangeState {
// the twap window to use for the swap in seconds
pub twap_window_seconds: u64,
// the recommended path to take for the swap
pub recommended_swap_route: Option<SwapOperationsListUnchecked>,
// whether or not to force the swap route
pub force_swap_route: bool,
pub forced_swap_route: Option<Vec<SwapAmountInRoute>>,
}

pub const MODIFY_RANGE_STATE: Item<Option<ModifyRangeState>> = Item::new("modify_range_state");
Expand Down
Loading