diff --git a/artifacts/checksums.txt b/artifacts/checksums.txt index 493675ea..df1ceed2 100644 --- a/artifacts/checksums.txt +++ b/artifacts/checksums.txt @@ -1,18 +1,18 @@ -21355a578e0ef0861f4b9c23e70f54e90847137ad7cf550bdc60ad762c4df8e3 dexter_governance_admin-aarch64.wasm -378459f0abdc57f4cadb8692be2352cea64acc16d2fc77d104f2d1467939401d dexter_governance_admin.wasm -ca6a64f456f478973cfd9b3bc99c2725f6f5c182f9f4df9005d7f0436661aa5d dexter_keeper-aarch64.wasm -50242640f23b46c1f0276f479a2852fac30ea386c590c17f7493b4529112c870 dexter_keeper.wasm -6422ec98a4996161f687380bcca826b02fe26f402a20620246a18ea21229420f dexter_multi_staking-aarch64.wasm -09c374819a3e57ea0b9da6be5c54d061b6d5838d2e943fce7096af3db5c00de8 dexter_multi_staking.wasm -1f2687ed6d8d91595c3251abd4514c09749bebf6b9ef8cbd94753bcdc467e218 dexter_router-aarch64.wasm -48b97784bc431744d2f727941da939ce6cf04c49959b97595dc431b080070cf9 dexter_router.wasm -b448981216b66c02f592c4edc8afb95caa563d9191876d8f71532f8387df70f3 dexter_superfluid_lp-aarch64.wasm -803214635c6b618c4395206bb54f0f5f4d861c90096f064272d1dabf7fa1e3cc dexter_superfluid_lp.wasm -f08b0b2809e99e8ae65ec28293a097a6faca78e5a4530ba94d498382a32ae9ae dexter_vault-aarch64.wasm -0c15b06cfb0f52b779b79fd4b56f784babcb172b75c35ac4b83f3b0fdf7acdba dexter_vault.wasm -9c1ef4d27c2f76a968c909ffdc6739a794d871594151e49e931a48da1d87bdc2 lp_token-aarch64.wasm -9633cca272749e266be93aba1a597d3fe49d0a84e7ab842d7a34402c01f8bef5 lp_token.wasm -5e35bfe3d8e3c5f89f585c04b2353893162cac2d299c132c2bccb494a25ee7a7 stable_pool-aarch64.wasm -730fe353b08d71a33bd12694064338dc78373a35fe39a7575ad5ed79d389b821 stable_pool.wasm -7aea930f4bcb0da4e94dc173c0528185138671b2d868cf679ce42b9ca90a53fa weighted_pool-aarch64.wasm -7019ffc8f3eacdfcc13d588d26de784204f729fa2898ba1ff2cf5bb1e7bee586 weighted_pool.wasm +f39890d02fc67b78922bcbce111603e4a50bcf97bc2a1615cf0bdc8ad25ed07c dexter_governance_admin-aarch64.wasm +c54c9a4e0782a12787ed849acd89349c8fe8cc151518ec39955b262c2d0d6092 dexter_governance_admin.wasm +9fa111e409b266a474027587ad4cb997c7aa8bf3be0a53cabf77b331147952bd dexter_keeper-aarch64.wasm +c6530ace24ee2aaa3c2e736f27544a139ead974cfe64e658f3b17d5dba8a95f4 dexter_keeper.wasm +d0588a5166b804c6fde9ce264ef3eedf321a0feb2f60196afc2bccbafd5664d3 dexter_lp_token-aarch64.wasm +6f54c1020a8fd4d0963c3a0691563ced131c98b05426ff5159164f01167cbc22 dexter_lp_token.wasm +9bf2599fcbb264c1c44ff9d17df8523af18339d109133464fef057bbf84113ed dexter_multi_staking-aarch64.wasm +ad7affc67012f59eb512ddc3ffc396dccfd0f58249353fa8375ec5dc1c2c86ac dexter_multi_staking.wasm +4c4b22d636f2a60d422fc590347b576270dd8ef3c88959afc5f0e93cbc7a022a dexter_router-aarch64.wasm +4f248b5640ccf97ba291a5004fef8bbee5720321effdcb3bc5fd0d119042c99e dexter_router.wasm +19c7f35ee650d8b753f987db2cb77d83fdd6e7f91997ecdc52f9eb2979377e59 dexter_stable_pool-aarch64.wasm +028bd6eb2b085a4a4f03fe32e25daef1417edeb91efd3de3d5c8bc38f2ac9ef9 dexter_stable_pool.wasm +3fbc72f69084b89cde06b8af2068935474fdab7303c8875becb6dfd6640605ce dexter_superfluid_lp-aarch64.wasm +b716764b8f4495095225897f29d5db3f3435773ec0fa356b94beec8df2edbac1 dexter_superfluid_lp.wasm +cf42065add276a52cc9c53366adf25612caf546624eca218a33bcd013712db3f dexter_vault-aarch64.wasm +485d58e9cafbafb0cea67afa6e151f05254c313047da3328f157080c943a1bba dexter_vault.wasm +8a09bfb21e09482d25535d629171a095b9a5a334e72c3679aa26db4296d60984 dexter_weighted_pool-aarch64.wasm +f26735c014df02bf25efd744cf5c93c656c6b5509b264679f3d51c0fcfc5fbe9 dexter_weighted_pool.wasm diff --git a/artifacts/checksums_intermediate.txt b/artifacts/checksums_intermediate.txt deleted file mode 100644 index 89af001f..00000000 --- a/artifacts/checksums_intermediate.txt +++ /dev/null @@ -1,8 +0,0 @@ -391c353d650626d40011385a2fe50fb506a09d2472a6c54da94d885cd1ac52bf target/wasm32-unknown-unknown/release/dexter_governance_admin.wasm -13fe7953094edaf64dd46dd832be31541557a93d3601f6017315d227fc8b9a27 target/wasm32-unknown-unknown/release/dexter_keeper.wasm -2465ac00de52d10397e64142799751ca33cd6a387b348e462d43fc79192cf1c7 target/wasm32-unknown-unknown/release/dexter_multi_staking.wasm -d7fce682716cc1e79e2d370da5544fd0840e4bbf75f3c9d8c7a34c55d0fa713f target/wasm32-unknown-unknown/release/dexter_router.wasm -add05a4995b70b780078908bfbe9e6754ad06c2ce5793f93595d252ad4121ea7 target/wasm32-unknown-unknown/release/dexter_vault.wasm -00ba3921736b1f788e079c87085199289e5dc3c7801c7762c24674603f933551 target/wasm32-unknown-unknown/release/lp_token.wasm -936645177e3da336e4689d535cfdc25c48f5723b0d4b34b42d38783b2fd3f7b9 target/wasm32-unknown-unknown/release/stable_pool.wasm -f99881e3c5db034788179720ed70afffafc0d3651eb156a8f24bfb4a5048e850 target/wasm32-unknown-unknown/release/weighted_pool.wasm diff --git a/artifacts/dexter_governance_admin-aarch64.wasm b/artifacts/dexter_governance_admin-aarch64.wasm index 47fe256c..0f1e6db3 100644 Binary files a/artifacts/dexter_governance_admin-aarch64.wasm and b/artifacts/dexter_governance_admin-aarch64.wasm differ diff --git a/artifacts/dexter_governance_admin.wasm b/artifacts/dexter_governance_admin.wasm index 97a57634..67d65526 100644 Binary files a/artifacts/dexter_governance_admin.wasm and b/artifacts/dexter_governance_admin.wasm differ diff --git a/artifacts/dexter_keeper-aarch64.wasm b/artifacts/dexter_keeper-aarch64.wasm index 7086bd81..0b967db2 100644 Binary files a/artifacts/dexter_keeper-aarch64.wasm and b/artifacts/dexter_keeper-aarch64.wasm differ diff --git a/artifacts/dexter_keeper.wasm b/artifacts/dexter_keeper.wasm index ccfdfe2d..c07ef794 100644 Binary files a/artifacts/dexter_keeper.wasm and b/artifacts/dexter_keeper.wasm differ diff --git a/artifacts/dexter_lp_token-aarch64.wasm b/artifacts/dexter_lp_token-aarch64.wasm new file mode 100644 index 00000000..465631c2 Binary files /dev/null and b/artifacts/dexter_lp_token-aarch64.wasm differ diff --git a/artifacts/dexter_lp_token.wasm b/artifacts/dexter_lp_token.wasm new file mode 100644 index 00000000..2b6885db Binary files /dev/null and b/artifacts/dexter_lp_token.wasm differ diff --git a/artifacts/dexter_multi_staking-aarch64.wasm b/artifacts/dexter_multi_staking-aarch64.wasm index bd0ab2ac..047a439d 100644 Binary files a/artifacts/dexter_multi_staking-aarch64.wasm and b/artifacts/dexter_multi_staking-aarch64.wasm differ diff --git a/artifacts/dexter_multi_staking.wasm b/artifacts/dexter_multi_staking.wasm index dcb51a96..4731a738 100644 Binary files a/artifacts/dexter_multi_staking.wasm and b/artifacts/dexter_multi_staking.wasm differ diff --git a/artifacts/dexter_router-aarch64.wasm b/artifacts/dexter_router-aarch64.wasm index f4929b06..f47c37d0 100644 Binary files a/artifacts/dexter_router-aarch64.wasm and b/artifacts/dexter_router-aarch64.wasm differ diff --git a/artifacts/dexter_router.wasm b/artifacts/dexter_router.wasm index 02160f7c..e01aee2c 100644 Binary files a/artifacts/dexter_router.wasm and b/artifacts/dexter_router.wasm differ diff --git a/artifacts/dexter_stable_pool-aarch64.wasm b/artifacts/dexter_stable_pool-aarch64.wasm new file mode 100644 index 00000000..ddd445dd Binary files /dev/null and b/artifacts/dexter_stable_pool-aarch64.wasm differ diff --git a/artifacts/dexter_stable_pool.wasm b/artifacts/dexter_stable_pool.wasm new file mode 100644 index 00000000..0de7a9f3 Binary files /dev/null and b/artifacts/dexter_stable_pool.wasm differ diff --git a/artifacts/dexter_superfluid_lp-aarch64.wasm b/artifacts/dexter_superfluid_lp-aarch64.wasm index bd7f076f..070aed65 100644 Binary files a/artifacts/dexter_superfluid_lp-aarch64.wasm and b/artifacts/dexter_superfluid_lp-aarch64.wasm differ diff --git a/artifacts/dexter_superfluid_lp.wasm b/artifacts/dexter_superfluid_lp.wasm index b366a426..57881e84 100644 Binary files a/artifacts/dexter_superfluid_lp.wasm and b/artifacts/dexter_superfluid_lp.wasm differ diff --git a/artifacts/dexter_vault-aarch64.wasm b/artifacts/dexter_vault-aarch64.wasm index 813ff51c..29be4430 100644 Binary files a/artifacts/dexter_vault-aarch64.wasm and b/artifacts/dexter_vault-aarch64.wasm differ diff --git a/artifacts/dexter_vault.wasm b/artifacts/dexter_vault.wasm index 752824b1..c34ff0e2 100644 Binary files a/artifacts/dexter_vault.wasm and b/artifacts/dexter_vault.wasm differ diff --git a/artifacts/dexter_weighted_pool-aarch64.wasm b/artifacts/dexter_weighted_pool-aarch64.wasm new file mode 100644 index 00000000..090ba50e Binary files /dev/null and b/artifacts/dexter_weighted_pool-aarch64.wasm differ diff --git a/artifacts/dexter_weighted_pool.wasm b/artifacts/dexter_weighted_pool.wasm new file mode 100644 index 00000000..c784c600 Binary files /dev/null and b/artifacts/dexter_weighted_pool.wasm differ diff --git a/artifacts/lp_token-aarch64.wasm b/artifacts/lp_token-aarch64.wasm deleted file mode 100644 index 61675c13..00000000 Binary files a/artifacts/lp_token-aarch64.wasm and /dev/null differ diff --git a/artifacts/lp_token.wasm b/artifacts/lp_token.wasm deleted file mode 100644 index d6d91e94..00000000 Binary files a/artifacts/lp_token.wasm and /dev/null differ diff --git a/artifacts/stable_pool-aarch64.wasm b/artifacts/stable_pool-aarch64.wasm deleted file mode 100644 index c931e58d..00000000 Binary files a/artifacts/stable_pool-aarch64.wasm and /dev/null differ diff --git a/artifacts/stable_pool.wasm b/artifacts/stable_pool.wasm deleted file mode 100644 index 181e2375..00000000 Binary files a/artifacts/stable_pool.wasm and /dev/null differ diff --git a/artifacts/weighted_pool-aarch64.wasm b/artifacts/weighted_pool-aarch64.wasm deleted file mode 100644 index 196a5212..00000000 Binary files a/artifacts/weighted_pool-aarch64.wasm and /dev/null differ diff --git a/artifacts/weighted_pool.wasm b/artifacts/weighted_pool.wasm deleted file mode 100644 index 88407e78..00000000 Binary files a/artifacts/weighted_pool.wasm and /dev/null differ diff --git a/contracts/governance_admin/Cargo.toml b/contracts/governance_admin/Cargo.toml index a5ea08a8..9192e134 100644 --- a/contracts/governance_admin/Cargo.toml +++ b/contracts/governance_admin/Cargo.toml @@ -21,7 +21,7 @@ crate-type = ["cdylib", "rlib"] backtraces = ["cosmwasm-std/backtraces"] [dependencies] -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" cw2 = "1.0.1" cw20 = "1.0.1" cw-storage-plus = { version = "1.0.1", features = ["iterator"] } @@ -39,9 +39,9 @@ serde-cw-value = "0.7.0" cosmwasm-schema = "1.5.0" dexter-vault = {path = "../vault"} dexter-keeper = {path = "../keeper"} -stable-pool = {path = "../pools/stable_pool" } -weighted-pool = {path = "../pools/weighted_pool" } -lp-token = {path = "../lp_token"} +dexter-stable-pool = {path = "../pools/stable_pool" } +dexter-weighted-pool = {path = "../pools/weighted_pool" } +dexter-lp-token = {path = "../lp_token"} cw-multi-test = "0.16.2" persistence-test-tube = "1.0.0" cw20-base = { version = "1.0.1", features = ["library"] } diff --git a/contracts/governance_admin/tests/create-pool.rs b/contracts/governance_admin/tests/create-pool.rs index 73e7d421..e31fa841 100644 --- a/contracts/governance_admin/tests/create-pool.rs +++ b/contracts/governance_admin/tests/create-pool.rs @@ -11,7 +11,7 @@ use dexter::{ use persistence_std::types::cosmos::gov::v1::VoteOption; use persistence_test_tube::{Account, Module, PersistenceTestApp, SigningAccount, Wasm}; use utils::GovAdminTestSetup; -use weighted_pool::state::WeightedParams; +use dexter_weighted_pool::state::WeightedParams; use crate::utils::gov_execute_msg; diff --git a/contracts/governance_admin/tests/reward-schedule.rs b/contracts/governance_admin/tests/reward-schedule.rs index 79c4150a..57357735 100644 --- a/contracts/governance_admin/tests/reward-schedule.rs +++ b/contracts/governance_admin/tests/reward-schedule.rs @@ -22,7 +22,7 @@ use persistence_test_tube::{ Account, ExecuteResponse, Gov, Module, PersistenceTestApp, RunnerError, SigningAccount, Wasm, }; use utils::GovAdminTestSetup; -use weighted_pool::state::WeightedParams; +use dexter_weighted_pool::state::WeightedParams; mod utils; diff --git a/contracts/governance_admin/tests/utils/mod.rs b/contracts/governance_admin/tests/utils/mod.rs index fb459e9b..23f67513 100644 --- a/contracts/governance_admin/tests/utils/mod.rs +++ b/contracts/governance_admin/tests/utils/mod.rs @@ -244,12 +244,12 @@ pub fn setup_test_contracts() -> GovAdminTestSetup { read_wasm_byte_code_at_path("artifacts/dexter_governance_admin-aarch64.wasm"); let vault_wasm_code = read_wasm_byte_code_at_path("artifacts/dexter_vault-aarch64.wasm"); let keeper_wasm_code = read_wasm_byte_code_at_path("artifacts/dexter_keeper-aarch64.wasm"); - let stable_pool_wasm_code = read_wasm_byte_code_at_path("artifacts/stable_pool-aarch64.wasm"); + let stable_pool_wasm_code = read_wasm_byte_code_at_path("artifacts/dexter_stable_pool-aarch64.wasm"); let weighted_pool_wasm_code = - read_wasm_byte_code_at_path("artifacts/weighted_pool-aarch64.wasm"); + read_wasm_byte_code_at_path("artifacts/dexter_weighted_pool-aarch64.wasm"); let multi_staking_wasm_code = read_wasm_byte_code_at_path("artifacts/dexter_multi_staking-aarch64.wasm"); - let lp_token_wasm_code = read_wasm_byte_code_at_path("artifacts/lp_token-aarch64.wasm"); + let lp_token_wasm_code = read_wasm_byte_code_at_path("artifacts/dexter_lp_token-aarch64.wasm"); let gov_admin_code_id = wasm .store_code(&gov_admin_wasm_code, None, &user) diff --git a/contracts/keeper/Cargo.toml b/contracts/keeper/Cargo.toml index 9a65ec38..3200229f 100644 --- a/contracts/keeper/Cargo.toml +++ b/contracts/keeper/Cargo.toml @@ -21,7 +21,7 @@ crate-type = ["cdylib", "rlib"] backtraces = ["cosmwasm-std/backtraces"] [dependencies] -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" cw2 = "1.0.1" cw20 = "1.0.1" cw-storage-plus = { version = "1.0.1", features = ["iterator"] } @@ -36,7 +36,7 @@ const_format = "0.2.30" [dev-dependencies] cosmwasm-schema = "1.5.0" dexter-vault = {path = "../vault"} -stable-pool = {path = "../pools/stable_pool" } -weighted-pool = {path = "../pools/weighted_pool" } -lp-token = {path = "../lp_token"} +dexter-stable-pool = {path = "../pools/stable_pool" } +dexter-weighted-pool = {path = "../pools/weighted_pool" } +dexter-lp-token = {path = "../lp_token"} cw-multi-test = "0.16.2" diff --git a/contracts/keeper/src/contract.rs b/contracts/keeper/src/contract.rs index 07205632..0b008017 100644 --- a/contracts/keeper/src/contract.rs +++ b/contracts/keeper/src/contract.rs @@ -4,7 +4,7 @@ use crate::state::{CONFIG, OWNERSHIP_PROPOSAL}; use const_format::concatcp; use cosmwasm_std::{ - entry_point, to_json_binary, Addr, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, Event, + entry_point, to_json_binary, Addr, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, Event, MessageInfo, Response, StdError, StdResult, Uint128, WasmMsg, }; use cw2::{get_contract_version, set_contract_version}; @@ -269,14 +269,22 @@ fn exit_lp_tokens( config.vault_address, lp_token_address.clone(), amount, - min_assets_received, + min_assets_received.clone(), )?; - Ok(Response::new().add_message(tranfer_msg).add_event( - Event::from_info(concatcp!(CONTRACT_NAME, "::exit_lp_tokens"), &info) - .add_attribute("lp_token_address", lp_token_address.to_string()) - .add_attribute("amount", amount.to_string()), - )) + let mut event = Event::from_info(concatcp!(CONTRACT_NAME, "::exit_lp_tokens"), &info) + .add_attribute("lp_token_address", lp_token_address.to_string()) + .add_attribute("amount", amount.to_string()); + + if let Some(min_assets_received) = min_assets_received { + event = event.add_attribute( + "min_assets_received", + serde_json_wasm::to_string(&min_assets_received).unwrap(), + ); + } + + let response = Response::new().add_message(tranfer_msg).add_event(event); + Ok(response) } /// Swaps the specified amount of the specified asset for another asset using the Dexter protocol. @@ -334,9 +342,7 @@ fn swap_asset( asset_in: offer_asset.info.clone(), asset_out: ask_asset_info.clone(), swap_type: dexter::vault::SwapType::GiveIn {}, - amount: offer_asset.amount, - max_spread: Some(Decimal::from_ratio(5u128, 100u128)), - belief_price: None, + amount: offer_asset.amount }, recipient: Some(env.contract.address.to_string()), min_receive, @@ -351,13 +357,17 @@ fn swap_asset( msgs.push(cosmos_msg); - Ok(Response::new().add_messages(msgs).add_event( - Event::from_info(concatcp!(CONTRACT_NAME, "::swap_asset"), &info) - .add_attribute("pool_id", pool_id.to_string()) - .add_attribute("offer_asset", offer_asset.to_string()) - .add_attribute("ask_asset_info", ask_asset_info.to_string()) - .add_attribute("min_receive", min_receive.unwrap_or_default().to_string()), - )) + let mut event = Event::from_info(concatcp!(CONTRACT_NAME, "::swap_asset"), &info) + .add_attribute("pool_id", pool_id.to_string()) + .add_attribute("offer_asset", serde_json_wasm::to_string(&offer_asset).unwrap()) + .add_attribute("ask_asset_info", serde_json_wasm::to_string(&ask_asset_info).unwrap()); + + if let Some(min_receive) = min_receive { + event = event.add_attribute("min_receive", min_receive.to_string()); + } + + let response = Response::new().add_messages(msgs).add_event(event); + Ok(response) } // ----------------x----------------x---------------------x-----------------------x----------------x---------------- diff --git a/contracts/keeper/tests/integration.rs b/contracts/keeper/tests/integration.rs index 4505cd21..45b22d89 100644 --- a/contracts/keeper/tests/integration.rs +++ b/contracts/keeper/tests/integration.rs @@ -25,9 +25,9 @@ fn instantiate_contracts(router: &mut App, owner: Addr, keeper_admin: Addr) -> ( let vault_code_id = router.store_code(vault_contract); let stable5_contract = Box::new(ContractWrapper::new_with_empty( - stable_pool::contract::execute, - stable_pool::contract::instantiate, - stable_pool::contract::query, + dexter_stable_pool::contract::execute, + dexter_stable_pool::contract::instantiate, + dexter_stable_pool::contract::query, )); let stable5_code_id = router.store_code(stable5_contract); diff --git a/contracts/keeper/tests/utils/mod.rs b/contracts/keeper/tests/utils/mod.rs index 1156d71a..e424ff7c 100644 --- a/contracts/keeper/tests/utils/mod.rs +++ b/contracts/keeper/tests/utils/mod.rs @@ -11,7 +11,7 @@ use dexter::vault::{ }; use dexter::keeper::InstantiateMsg as KeeperInstantiateMsg; -use weighted_pool::state::WeightedParams; +use dexter_weighted_pool::state::WeightedParams; pub const EPOCH_START: u64 = 1_000_000; @@ -183,9 +183,9 @@ pub fn instantiate_contracts( fn store_weighted_pool_code(app: &mut App) -> u64 { let pool_contract = Box::new(ContractWrapper::new_with_empty( - weighted_pool::contract::execute, - weighted_pool::contract::instantiate, - weighted_pool::contract::query, + dexter_weighted_pool::contract::execute, + dexter_weighted_pool::contract::instantiate, + dexter_weighted_pool::contract::query, )); app.store_code(pool_contract) } @@ -214,9 +214,9 @@ fn store_keeper_code(app: &mut App) -> u64 { pub fn store_token_code(app: &mut App) -> u64 { let token_contract = Box::new(ContractWrapper::new_with_empty( - lp_token::contract::execute, - lp_token::contract::instantiate, - lp_token::contract::query, + dexter_lp_token::contract::execute, + dexter_lp_token::contract::instantiate, + dexter_lp_token::contract::query, )); app.store_code(token_contract) } diff --git a/contracts/lp_token/Cargo.toml b/contracts/lp_token/Cargo.toml index 6416aef6..67ab03a6 100644 --- a/contracts/lp_token/Cargo.toml +++ b/contracts/lp_token/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "lp-token" +name = "dexter-lp-token" version = "1.0.0" -authors = ["Astroport"] +authors = ["Persistence Labs"] edition = "2021" description = "Expanded implementation of a CW-20 compliant token for post intialization" license = "MIT" @@ -18,10 +18,10 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -dexter = { path = "../../packages/dexter", default-features = false } +dexter = { version = "1.4.0", path = "../../packages/dexter", default-features = false } cw2 = "1.0.1" cw20 = "1.0.1" cw20-base = { version = "1.0.1", features = ["library"] } -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" snafu = "0.7.4" cosmwasm-schema = "1.5.0" diff --git a/contracts/lp_token/schema/lp-token.json b/contracts/lp_token/schema/dexter-lp-token.json similarity index 99% rename from contracts/lp_token/schema/lp-token.json rename to contracts/lp_token/schema/dexter-lp-token.json index 3aafe03c..898e7194 100644 --- a/contracts/lp_token/schema/lp-token.json +++ b/contracts/lp_token/schema/dexter-lp-token.json @@ -1,5 +1,5 @@ { - "contract_name": "lp-token", + "contract_name": "dexter-lp-token", "contract_version": "1.0.0", "idl_version": "1.0.0", "instantiate": { diff --git a/contracts/multi_staking/Cargo.toml b/contracts/multi_staking/Cargo.toml index 882ae320..94300db4 100644 --- a/contracts/multi_staking/Cargo.toml +++ b/contracts/multi_staking/Cargo.toml @@ -3,6 +3,9 @@ name = "dexter-multi-staking" version = "3.1.0" authors = ["Persistence Labs"] edition = "2021" +description = "Dexter Multi-Staking Contract: allows to stake LP tokens and earn rewards in multiple tokens" +repository = "https://github.com/dexter-zone/dexter_core" +license = "MIT OR Apache-2.0" [lib] crate-type = ["cdylib", "rlib"] @@ -15,11 +18,11 @@ library = [] [dependencies] cw2 = "1.0.1" cw20 = "1.0.1" -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" cw-storage-plus = "1.0.1" schemars = "0.8.11" serde = { version = "1.0.152", default-features = false, features = ["derive"] } -dexter = { path = "../../packages/dexter", default-features = false } +dexter = { version = "1.4.0", path = "../../packages/dexter", default-features = false } thiserror = "1.0.38" cosmwasm-schema = "1.5.0" serde-json-wasm = "0.5.0" @@ -27,7 +30,7 @@ const_format = "0.2.30" [dev-dependencies] cosmwasm-schema = "1.5.0" -lp-token = {path = "../lp_token"} +dexter-lp-token = {path = "../lp_token"} cw-multi-test = "0.16.2" cw20-base = "1.0.1" anyhow = "1.0.68" diff --git a/contracts/multi_staking/tests/create-reward.rs b/contracts/multi_staking/tests/create-reward.rs index ff6fef87..9eb12cd2 100644 --- a/contracts/multi_staking/tests/create-reward.rs +++ b/contracts/multi_staking/tests/create-reward.rs @@ -208,7 +208,7 @@ fn test_reward_schedule_queries() { let (multi_staking_instance, lp_token_addr) = setup(&mut app, admin_addr.clone()); // Allow another LP token in the multi staking contract - let lp_token1_addr = Addr::unchecked("lp-token-1"); + let lp_token1_addr = Addr::unchecked("dexter-lp-token-1"); app.execute_contract( admin_addr.clone(), multi_staking_instance.clone(), diff --git a/contracts/multi_staking/tests/utils/mod.rs b/contracts/multi_staking/tests/utils/mod.rs index 6dae345f..ad133995 100644 --- a/contracts/multi_staking/tests/utils/mod.rs +++ b/contracts/multi_staking/tests/utils/mod.rs @@ -109,9 +109,9 @@ pub fn create_dummy_cw20_token(app: &mut App, admin: &Addr, code_id: u64) -> Add pub fn store_lp_token_contract(app: &mut App) -> u64 { let lp_token_contract = Box::new(ContractWrapper::new_with_empty( - lp_token::contract::execute, - lp_token::contract::instantiate, - lp_token::contract::query, + dexter_lp_token::contract::execute, + dexter_lp_token::contract::instantiate, + dexter_lp_token::contract::query, )); let code_id = app.store_code(lp_token_contract); return code_id; diff --git a/contracts/pools/stable_pool/Cargo.toml b/contracts/pools/stable_pool/Cargo.toml index b3ef5546..01339f76 100644 --- a/contracts/pools/stable_pool/Cargo.toml +++ b/contracts/pools/stable_pool/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "stable-pool" -version = "1.0.0" -authors = ["AstroTechLabs"] +name = "dexter-stable-pool" +version = "1.1.1" +authors = ["Persistence Labs"] edition = "2021" -description = "A Dexter DEX pool implementing the stable 3-pool AMM type" +description = "A Dexter DEX pool implementing the stableswap and metastable AMM models" license = "MIT" exclude = [ @@ -24,10 +24,10 @@ backtraces = ["cosmwasm-std/backtraces"] [dependencies] integer-sqrt = "0.1.5" -dexter = { path = "../../../packages/dexter", default-features = false } +dexter = { version = "1.4.0", path = "../../../packages/dexter", default-features = false } cw2 = "1.0.1" cw20 = "1.0.1" -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" cw-storage-plus = "1.0.1" schemars = "0.8.11" serde = { version = "1.0.152", default-features = false, features = ["derive"] } @@ -41,7 +41,7 @@ const_format = "0.2.30" [dev-dependencies] anyhow = "1.0" sim = { git = "https://github.com/dexter-zone/stableswap_simulations.git", rev = "d40f0e77f6b21cccdd8415f6f36db31f76be2f3f", package = "sim" } -lp-token = {path = "../../lp_token"} +dexter-lp-token = {path = "../../lp_token"} cw-multi-test = "0.16.2" -dexter-vault = {path = "../../vault"} +dexter-vault = { path = "../../vault"} proptest = "0.10.1" diff --git a/contracts/pools/stable_pool/schema/stable-pool.json b/contracts/pools/stable_pool/schema/dexter-stable-pool.json similarity index 93% rename from contracts/pools/stable_pool/schema/stable-pool.json rename to contracts/pools/stable_pool/schema/dexter-stable-pool.json index d0234802..28dd112c 100644 --- a/contracts/pools/stable_pool/schema/stable-pool.json +++ b/contracts/pools/stable_pool/schema/dexter-stable-pool.json @@ -1,6 +1,6 @@ { - "contract_name": "stable-pool", - "contract_version": "1.0.0", + "contract_name": "dexter-stable-pool", + "contract_version": "1.1.1", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", @@ -523,26 +523,6 @@ "ask_asset": { "$ref": "#/definitions/AssetInfo" }, - "belief_price": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, - "max_spread": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, "offer_asset": { "$ref": "#/definitions/AssetInfo" }, @@ -555,6 +535,32 @@ }, "additionalProperties": false }, + { + "title": "Description - Returns the spot price of the asset in a [`SpotPrice`] object.", + "type": "object", + "required": [ + "spot_price" + ], + "properties": { + "spot_price": { + "type": "object", + "required": [ + "ask_asset", + "offer_asset" + ], + "properties": { + "ask_asset": { + "$ref": "#/definitions/AssetInfo" + }, + "offer_asset": { + "$ref": "#/definitions/AssetInfo" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "title": "Description - Returns information about the cumulative price of the asset in a [`CumulativePriceResponse`] object.", "type": "object", @@ -677,10 +683,6 @@ } ] }, - "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" - }, "ExitType": { "description": "This struct describes the ways one can choose to exit from a pool.", "oneOf": [ @@ -769,8 +771,21 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "MigrateMsg", "description": "This struct describes a migration message. We currently take no arguments for migrations.", - "type": "object", - "additionalProperties": false + "oneOf": [ + { + "type": "object", + "required": [ + "v1_1" + ], + "properties": { + "v1_1": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] }, "sudo": null, "responses": { @@ -1732,6 +1747,91 @@ "title": "Uint128", "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" + }, + "spot_price": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "SpotPrice", + "type": "object", + "required": [ + "from", + "price", + "price_including_fee", + "to" + ], + "properties": { + "from": { + "$ref": "#/definitions/AssetInfo" + }, + "price": { + "$ref": "#/definitions/Decimal256" + }, + "price_including_fee": { + "$ref": "#/definitions/Decimal256" + }, + "to": { + "$ref": "#/definitions/AssetInfo" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types.", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + } + } } } } diff --git a/contracts/pools/stable_pool/src/contract.rs b/contracts/pools/stable_pool/src/contract.rs index e0e358b6..85dd42b9 100644 --- a/contracts/pools/stable_pool/src/contract.rs +++ b/contracts/pools/stable_pool/src/contract.rs @@ -1,20 +1,19 @@ use const_format::concatcp; use cosmwasm_schema::cw_serde; use cosmwasm_std::{ - entry_point, from_json, to_json_binary, Addr, Binary, Decimal, Decimal256, Deps, DepsMut, Env, - Event, Fraction, MessageInfo, Response, StdError, StdResult, Uint128, Uint256, Uint64, + entry_point, from_json, to_json_binary, Addr, Binary, Decimal, Decimal256, Deps, DepsMut, Env, Event, MessageInfo, Response, StdError, StdResult, Uint128, Uint256, Uint64 }; -use cw2::set_contract_version; +use cw2::{get_contract_version, set_contract_version}; +use cw_storage_plus::Item; use itertools::Itertools; use std::collections::HashMap; -use std::str::FromStr; use std::vec; use crate::error::ContractError; use crate::math::{compute_d, calc_spot_price, AMP_PRECISION, MAX_AMP, MAX_AMP_CHANGE, MIN_AMP_CHANGING_TIME}; -use crate::state::{get_precision, AssetScalingFactor, MathConfig, StablePoolParams, StablePoolUpdateParams, StableSwapConfig, Twap, CONFIG, MATHCONFIG, STABLESWAP_CONFIG, TWAPINFO, PRECISIONS}; +use crate::state::{get_precision, AssetScalingFactor, MathConfig, StablePoolParams, StablePoolUpdateParams, StableSwapConfig, StableSwapConfigV1, Twap, CONFIG, MATHCONFIG, PRECISIONS, STABLESWAP_CONFIG, TWAPINFO}; use crate::utils::{accumulate_prices, compute_offer_amount, compute_swap}; -use dexter::pool::{return_exit_failure, return_join_failure, return_swap_failure, store_precisions, update_fee, AfterExitResponse, AfterJoinResponse, Config, ConfigResponse, CumulativePriceResponse, CumulativePricesResponse, ExecuteMsg, ExitType, FeeResponse, InstantiateMsg, MigrateMsg, QueryMsg, ResponseType, SpotPrice, SwapResponse, Trade, DEFAULT_SPREAD}; +use dexter::pool::{return_exit_failure, return_join_failure, return_swap_failure, store_precisions, update_fee, AfterExitResponse, AfterJoinResponse, Config, ConfigResponse, CumulativePriceResponse, CumulativePricesResponse, ExecuteMsg, ExitType, FeeResponse, InstantiateMsg, MigrateMsg, QueryMsg, ResponseType, SpotPrice, SwapResponse, Trade}; use dexter::asset::{Asset, AssetExchangeRate, AssetInfo, Decimal256Ext, DecimalAsset}; use dexter::helper::{calculate_underlying_fees, get_share_in_assets, select_pools, EventExt}; @@ -25,12 +24,15 @@ use dexter::vault::{SwapType, FEE_PRECISION}; const CONTRACT_NAME: &str = "dexter-stable-pool"; /// Contract version that is used for migration. const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const CONTRACT_VERSION_V1: &str = "1.0.0"; /// Maximum number of assets supported by the pool const MAX_ASSETS: usize = 5; /// Minimum number of assets supported by the pool const MIN_ASSETS: usize = 2; +type ContractResult = Result; + // ----------------x----------------x----------------x----------------x----------------x---------------- // ----------------x----------------x Instantiate Contract : Execute function x---------------- // ----------------x----------------x----------------x----------------x----------------x---------------- @@ -86,7 +88,7 @@ pub fn instantiate( // validate that scaling factor is greater than 0 for all the assets for asset_scaling_factor in ¶ms.scaling_factors { - if !(asset_scaling_factor.scaling_factor > Decimal256::zero()) { + if asset_scaling_factor.scaling_factor == Decimal256::zero() { return Err(ContractError::InvalidScalingFactor); } } @@ -105,11 +107,6 @@ pub fn instantiate( .addr_validate(¶ms.scaling_factor_manager.clone().unwrap().to_string())?; } - // validate max allowed spread - if !(params.max_allowed_spread > Decimal::zero() && params.max_allowed_spread < Decimal::one()) { - return Err(ContractError::InvalidMaxAllowedSpread); - } - // store precisions for assets in storage let greatest_precision = store_precisions( deps.branch(), @@ -168,8 +165,7 @@ pub fn instantiate( let stableswap_config = StableSwapConfig { scaling_factor_manager: params.scaling_factor_manager.clone(), supports_scaling_factors_update: params.supports_scaling_factors_update, - scaling_factors: params.scaling_factors.clone(), - max_allowed_spread: params.max_allowed_spread, + scaling_factors: params.scaling_factors.clone() }; // Store config, MathConfig and twap in storage @@ -281,7 +277,7 @@ fn update_scaling_factor( return Err(ContractError::UnsupportedAsset); } - if !(scaling_factor > Decimal256::zero()) { + if scaling_factor == Decimal256::zero() { return Err(ContractError::InvalidScalingFactor); } @@ -357,38 +353,6 @@ fn update_scaling_factor_manager( )) } -/// Updates the max allowed spread of the pool. -/// Only vault owner can execute this function. -fn update_max_allowed_spread( - deps: DepsMut, - info: MessageInfo, - max_allowed_spread: Decimal, -) -> Result { - let config: Config = CONFIG.load(deps.storage)?; - let vault_config = query_vault_config(&deps.querier, config.vault_addr.clone().to_string())?; - let mut stableswap_config = STABLESWAP_CONFIG.load(deps.storage)?; - - // Access Check :: Only Vault's Owner can execute this function - if info.sender != vault_config.owner && info.sender != config.vault_addr { - return Err(ContractError::Unauthorized {}); - } - - // Max allowed spread should be between 0 and 1 not inclusive i.e 0 < max_allowed_spread < 1 - if !(max_allowed_spread > Decimal::zero() && max_allowed_spread < Decimal::one()) { - return Err(ContractError::InvalidMaxAllowedSpread); - } - - // Update config - stableswap_config.max_allowed_spread = max_allowed_spread; - STABLESWAP_CONFIG.save(deps.storage, &stableswap_config)?; - - // Emit an event - let event = Event::from_info(concatcp!(CONTRACT_NAME, "::update_config::update_max_allowed_spread"), &info) - .add_attribute("max_allowed_spread", max_allowed_spread.to_string()); - - Ok(Response::new().add_event(event)) -} - /// ## Description /// Admin Access by Vault :: Callable only by Dexter::Vault --> Updates locally stored asset balances state. Operation --> Updates locally stored [`Asset`] state /// Returns an [`ContractError`] on failure, otherwise returns the [`Response`] with the specified attributes if the operation was successful. @@ -481,9 +445,6 @@ pub fn update_config( StablePoolUpdateParams::UpdateScalingFactorManager { manager } => { update_scaling_factor_manager(deps, info, manager) } - StablePoolUpdateParams::UpdateMaxAllowedSpread { max_allowed_spread } => { - update_max_allowed_spread(deps, info, max_allowed_spread) - } } } // ----------------x----------------x---------------------x-----------------------x----------------x---------------- @@ -514,8 +475,6 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { offer_asset, ask_asset, amount, - max_spread: _, - belief_price: _, } => to_json_binary(&query_on_swap( deps, env, @@ -523,7 +482,6 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { offer_asset, ask_asset, amount, - )?), QueryMsg::CumulativePrice { offer_asset, @@ -557,7 +515,6 @@ pub fn query_config(deps: Deps, env: Env) -> StdResult { math_params: Some(to_json_binary(&math_config).unwrap()), additional_params: Some( to_json_binary(&StablePoolParams { - max_allowed_spread: stable_swap_config.max_allowed_spread, amp: cur_amp.checked_div(AMP_PRECISION).unwrap(), scaling_factors: stable_swap_config.scaling_factors, scaling_factor_manager: stable_swap_config.scaling_factor_manager, @@ -975,7 +932,7 @@ pub fn query_on_swap( let offer_asset: Asset; let ask_asset: Asset; - let calc_amount: Uint128; + let (calc_amount, spread_amount): (Uint128, Uint128); let total_fee: Uint128; let ask_asset_scaling_factor = scaling_factors @@ -1006,7 +963,7 @@ pub fn query_on_swap( .to_scaled_decimal_asset(offer_precision, offer_asset_scaling_factor)?; // Calculate the number of ask_asset tokens to be transferred to the recipient from the Vault contract - calc_amount = match compute_swap( + (calc_amount, spread_amount) = match compute_swap( deps.storage, &env, &math_config, @@ -1043,7 +1000,7 @@ pub fn query_on_swap( .to_scaled_decimal_asset(ask_precision, ask_asset_scaling_factor)?; // Calculate the number of offer_asset tokens to be transferred from the trader from the Vault contract - (calc_amount, total_fee) = match compute_offer_amount( + (calc_amount, spread_amount, total_fee) = match compute_offer_amount( deps.storage, &env, &math_config, @@ -1086,7 +1043,7 @@ pub fn query_on_swap( trade_params: Trade { amount_in: offer_asset.amount, amount_out: ask_asset.amount, - spread: Uint128::zero(), + spread: spread_amount, }, response: ResponseType::Success {}, fee: Some(Asset { @@ -1481,68 +1438,6 @@ fn imbalanced_withdraw( }) } -/// ## Description -/// Returns a [`ContractError`] on failure. -/// If `belief_price` and `max_spread` are both specified, we compute a new spread, otherwise we just use the swap spread to check `max_spread`. -/// -/// ## Params -/// * **belief_price** is an object of type [`Option`]. This is the belief price used in the swap. -/// * **max_spread** is an object of type [`Option`]. This is the max spread allowed so that the swap can be executed successfuly. -/// * **offer_amount** is an object of type [`Uint128`]. This is the amount of assets to swap. -/// * **return_amount** is an object of type [`Uint128`]. This is the amount of assets to receive from the swap. -/// * **spread_amount** is an object of type [`Uint128`]. This is the spread used in the swap. -pub fn assert_max_spread( - max_allowed_spread: Decimal, - belief_price: Option, - max_spread: Option, - offer_amount: Uint128, - return_amount: Uint128, - spread_amount: Uint128, -) -> ResponseType { - let default_spread = Decimal::from_str(DEFAULT_SPREAD).unwrap(); - - let max_spread = max_spread.unwrap_or(default_spread); - if max_spread.gt(&max_allowed_spread) { - return ResponseType::Failure((ContractError::AllowedSpreadAssertion {}).to_string()); - } - let calc_spread = Decimal::from_ratio(spread_amount, return_amount + spread_amount); - - if let Some(belief_price) = belief_price { - let expected_return = offer_amount - * belief_price - .inv() - .ok_or_else(|| { - ResponseType::Failure( - (ContractError::Std(StdError::generic_err( - "Invalid belief_price. Check the input values.", - ))) - .to_string(), - ) - }) - .unwrap(); - - let spread_amount = expected_return.saturating_sub(return_amount); - let calc_spread = Decimal::from_ratio(spread_amount, expected_return); - - if return_amount < expected_return && calc_spread > max_spread { - return ResponseType::Failure( - (ContractError::MaxSpreadAssertion { - spread_amount: calc_spread, - }) - .to_string(), - ); - } - } else if calc_spread > max_spread { - return ResponseType::Failure( - (ContractError::MaxSpreadAssertion { - spread_amount: calc_spread, - }) - .to_string(), - ); - } - - ResponseType::Success {} -} // --------x--------x--------x--------x--------x--------x-------- // --------x--------x AMP COMPUTE Functions x--------x--------- @@ -1584,21 +1479,6 @@ fn compute_current_amp(math_config: &MathConfig, env: &Env) -> StdResult { } } -// --------x--------x--------x--------x--------x--------x--- -// --------x--------x Migrate Function x--------x--------- -// --------x--------x--------x--------x--------x--------x--- - -/// ## Description -/// Used for migration of contract. Returns the default object of type [`Response`]. -/// ## Params -/// * **_deps** is the object of type [`DepsMut`]. -/// * **_env** is the object of type [`Env`]. -/// * **_msg** is the object of type [`MigrateMsg`]. -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult { - Ok(Response::default()) -} - // --------x--------x--------x--------x--------x--------x--- // --------x--------x Helper Functions x--------x--------- // --------x--------x--------x--------x--------x--------x--- @@ -1625,3 +1505,42 @@ pub fn transform_to_scaled_decimal_asset( }) .collect::>>() } + +// migrate msg +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> ContractResult { + match msg { + MigrateMsg::V1_1 {} => { + // fetch current version to ensure it's v1 + let version = get_contract_version(deps.storage)?; + if version.version != CONTRACT_VERSION_V1 { + return Err(ContractError::InvalidContractVersion { + expected_version: CONTRACT_VERSION_V1.to_string(), + current_version: version.version, + }); + } + + if version.contract != CONTRACT_NAME { + return Err(ContractError::InvalidContractName { + expected_name: CONTRACT_NAME.to_string(), + contract_name: version.contract, + }); + } + + // fix the stableswap config + let stableswap_config: StableSwapConfigV1 = Item::new("stableswap_config").load(deps.storage)?; + + // remove the max_allowed_spread field + let stableswap_config_new: StableSwapConfig = StableSwapConfig { + supports_scaling_factors_update: stableswap_config.supports_scaling_factors_update, + scaling_factors: stableswap_config.scaling_factors, + scaling_factor_manager: stableswap_config.scaling_factor_manager + }; + + STABLESWAP_CONFIG.save(deps.storage, &stableswap_config_new)?; + set_contract_version(deps.storage, CONTRACT_VERSION, CONTRACT_NAME)?; + + Ok(Response::default()) + } + } +} \ No newline at end of file diff --git a/contracts/pools/stable_pool/src/error.rs b/contracts/pools/stable_pool/src/error.rs index eeb1d63d..7579fbbd 100644 --- a/contracts/pools/stable_pool/src/error.rs +++ b/contracts/pools/stable_pool/src/error.rs @@ -102,6 +102,18 @@ pub enum ContractError { #[error("Duplicate asset info in scaling factors")] DuplicateAssetInfoInScalingFactors, + + #[error("Invalid contract version for upgrade. Expected version: {expected_version} Found: {current_version}")] + InvalidContractVersion { + current_version: String, + expected_version: String, + }, + + #[error("Invalid contract name for upgrade. Expected name: {expected_name} Found: {contract_name}")] + InvalidContractName { + contract_name: String, + expected_name: String, + }, } impl From for ContractError { diff --git a/contracts/pools/stable_pool/src/math.rs b/contracts/pools/stable_pool/src/math.rs index 65d5052b..1fb688bd 100644 --- a/contracts/pools/stable_pool/src/math.rs +++ b/contracts/pools/stable_pool/src/math.rs @@ -110,7 +110,6 @@ pub(crate) fn calc_y( // d is computed with the largest precision possible i.e Decimal256::DECIMAL_PLACES i.e 18 let d = compute_d(amp, &pool_values)?.to_uint256_with_precision(Decimal256::DECIMAL_PLACES)?; - let mut c = d; for pool in pools { @@ -132,27 +131,20 @@ pub(crate) fn calc_y( } let c = c * d / (ann * Uint256::from(n_coins)); - // let sum = sum.to_uint256_with_precision(Decimal256::DECIMAL_PLACES)?; - let b = sum + d / ann; let mut y = d; - // println!("y: {}", y); - let d = y; for _ in 0..ITERATIONS { let y_prev = y; y = (y * y + c) / (y + y + b - d); - // println!("iter: {}, y_new: {}", iter, y); if y >= y_prev { if y - y_prev <= Uint256::from(1u8) { // We need to scale the value from the MAX_PRECISION to the precision of the asset // We do this by dividing the value by the ratio of the two precisions let decimal_difference = Decimal256::DECIMAL_PLACES - output_precision as u32; // this is safe because ask_asset_precision is always <= 18 - // println!("decimal_difference: {}", decimal_difference); - let precision_ratio = Uint256::from(10u8).pow(decimal_difference as u32); let y = y.checked_div(precision_ratio)?; @@ -162,8 +154,6 @@ pub(crate) fn calc_y( // We need to scale the value from the MAX_PRECISION to the precision of the asset // We do this by dividing the value by the ratio of the two precisions let decimal_difference = Decimal256::DECIMAL_PLACES - output_precision as u32; // this is safe because ask_asset_precision is always <= 18 - // println!("decimal_difference: {}", decimal_difference); - let precision_ratio = Uint256::from(10u8).pow(decimal_difference as u32); let y = y.checked_div(precision_ratio)?; return Ok(y.try_into()?); @@ -276,8 +266,8 @@ pub(crate) fn calc_spot_price( #[cfg(test)] mod tests { + use std::str::FromStr; - use super::*; use dexter::{asset::{native_asset, Asset}, uint128_with_precision}; use sim::StableSwapModel; diff --git a/contracts/pools/stable_pool/src/state.rs b/contracts/pools/stable_pool/src/state.rs index bf69d7d2..f8318c1d 100644 --- a/contracts/pools/stable_pool/src/state.rs +++ b/contracts/pools/stable_pool/src/state.rs @@ -33,8 +33,20 @@ pub struct MathConfig { pub greatest_precision: u8, } +/// Stablswap config. New version removes the unused max_allowed_spread field. #[cw_serde] pub struct StableSwapConfig { + /// If this is true, then the scaling factors can be updated by the scaling_factor_manager. + pub supports_scaling_factors_update: bool, + /// The vector of scaling factors for each asset in the pool. + /// The scaling factor is used to scale the volume of the asset in the pool for the stableswap invariant calculations. + pub scaling_factors: Vec, + // This address is allowed to update scaling factors. This address is required if support_scaling_factors_update is true. + pub scaling_factor_manager: Option, +} + +#[cw_serde] +pub struct StableSwapConfigV1 { /// Max allowed spread between the price of the asset and the price of the pool. /// If the spread is greater than this value, the swap will fail. /// This value is configurable by the Pool Manager. @@ -86,8 +98,6 @@ pub struct Twap { pub struct StablePoolParams { /// The current stableswap pool amplification pub amp: u64, - /// Max allowed spread for the trades - pub max_allowed_spread: Decimal, /// Support scaling factors update pub supports_scaling_factors_update: bool, /// Scaling factors @@ -123,8 +133,7 @@ pub enum StablePoolUpdateParams { StartChangingAmp { next_amp: u64, next_amp_time: u64 }, StopChangingAmp {}, UpdateScalingFactorManager { manager: Addr }, - UpdateScalingFactor { asset_info: AssetInfo, scaling_factor: Decimal256 }, - UpdateMaxAllowedSpread { max_allowed_spread: Decimal }, + UpdateScalingFactor { asset_info: AssetInfo, scaling_factor: Decimal256 } } // ----------------x----------------x----------------x---------------- diff --git a/contracts/pools/stable_pool/src/utils.rs b/contracts/pools/stable_pool/src/utils.rs index 729f8ada..208e8063 100644 --- a/contracts/pools/stable_pool/src/utils.rs +++ b/contracts/pools/stable_pool/src/utils.rs @@ -31,7 +31,7 @@ pub(crate) fn compute_swap( ask_pool: &DecimalAsset, pools: &[DecimalAsset], ask_asset_scaling_factor: Decimal256, -) -> StdResult { +) -> StdResult<(Uint128, Uint128)> { // get ask asset precision let ask_asset_precision = get_precision(storage, &ask_pool.info)?; @@ -49,7 +49,20 @@ pub(crate) fn compute_swap( .without_scaling_factor(ask_asset_scaling_factor)? .to_uint128_with_precision(ask_asset_precision)?; - Ok(return_amount_without_scaling_factor) + let offer_asset_amount = offer_asset + .amount + .to_uint128_with_precision(ask_asset_precision)?; + + + // We consider swap rate 1:1 in stable swap thus any difference is considered as spread. + let spread_amount = offer_asset_amount.saturating_sub(return_amount); + + // Spread amount must be scaled by the scaling factor of the ask asset to get the actual spread amount in the ask asset terms. + let spread_amount_without_scaling_factor = Decimal256::with_precision(spread_amount, ask_asset_precision as u32)? + .without_scaling_factor(ask_asset_scaling_factor)? + .to_uint128_with_precision(ask_asset_precision)?; + + Ok((return_amount_without_scaling_factor, spread_amount_without_scaling_factor)) } /// ## Description @@ -70,10 +83,11 @@ pub(crate) fn compute_offer_amount( ask_pool: &DecimalAsset, pools: &[DecimalAsset], commission_rate: u16, - _ask_asset_scaling_factor: Decimal256, + ask_asset_scaling_factor: Decimal256, offer_asset_scaling_factor: Decimal256, -) -> StdResult<(Uint128, Uint128)> { +) -> StdResult<(Uint128, Uint128, Uint128)> { let offer_precision = get_precision(storage, &offer_pool.info)?; + let ask_precision = get_precision(storage, &ask_asset.info)?; let one_minus_commission = Decimal256::one() - decimal_to_decimal256(Decimal::from_ratio(commission_rate, FEE_PRECISION))?; @@ -108,7 +122,16 @@ pub(crate) fn compute_offer_amount( let fee = offer_amount_including_fee - offer_amount_without_scaling_factor; let fee_uint128 = fee.to_uint128_with_precision(offer_precision)?; - Ok((offer_amount_including_fee_uint128, fee_uint128)) + // We assume the assets should stay in a 1:1 ratio, so the true exchange rate is 1. Any exchange rate < 1 could be considered the spread + let ask_asset_with_scaling_factor_gp = ask_asset.amount.to_uint128_with_precision(Decimal256::DECIMAL_PLACES)?; + let offer_amount_with_scaling_factor_excluding_fee_gp = offer_amount_with_scaling_factor_gp; + let spread_amount_gp = offer_amount_with_scaling_factor_excluding_fee_gp.saturating_sub(ask_asset_with_scaling_factor_gp); + + let spread_amount_without_scaling_factor = Decimal256::with_precision(spread_amount_gp, Decimal256::DECIMAL_PLACES as u32)? + .without_scaling_factor(ask_asset_scaling_factor)? + .to_uint128_with_precision(ask_precision)?; + + Ok((offer_amount_including_fee_uint128, spread_amount_without_scaling_factor, fee_uint128)) } // --------x--------x--------x--------x--------x--------x-------- diff --git a/contracts/pools/stable_pool/tests/integration.rs b/contracts/pools/stable_pool/tests/integration.rs index df2c3ad7..02a687e3 100644 --- a/contracts/pools/stable_pool/tests/integration.rs +++ b/contracts/pools/stable_pool/tests/integration.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{from_json, to_json_binary, Addr, Coin, Decimal, Timestamp, Uint128}; +use cosmwasm_std::{from_json, to_json_binary, Addr, Coin, Timestamp, Uint128}; use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg}; use cw_multi_test::Executor; @@ -10,8 +10,8 @@ use dexter::vault::{ SwapType, }; -use stable_pool::math::{MAX_AMP, MAX_AMP_CHANGE, MIN_AMP_CHANGING_TIME}; -use stable_pool::state::{StablePoolParams, StablePoolUpdateParams}; +use dexter_stable_pool::math::{MAX_AMP, MAX_AMP_CHANGE, MIN_AMP_CHANGING_TIME}; +use dexter_stable_pool::state::{StablePoolParams, StablePoolUpdateParams}; use crate::utils::*; pub mod utils; @@ -299,42 +299,6 @@ fn test_update_config() { let params: StablePoolParams = from_json(&res.additional_params.unwrap()).unwrap(); assert_eq!(params.amp, 20u64); - // Change max allowed spread limits for trades - let msg = ExecuteMsg::UpdateConfig { - params: to_json_binary(&StablePoolUpdateParams::UpdateMaxAllowedSpread { - max_allowed_spread: Decimal::percent(90), - }) - .unwrap(), - }; - - app.execute_contract(owner.clone(), pool_addr.clone(), &msg, &[]).unwrap(); - - // validate max allowed spread change - let res: ConfigResponse = app - .wrap() - .query_wasm_smart(pool_addr.clone(), &QueryMsg::Config {}) - .unwrap(); - - let params: StablePoolParams = from_json(&res.additional_params.unwrap()).unwrap(); - assert_eq!(params.max_allowed_spread, Decimal::percent(90)); - - // try updating max spread to an invalid value - let msg = ExecuteMsg::UpdateConfig { - params: to_json_binary(&StablePoolUpdateParams::UpdateMaxAllowedSpread { - max_allowed_spread: Decimal::percent(100), - }) - .unwrap(), - }; - - let resp = app - .execute_contract(owner.clone(), pool_addr.clone(), &msg, &[]) - .unwrap_err(); - - assert_eq!( - resp.root_cause().to_string(), - "Invalid max allowed spread. Max allowed spread should be positive non-zero value less than 1" - ); - } /// Tests the following - @@ -1806,8 +1770,6 @@ fn test_swap() { denom: "axlusd".to_string(), }, amount: Uint128::from(1000u128), - max_spread: None, - belief_price: None, }, ) .unwrap(); @@ -1829,8 +1791,6 @@ fn test_swap() { contract_addr: token_instance0.clone(), }, amount: Uint128::from(1000u128), - max_spread: None, - belief_price: None, }, ) .unwrap(); @@ -1881,8 +1841,6 @@ fn test_swap() { contract_addr: token_instance0.clone(), }, amount: Uint128::from(1000u128), - max_spread: Some(Decimal::from_ratio(1u128, 10u128)), - belief_price: None, }, ) .unwrap(); @@ -1897,7 +1855,7 @@ fn test_swap() { ); assert_eq!( swap_offer_asset_res.trade_params.spread, - Uint128::from(0u128) + Uint128::from(5u128) ); assert_eq!( swap_offer_asset_res.fee.clone().unwrap().info, @@ -1950,8 +1908,6 @@ fn test_swap() { contract_addr: token_instance0.clone(), }, amount: Uint128::from(7846_00000u128), - max_spread: Some(Decimal::from_ratio(2u128, 10u128)), - belief_price: None, }, ) .unwrap(); @@ -1966,7 +1922,7 @@ fn test_swap() { ); assert_eq!( swap_offer_asset_res.trade_params.spread, - Uint128::from(0u128) + Uint128::from(5341176u128) ); assert_eq!( swap_offer_asset_res.fee.clone().unwrap().info, @@ -1994,8 +1950,6 @@ fn test_swap() { contract_addr: token_instance0.clone(), }, amount: Uint128::from(30000_000000u128), - max_spread: Some(Decimal::from_ratio(1u128, 100u128)), - belief_price: None, }, ) .unwrap(); @@ -2015,7 +1969,7 @@ fn test_swap() { ); assert_eq!( swap_offer_asset_res.trade_params.spread, - Uint128::from(0u128) + Uint128::from(1949253782u128) ); assert_eq!(swap_offer_asset_res.fee.clone(), Some(Asset { info: AssetInfo::NativeToken { @@ -2038,8 +1992,6 @@ fn test_swap() { contract_addr: token_instance1.clone(), }, amount: Uint128::from(50000_000000u128), - max_spread: Some(Decimal::from_ratio(2u128, 100u128)), - belief_price: None, }, ) .unwrap(); @@ -2058,7 +2010,7 @@ fn test_swap() { ); assert_eq!( swap_offer_asset_res.trade_params.spread, - Uint128::from(0u128) + Uint128::from(11552_075912u128) ); assert_eq!(swap_offer_asset_res.fee.clone(), Some(Asset { info: native_asset_info("axlusd".to_string()), @@ -2079,8 +2031,6 @@ fn test_swap() { contract_addr: token_instance0.clone(), }, amount: Uint128::from(1000u128), - max_spread: Some(Decimal::from_ratio(20u128, 100u128)), - belief_price: None, }, recipient: None, min_receive: None, @@ -2180,8 +2130,6 @@ fn test_swap() { denom: "axlusd".to_string(), }, amount: Uint128::from(1000u128), - max_spread: Some(Decimal::from_ratio(20u128, 100u128)), - belief_price: None, }, recipient: None, min_receive: None, diff --git a/contracts/pools/stable_pool/tests/scaling_factor_simulation.rs b/contracts/pools/stable_pool/tests/scaling_factor_simulation.rs index 082f5cd8..4cf866a1 100644 --- a/contracts/pools/stable_pool/tests/scaling_factor_simulation.rs +++ b/contracts/pools/stable_pool/tests/scaling_factor_simulation.rs @@ -9,7 +9,7 @@ use cosmwasm_std::{Uint128, Addr, Coin, Decimal, Decimal256}; use cw_multi_test::{App, Executor}; use dexter::{asset::{AssetInfo, Asset}, vault::{FeeInfo, ExecuteMsg, SwapType, SingleSwapRequest}, pool::{SwapResponse, ConfigResponse}}; use itertools::Itertools; -use stable_pool::state::AssetScalingFactor; +use dexter_stable_pool::state::AssetScalingFactor; use dexter::pool::QueryMsg as PoolQueryMsg; use crate::utils::*; @@ -118,14 +118,11 @@ impl StableSwapSimulation { } fn perform_swap(&mut self) -> Result<(Uint128, Uint128, Uint128)> { - let max_spread = Some(Decimal::from_ratio(50u128, 100u128)); let swap_query_msg = PoolQueryMsg::OnSwap { swap_type: SwapType::GiveIn {}, offer_asset: self.swap_in_asset.clone(), ask_asset: self.swap_out_asset.clone(), amount: self.swap_in_amount, - max_spread: max_spread.clone(), - belief_price: None }; let swap_response: SwapResponse = self.app.wrap().query_wasm_smart(&self.pool, &swap_query_msg).unwrap(); @@ -142,8 +139,6 @@ impl StableSwapSimulation { asset_in: self.swap_in_asset.clone(), asset_out: self.swap_out_asset.clone(), amount: self.swap_in_amount, - max_spread: max_spread.clone(), - belief_price: None, }, recipient: None, min_receive: None, diff --git a/contracts/pools/stable_pool/tests/test_scaling_factor.rs b/contracts/pools/stable_pool/tests/test_scaling_factor.rs index f472f075..04fa0fdf 100644 --- a/contracts/pools/stable_pool/tests/test_scaling_factor.rs +++ b/contracts/pools/stable_pool/tests/test_scaling_factor.rs @@ -7,7 +7,7 @@ use crate::utils::{ perform_and_test_swap_give_out, store_token_code, validate_culumative_prices, log_pool_info }; -use cosmwasm_std::{to_json_binary, Addr, Coin, Decimal, Decimal256, Uint128}; +use cosmwasm_std::{to_json_binary, Addr, Coin, Decimal256, Uint128}; use cw20::Cw20ExecuteMsg; use cw_multi_test::Executor; use dexter::asset::{Asset, AssetExchangeRate, AssetInfo}; @@ -16,7 +16,7 @@ use dexter::vault::{Cw20HookMsg, ExecuteMsg, FeeInfo, PoolInfoResponse, QueryMsg use itertools::Itertools; use dexter::vault; -use stable_pool::state::AssetScalingFactor; +use dexter_stable_pool::state::AssetScalingFactor; pub mod utils; @@ -347,7 +347,6 @@ fn test_swap() { AssetInfo::NativeToken { denom: "uatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(10_173_469u128), Uint128::from(0u128), Asset { @@ -375,9 +374,8 @@ fn test_swap() { AssetInfo::NativeToken { denom: "uatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(1_017_336_487u128), - Uint128::from(0u128), + Uint128::from(10_451u128), Asset { info: AssetInfo::NativeToken { denom: "ustkatom".to_string(), @@ -403,9 +401,8 @@ fn test_swap() { AssetInfo::NativeToken { denom: "ustkatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(982_978_603u128), - Uint128::from(0u128), + Uint128::from(30_273u128), Asset { info: AssetInfo::NativeToken { denom: "ustkatom".to_string(), @@ -503,7 +500,6 @@ fn test_swap_different_precision() { AssetInfo::NativeToken { denom: "uatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(10_173_469u128), Uint128::from(0u128), Asset { @@ -531,9 +527,8 @@ fn test_swap_different_precision() { AssetInfo::NativeToken { denom: "uatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(1_017_336_487u128), - Uint128::from(0u128), + Uint128::from(10_451u128), Asset { info: AssetInfo::NativeToken { denom: "ustkatom".to_string(), @@ -559,9 +554,8 @@ fn test_swap_different_precision() { AssetInfo::NativeToken { denom: "ustkatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(982_978_603_388u128), - Uint128::from(0u128), + Uint128::from(30_273u128), Asset { info: AssetInfo::NativeToken { denom: "ustkatom".to_string(), @@ -705,7 +699,6 @@ fn test_swap_different_lsd_assets() { amount: Uint128::new(10_000_000_000u128), }, st_atom_asset.clone(), - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(9_766_530u128), Uint128::from(0u128), Asset { @@ -753,9 +746,8 @@ fn test_swap_different_lsd_assets() { AssetInfo::NativeToken { denom: "ustatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(976_643_026u128), - Uint128::from(0u128), + Uint128::from(10_033u128), Asset { info: AssetInfo::NativeToken { denom: "ustkatom".to_string(), @@ -803,9 +795,8 @@ fn test_swap_different_lsd_assets() { AssetInfo::NativeToken { denom: "ustkatom".to_string(), }, - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(1_023_936_467_628u128), - Uint128::from(0u128), + Uint128::from(30_685u128), Asset { info: AssetInfo::NativeToken { denom: "ustkatom".to_string(), @@ -982,9 +973,8 @@ fn test_5_asset_lsd_pool_with_different_precisions() { ), }, atom_asset.clone(), - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(1_038_125u128), - Uint128::from(0u128), + Uint128::from(416u128), Asset { info: statom_asset.clone(), amount: Uint128::from(3_000u128), @@ -1007,9 +997,8 @@ fn test_5_asset_lsd_pool_with_different_precisions() { ), }, qatom_asset.clone(), - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(10_277_441_665_935_813u128), - Uint128::from(0u128), + Uint128::from(4_120_834_064_186u128), Asset { info: statom_asset.clone(), amount: Uint128::from(30_000_000u128), @@ -1032,7 +1021,6 @@ fn test_5_asset_lsd_pool_with_different_precisions() { ), }, wrapped_atom_asset.clone(), - Some(Decimal::from_ratio(20u64, 100u64)), Uint128::from(10_233_757_152u128), Uint128::from(0u128), Asset { diff --git a/contracts/pools/stable_pool/tests/utils/mod.rs b/contracts/pools/stable_pool/tests/utils/mod.rs index af36dabe..5b7392f4 100644 --- a/contracts/pools/stable_pool/tests/utils/mod.rs +++ b/contracts/pools/stable_pool/tests/utils/mod.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use cosmwasm_std::testing::mock_env; -use cosmwasm_std::{attr, to_json_binary, Addr, Coin, Decimal, Decimal256, Timestamp, Uint128}; +use cosmwasm_std::{attr, to_json_binary, Addr, Coin, Decimal256, Timestamp, Uint128}; use cw20::{BalanceResponse, Cw20QueryMsg, MinterResponse}; use cw_multi_test::{App, ContractWrapper, Executor}; @@ -22,7 +22,7 @@ use cw20::Cw20ExecuteMsg; use dexter::pool::ExitType::ExactLpBurn; use dexter::vault; use itertools::Itertools; -use stable_pool::state::{AssetScalingFactor, MathConfig, StablePoolParams}; +use dexter_stable_pool::state::{AssetScalingFactor, MathConfig, StablePoolParams}; pub const EPOCH_START: u64 = 1_000_000; @@ -52,18 +52,18 @@ pub fn store_vault_code(app: &mut App) -> u64 { pub fn store_stable_pool_code(app: &mut App) -> u64 { let pool_contract = Box::new(ContractWrapper::new_with_empty( - stable_pool::contract::execute, - stable_pool::contract::instantiate, - stable_pool::contract::query, + dexter_stable_pool::contract::execute, + dexter_stable_pool::contract::instantiate, + dexter_stable_pool::contract::query, )); app.store_code(pool_contract) } pub fn store_token_code(app: &mut App) -> u64 { let token_contract = Box::new(ContractWrapper::new_with_empty( - lp_token::contract::execute, - lp_token::contract::instantiate, - lp_token::contract::query, + dexter_lp_token::contract::execute, + dexter_lp_token::contract::instantiate, + dexter_lp_token::contract::query, )); app.store_code(token_contract) } @@ -148,7 +148,6 @@ pub fn instantiate_contract_generic( scaling_factors, supports_scaling_factors_update: false, scaling_factor_manager: None, - max_allowed_spread: Decimal::from_ratio(50u128, 100u128), }) .unwrap(), ), @@ -530,7 +529,6 @@ pub fn perform_and_test_swap_give_in( pool_id: Uint128, asset_in: Asset, asset_out: AssetInfo, - max_spread: Option, expected_asset_out: Uint128, expected_spread: Uint128, expected_fee: Asset, @@ -540,8 +538,6 @@ pub fn perform_and_test_swap_give_in( offer_asset: asset_in.info.clone(), ask_asset: asset_out.clone(), amount: asset_in.amount, - max_spread, - belief_price: None, }; let swap_query_res: SwapResponse = app @@ -587,8 +583,6 @@ pub fn perform_and_test_swap_give_in( asset_in: asset_in.info, asset_out, amount: asset_in.amount, - max_spread, - belief_price: None, }, recipient: None, min_receive: None, @@ -608,7 +602,6 @@ pub fn perform_and_test_swap_give_out( pool_id: Uint128, asset_out: Asset, asset_in: AssetInfo, - max_spread: Option, expected_asset_in: Uint128, expected_spread: Uint128, expected_fee: Asset, @@ -618,8 +611,6 @@ pub fn perform_and_test_swap_give_out( offer_asset: asset_in.clone(), ask_asset: asset_out.info.clone(), amount: asset_out.amount, - max_spread, - belief_price: None, }; let swap_query_res: SwapResponse = app @@ -665,8 +656,6 @@ pub fn perform_and_test_swap_give_out( asset_in, asset_out: asset_out.info, amount: asset_out.amount, - max_spread, - belief_price: None, }, recipient: None, min_receive: None, diff --git a/contracts/pools/weighted_pool/Cargo.toml b/contracts/pools/weighted_pool/Cargo.toml index 11d39169..9cf7f134 100644 --- a/contracts/pools/weighted_pool/Cargo.toml +++ b/contracts/pools/weighted_pool/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "weighted-pool" -version = "1.0.0" -authors = ["AstroTechLabs"] +name = "dexter-weighted-pool" +version = "1.1.1" +authors = ["Persistence Labs"] edition = "2021" description = "A Dexter DEX pool implementing the generalized constant product AMM type as introduced by Balancer" license = "MIT" @@ -24,10 +24,10 @@ backtraces = ["cosmwasm-std/backtraces"] [dependencies] integer-sqrt = "0.1.5" -dexter = { path = "../../../packages/dexter", default-features = false } +dexter = { version = "1.4.0", path = "../../../packages/dexter", default-features = false } cw2 = "1.0.1" cw20 = "1.0.1" -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" cw-storage-plus = "1.0.1" schemars = "0.8.11" serde = { version = "1.0.152", default-features = false, features = ["derive"] } @@ -39,6 +39,6 @@ const_format = "0.2.30" [dev-dependencies] cw-multi-test = "0.16.2" -dexter-vault = {path = "../../vault"} -lp-token = {path = "../../lp_token"} +dexter-vault = { path = "../../vault"} +dexter-lp-token = { path = "../../lp_token"} proptest = "0.10.1" diff --git a/contracts/pools/weighted_pool/schema/weighted-pool.json b/contracts/pools/weighted_pool/schema/dexter-weighted-pool.json similarity index 93% rename from contracts/pools/weighted_pool/schema/weighted-pool.json rename to contracts/pools/weighted_pool/schema/dexter-weighted-pool.json index 24d89e71..76cd7919 100644 --- a/contracts/pools/weighted_pool/schema/weighted-pool.json +++ b/contracts/pools/weighted_pool/schema/dexter-weighted-pool.json @@ -1,6 +1,6 @@ { - "contract_name": "weighted-pool", - "contract_version": "1.0.0", + "contract_name": "dexter-weighted-pool", + "contract_version": "1.1.1", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", @@ -523,26 +523,6 @@ "ask_asset": { "$ref": "#/definitions/AssetInfo" }, - "belief_price": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, - "max_spread": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, "offer_asset": { "$ref": "#/definitions/AssetInfo" }, @@ -555,6 +535,32 @@ }, "additionalProperties": false }, + { + "title": "Description - Returns the spot price of the asset in a [`SpotPrice`] object.", + "type": "object", + "required": [ + "spot_price" + ], + "properties": { + "spot_price": { + "type": "object", + "required": [ + "ask_asset", + "offer_asset" + ], + "properties": { + "ask_asset": { + "$ref": "#/definitions/AssetInfo" + }, + "offer_asset": { + "$ref": "#/definitions/AssetInfo" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "title": "Description - Returns information about the cumulative price of the asset in a [`CumulativePriceResponse`] object.", "type": "object", @@ -677,10 +683,6 @@ } ] }, - "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" - }, "ExitType": { "description": "This struct describes the ways one can choose to exit from a pool.", "oneOf": [ @@ -769,8 +771,21 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "MigrateMsg", "description": "This struct describes a migration message. We currently take no arguments for migrations.", - "type": "object", - "additionalProperties": false + "oneOf": [ + { + "type": "object", + "required": [ + "v1_1" + ], + "properties": { + "v1_1": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] }, "sudo": null, "responses": { @@ -1732,6 +1747,91 @@ "title": "Uint128", "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" + }, + "spot_price": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "SpotPrice", + "type": "object", + "required": [ + "from", + "price", + "price_including_fee", + "to" + ], + "properties": { + "from": { + "$ref": "#/definitions/AssetInfo" + }, + "price": { + "$ref": "#/definitions/Decimal256" + }, + "price_including_fee": { + "$ref": "#/definitions/Decimal256" + }, + "to": { + "$ref": "#/definitions/AssetInfo" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types.", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + } + } } } } diff --git a/contracts/pools/weighted_pool/src/contract.rs b/contracts/pools/weighted_pool/src/contract.rs index 1dfa1643..cfd0a5ac 100644 --- a/contracts/pools/weighted_pool/src/contract.rs +++ b/contracts/pools/weighted_pool/src/contract.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{ MessageInfo, Response, StdError, StdResult, Uint128, }; -use cw2::set_contract_version; +use cw2::{get_contract_version, set_contract_version}; use dexter::asset::{Asset, AssetExchangeRate, AssetInfo, Decimal256Ext, DecimalAsset}; use dexter::helper::{calculate_underlying_fees, EventExt, select_pools}; use dexter::pool::{return_exit_failure, return_join_failure, return_swap_failure, store_precisions, update_fee, AfterExitResponse, AfterJoinResponse, Config, ConfigResponse, CumulativePriceResponse, CumulativePricesResponse, ExecuteMsg, ExitType, FeeResponse, InstantiateMsg, MigrateMsg, QueryMsg, ResponseType, SpotPrice, SwapResponse, Trade}; @@ -27,6 +27,7 @@ use cosmwasm_std::Event; const CONTRACT_NAME: &str = "dexter-weighted-pool"; /// Contract version that is used for migration. const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const CONTRACT_VERSION_V1: &str = "1.0.0"; /// Number of LP tokens to mint when liquidity is provided for the first time to the pool. /// This does not include the token decimals. @@ -36,6 +37,8 @@ const MAX_ASSETS: usize = 8; /// Minimum number of assets supported by the pool const MIN_ASSETS: usize = 2; +type ContractResult = Result; + // ----------------x----------------x----------------x----------------x----------------x---------------- // ----------------x----------------x Instantiate Contract : Execute function x---------------- // ----------------x----------------x----------------x----------------x----------------x---------------- @@ -284,8 +287,6 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { offer_asset, ask_asset, amount, - max_spread, - belief_price, } => to_json_binary(&query_on_swap( deps, env, @@ -293,8 +294,6 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { offer_asset, ask_asset, amount, - max_spread, - belief_price, )?), QueryMsg::SpotPrice { offer_asset, ask_asset } => { to_json_binary(&query_spot_price(deps, env, offer_asset, ask_asset)?) @@ -750,9 +749,7 @@ pub fn query_on_swap( swap_type: SwapType, offer_asset_info: AssetInfo, ask_asset_info: AssetInfo, - amount: Uint128, - _max_spread: Option, - _belief_price: Option, + amount: Uint128 ) -> StdResult { // Load the config and math config from the storage let config: Config = CONFIG.load(deps.storage)?; @@ -1002,7 +999,29 @@ pub fn query_cumulative_prices(deps: Deps, env: Env) -> StdResult StdResult { - Ok(Response::default()) -} +pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> ContractResult { + match msg { + MigrateMsg::V1_1 {} => { + // fetch current version to ensure it's v1 + let version = get_contract_version(deps.storage)?; + if version.version != CONTRACT_VERSION_V1 { + return Err(ContractError::InvalidContractVersion { + expected_version: CONTRACT_VERSION_V1.to_string(), + current_version: version.version, + }); + } + + if version.contract != CONTRACT_NAME { + return Err(ContractError::InvalidContractName { + expected_name: CONTRACT_NAME.to_string(), + contract_name: version.contract, + }); + } + + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + Ok(Response::default()) + } + } +} \ No newline at end of file diff --git a/contracts/pools/weighted_pool/src/error.rs b/contracts/pools/weighted_pool/src/error.rs index dcc2ceee..5c0d6a2b 100644 --- a/contracts/pools/weighted_pool/src/error.rs +++ b/contracts/pools/weighted_pool/src/error.rs @@ -57,6 +57,18 @@ pub enum ContractError { #[error("Pair type mismatch. Check factory pair configs")] PoolTypeMismatch {}, + + #[error("Invalid contract version for upgrade. Expected version: {expected_version} Found: {current_version}")] + InvalidContractVersion { + current_version: String, + expected_version: String, + }, + + #[error("Invalid contract name for upgrade. Expected name: {expected_name} Found: {contract_name}")] + InvalidContractName { + contract_name: String, + expected_name: String, + }, } impl From for ContractError { diff --git a/contracts/pools/weighted_pool/src/utils.rs b/contracts/pools/weighted_pool/src/utils.rs index 5b7add55..2c99e9f9 100644 --- a/contracts/pools/weighted_pool/src/utils.rs +++ b/contracts/pools/weighted_pool/src/utils.rs @@ -51,22 +51,27 @@ pub(crate) fn compute_swap( // delta balanceOut is positive(tokens inside the pool decreases) let return_amount = solve_constant_function_invariant( - Decimal::from_str(&offer_pool.amount.to_string())?, - Decimal::from_str(&pool_post_swap_in_balance.to_string())?, + decimal256_to_decimal(offer_pool.amount)?, + decimal256_to_decimal(pool_post_swap_in_balance)?, offer_weight, - Decimal::from_str(&ask_pool.amount.to_string())?, + decimal256_to_decimal(ask_pool.amount)?, ask_weight, )?; + + let return_amount_decimal_256 = decimal_to_decimal256(return_amount)?; // adjust return amount to correct precision - let return_amount = adjust_precision( - return_amount.atomics(), - return_amount.decimal_places() as u8, - token_precision, - )?; + let return_amount_u128 = return_amount_decimal_256.to_uint128_with_precision(token_precision)?; - // difference in return amount compared to "ideal" swap. - Ok((return_amount, Uint128::zero())) + + let spot_price_before_swap = calc_spot_price(&offer_pool, &ask_pool, offer_weight, ask_weight)?; + let ideal_received_amount_without_price_impact = spot_price_before_swap.checked_mul(offer_asset.amount)?; + + // spread amount is the difference of the actual received amount and the ideal received amount without price impact + let spread_amount = ideal_received_amount_without_price_impact.to_uint128_with_precision(token_precision)? + .checked_sub(return_amount_u128)?; + + Ok((return_amount_u128, spread_amount)) } /// ## Description @@ -97,6 +102,7 @@ pub(crate) fn compute_offer_amount( let inv_one_minus_commission = Decimal256::one() / one_minus_commission; let ask_asset_amount = decimal256_to_decimal(ask_asset.amount)?; + let ask_asset_precision = get_precision(storage, &ask_pool.info)?; // Ask pool balance after swap let pool_post_swap_out_balance = @@ -122,16 +128,24 @@ pub(crate) fn compute_offer_amount( offer_weight, )?; // adjust return amount to correct precision - let real_offer = adjust_precision( + let real_offer_u128 = adjust_precision( real_offer.atomics(), real_offer.decimal_places() as u8, token_precision, )?; - let offer_amount_including_fee = (Uint256::from(real_offer) * inv_one_minus_commission).try_into()?; - let total_fee = offer_amount_including_fee - real_offer; + let offer_amount_including_fee = (Uint256::from(real_offer_u128) * inv_one_minus_commission).try_into()?; + let total_fee = offer_amount_including_fee - real_offer_u128; + + let spot_price_before_swap = calc_spot_price(&offer_pool, &ask_pool, offer_weight, ask_weight)?; + let real_offer_decimal_256 = decimal_to_decimal256(real_offer)?; + let ideal_received_amount_without_price_impact = spot_price_before_swap.checked_mul(real_offer_decimal_256)?; + + // spread amount is the difference of the actual received amount and the ideal received amount without price impact + let spread_amount = ideal_received_amount_without_price_impact.to_uint128_with_precision(token_precision)? + .checked_sub(ask_asset.amount.to_uint128_with_precision(ask_asset_precision)?)?; - Ok((offer_amount_including_fee, Uint128::zero(), total_fee)) + Ok((offer_amount_including_fee, spread_amount, total_fee)) } // --------x--------x--------x--------x--------x--------x-------- diff --git a/contracts/pools/weighted_pool/tests/integration.rs b/contracts/pools/weighted_pool/tests/integration.rs index b5d5f1b6..1b585a98 100644 --- a/contracts/pools/weighted_pool/tests/integration.rs +++ b/contracts/pools/weighted_pool/tests/integration.rs @@ -12,7 +12,7 @@ use dexter::vault::{ PoolTypeConfig, PoolInfo, PoolInfoResponse, PoolType, QueryMsg as VaultQueryMsg, SingleSwapRequest, SwapType, PoolCreationFee, }; -use weighted_pool::state::{MathConfig, WeightedAsset, WeightedParams}; +use dexter_weighted_pool::state::{MathConfig, WeightedAsset, WeightedParams}; const EPOCH_START: u64 = 1_000_000; @@ -42,18 +42,18 @@ fn store_vault_code(app: &mut App) -> u64 { fn store_weighted_pool_code(app: &mut App) -> u64 { let pool_contract = Box::new(ContractWrapper::new_with_empty( - weighted_pool::contract::execute, - weighted_pool::contract::instantiate, - weighted_pool::contract::query, + dexter_weighted_pool::contract::execute, + dexter_weighted_pool::contract::instantiate, + dexter_weighted_pool::contract::query, )); app.store_code(pool_contract) } fn store_token_code(app: &mut App) -> u64 { let token_contract = Box::new(ContractWrapper::new_with_empty( - lp_token::contract::execute, - lp_token::contract::instantiate, - lp_token::contract::query, + dexter_lp_token::contract::execute, + dexter_lp_token::contract::instantiate, + dexter_lp_token::contract::query, )); app.store_code(token_contract) } @@ -1659,9 +1659,7 @@ fn test_swap() { ask_asset: AssetInfo::NativeToken { denom: "xprt".to_string(), }, - amount: Uint128::from(1000u128), - max_spread: None, - belief_price: None, + amount: Uint128::from(1000u128) }, ) .unwrap(); @@ -1682,9 +1680,7 @@ fn test_swap() { ask_asset: AssetInfo::Token { contract_addr: token_instance0.clone(), }, - amount: Uint128::from(1000u128), - max_spread: None, - belief_price: None, + amount: Uint128::from(1000u128) }, ) .unwrap(); @@ -1727,9 +1723,7 @@ fn test_swap() { ask_asset: AssetInfo::Token { contract_addr: token_instance0.clone(), }, - amount: Uint128::from(1000u128), - max_spread: Some(Decimal::from_ratio(1u128, 10u128)), - belief_price: None, + amount: Uint128::from(1000u128) }, ) .unwrap(); @@ -1742,17 +1736,96 @@ fn test_swap() { swap_offer_asset_res.trade_params.amount_out, Uint128::from(1177u128) ); + assert_eq!( + swap_offer_asset_res.trade_params.spread, + Uint128::from(0u128) + ); assert_eq!( swap_offer_asset_res.fee.clone().unwrap().info, AssetInfo::NativeToken { denom: "xprt".to_string(), } ); + assert_eq!( swap_offer_asset_res.fee.clone().unwrap().amount, Uint128::from(30u128) ); + // test with a large quantity to see the spread + let swap_offer_asset_res: SwapResponse = app + .wrap() + .query_wasm_smart( + pool_addr.clone(), + &QueryMsg::OnSwap { + swap_type: SwapType::GiveIn {}, + offer_asset: AssetInfo::NativeToken { + denom: "xprt".to_string(), + }, + ask_asset: AssetInfo::Token { + contract_addr: token_instance0.clone(), + }, + amount: Uint128::from(1_000_000u128) + }, + ) + .unwrap(); + + assert_eq!(swap_offer_asset_res.response, ResponseType::Success {}); + assert_eq!( + swap_offer_asset_res.trade_params.amount_in, + Uint128::from(1000000u128) + ); + assert_eq!( + swap_offer_asset_res.trade_params.amount_out, + Uint128::from(1_177_472u128) + ); + assert_eq!( + swap_offer_asset_res.trade_params.spread, + Uint128::from(24u128) + ); + + assert_eq!( + swap_offer_asset_res.fee.clone().unwrap().info, + AssetInfo::NativeToken { + denom: "xprt".to_string(), + } + ); + + // let's try with an even larger quantity to see the spread + let swap_offer_asset_res: SwapResponse = app + .wrap() + .query_wasm_smart( + pool_addr.clone(), + &QueryMsg::OnSwap { + swap_type: SwapType::GiveIn {}, + offer_asset: AssetInfo::NativeToken { + denom: "xprt".to_string(), + }, + ask_asset: AssetInfo::Token { + contract_addr: token_instance0.clone(), + }, + amount: Uint128::from(1000_000_000u128) + }, + ) + .unwrap(); + + + assert_eq!(swap_offer_asset_res.response, ResponseType::Success {}); + assert_eq!( + swap_offer_asset_res.trade_params.amount_in, + Uint128::from(1000_000_000u128) + ); + + assert_eq!( + swap_offer_asset_res.trade_params.amount_out, + Uint128::from(1153_558_568u128) + ); + + assert_eq!( + swap_offer_asset_res.trade_params.spread, + Uint128::from(23_938_383u128) + ); + // SwapType::GiveOut {}, XPRT --> Token0 // offer_asset_info : xprt ask_asset_info : contract1 amount : 1000 // offer_pool : xprt 46743.000000 @@ -1784,9 +1857,7 @@ fn test_swap() { ask_asset: AssetInfo::Token { contract_addr: token_instance0.clone(), }, - amount: Uint128::from(1000u128), - max_spread: Some(Decimal::from_ratio(2u128, 10u128)), - belief_price: None, + amount: Uint128::from(1000u128) }, ) .unwrap(); @@ -1807,6 +1878,46 @@ fn test_swap() { swap_offer_asset_res.fee.clone().unwrap().amount, Uint128::from(25u128) ); + println!("swap_offer_asset_res: {:?}", swap_offer_asset_res); + assert_eq!( + swap_offer_asset_res.trade_params.spread.clone(), + Uint128::from(0u128) + ); + + // let's try with a large quantity to see the spread + let swap_offer_asset_res: SwapResponse = app + .wrap() + .query_wasm_smart( + pool_addr.clone(), + &QueryMsg::OnSwap { + swap_type: SwapType::GiveOut {}, + offer_asset: AssetInfo::NativeToken { + denom: "xprt".to_string(), + }, + ask_asset: AssetInfo::Token { + contract_addr: token_instance0.clone(), + }, + amount: Uint128::from(100_000_000u128) + } + ) + .unwrap(); + + assert_eq!(swap_offer_asset_res.response, ResponseType::Success {}); + assert_eq!( + swap_offer_asset_res.trade_params.amount_out, + Uint128::from(100_000_000u128) + ); + + assert_eq!( + swap_offer_asset_res.trade_params.amount_in, + Uint128::from(85_075_844u128) + ); + + assert_eq!( + swap_offer_asset_res.trade_params.spread, + Uint128::from(176_547u128) + ); + // ----- Execute GiveIn Swap----- // let swap_msg = VaultExecuteMsg::Swap { @@ -1819,9 +1930,7 @@ fn test_swap() { asset_out: AssetInfo::Token { contract_addr: token_instance0.clone(), }, - amount: Uint128::from(1000u128), - max_spread: None, - belief_price: None, + amount: Uint128::from(1000u128) }, recipient: None, min_receive: None, @@ -1854,9 +1963,7 @@ fn test_swap() { asset_out: AssetInfo::Token { contract_addr: token_instance0.clone(), }, - amount: Uint128::from(1000u128), - max_spread: None, - belief_price: None, + amount: Uint128::from(1000u128) }, recipient: None, min_receive: None, diff --git a/contracts/router/Cargo.toml b/contracts/router/Cargo.toml index c369c417..60ffc056 100644 --- a/contracts/router/Cargo.toml +++ b/contracts/router/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "dexter-router" -version = "1.0.0" -authors = ["buidl@astrotechlabs.com"] +version = "1.1.0" +authors = ["Persistence Labs"] edition = "2021" description = "A router contract - provides multi-step operations to facilitate single sign operation" license = "MIT" @@ -14,11 +14,11 @@ backtraces = ["cosmwasm-std/backtraces"] [dependencies] -dexter = { path = "../../packages/dexter", default-features = false } +dexter = { version = "1.4.0", path = "../../packages/dexter", default-features = false } cw20 = "1.0.1" cw2 = "1.0.1" cw20-base = { version = "1.0.1", features = ["library"] } -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" cw-storage-plus = "1.0.1" schemars = "0.8.11" thiserror = "1.0.38" @@ -31,7 +31,7 @@ const_format = "0.2.30" # we only need to enable this if we use integration tests cw-multi-test = "0.16.2" dexter-vault = { path = "../vault"} -stable-pool = { path = "../pools/stable_pool" } -weighted-pool = { path = "../pools/weighted_pool"} -lp-token = { path = "../lp_token"} +dexter-stable-pool = { path = "../pools/stable_pool" } +dexter-weighted-pool = { path = "../pools/weighted_pool"} +dexter-lp-token = { path = "../lp_token"} cw20 = "1.0.1" diff --git a/contracts/router/schema/dexter-router.json b/contracts/router/schema/dexter-router.json index 20c4e142..d270b540 100644 --- a/contracts/router/schema/dexter-router.json +++ b/contracts/router/schema/dexter-router.json @@ -1,6 +1,6 @@ { "contract_name": "dexter-router", - "contract_version": "1.0.0", + "contract_version": "1.1.0", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", @@ -183,10 +183,6 @@ } ] }, - "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" - }, "HopSwapRequest": { "description": "This enum describes a swap operation.", "type": "object", @@ -212,26 +208,6 @@ } ] }, - "belief_price": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, - "max_spread": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, "pool_id": { "description": "Pool Id via which the swap is to be routed", "allOf": [ @@ -355,10 +331,6 @@ } ] }, - "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" - }, "HopSwapRequest": { "description": "This enum describes a swap operation.", "type": "object", @@ -384,26 +356,6 @@ } ] }, - "belief_price": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, - "max_spread": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, "pool_id": { "description": "Pool Id via which the swap is to be routed", "allOf": [ @@ -469,8 +421,21 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "MigrateMsg", "description": "This structure describes a migration message. We currently take no arguments for migrations.", - "type": "object", - "additionalProperties": false + "oneOf": [ + { + "type": "object", + "required": [ + "v1_1" + ], + "properties": { + "v1_1": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] }, "sudo": null, "responses": { diff --git a/contracts/router/src/contract.rs b/contracts/router/src/contract.rs index a9718949..32b2e976 100644 --- a/contracts/router/src/contract.rs +++ b/contracts/router/src/contract.rs @@ -16,6 +16,7 @@ use dexter::vault::{self, SingleSwapRequest, SwapType}; const CONTRACT_NAME: &str = "dexter-router"; /// Contract version that is used for migration. const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const CONTRACT_VERSION_V1: &str = "1.0.0"; // ----------------x----------------x----------------x----------------x----------------x---------------- // ----------------x----------------x Instantiate Contract : Execute function x---------------- @@ -219,9 +220,7 @@ pub fn execute_multihop_swap( asset_out: first_hop.asset_out.clone(), swap_type: SwapType::GiveIn {}, // Amount provided is the amount to be used for the first hop - amount: offer_amount, - max_spread: first_hop.max_spread, - belief_price: first_hop.belief_price, + amount: offer_amount }; // Need to send native tokens if the offer asset is native token @@ -369,8 +368,6 @@ pub fn continue_hop_swap( swap_type: SwapType::GiveIn {}, // Amount returned from prev hop is to be used for the next hop amount: amount_returned_prev_hop, - max_spread: next_hop.max_spread, - belief_price: next_hop.belief_price, }; // Need to send native tokens if the offer asset is native token @@ -521,8 +518,6 @@ fn query_simulate_multihop( offer_asset: next_token_in.clone(), ask_asset: hop.asset_out.clone(), amount: next_amount_in.clone(), - max_spread: hop.max_spread, - belief_price: hop.belief_price, })?, }))?; @@ -590,8 +585,6 @@ fn query_simulate_multihop( offer_asset: hop.asset_in.clone(), ask_asset: hop.asset_out.clone(), amount: prev_amount_out.clone(), - max_spread: hop.max_spread, - belief_price: hop.belief_price, })?, }))?; @@ -650,9 +643,32 @@ fn query_simulate_multihop( /// ## Params /// * **_msg** is the object of type [`MigrateMsg`]. #[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { +pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result { let contract_version = get_contract_version(deps.storage)?; - set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + // validate contract name + if contract_version.contract != CONTRACT_NAME { + return Err(ContractError::InvalidContractNameForMigration { + expected: CONTRACT_NAME.to_string(), + actual: contract_version.contract.to_string(), + }); + } + + match msg { + MigrateMsg::V1_1 {} => { + // validate that the current contarct version is V1 + if contract_version.version != CONTRACT_VERSION_V1 { + return Err(ContractError::InvalidContractVersionForUpgrade { + upgrade_version: CONTRACT_VERSION_V1.to_string(), + expected: CONTRACT_VERSION_V1.to_string(), + actual: contract_version.version.to_string(), + }); + } + + // No state migration required for this contract + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + } + } Ok(Response::new() .add_attribute("previous_contract_name", &contract_version.contract) diff --git a/contracts/router/src/error.rs b/contracts/router/src/error.rs index e4815156..7733da90 100644 --- a/contracts/router/src/error.rs +++ b/contracts/router/src/error.rs @@ -8,6 +8,16 @@ pub enum ContractError { #[error("Error: {0}", msg)] InvalidMultihopSwapRequest { msg: String }, + + #[error("Invalid contract version for upgrade {upgrade_version}. Expected: {expected}, Actual: {actual}")] + InvalidContractVersionForUpgrade { + upgrade_version: String, + expected: String, + actual: String, + }, + + #[error("Invalid contract name for migration. Expected: {expected}, Actual: {actual}")] + InvalidContractNameForMigration { expected: String, actual: String }, } impl From for ContractError { diff --git a/contracts/router/tests/integration.rs b/contracts/router/tests/integration.rs index 8089f03f..bb5e0593 100644 --- a/contracts/router/tests/integration.rs +++ b/contracts/router/tests/integration.rs @@ -52,27 +52,27 @@ fn store_vault_code(app: &mut App) -> u64 { fn store_token_code(app: &mut App) -> u64 { let token_contract = Box::new(ContractWrapper::new_with_empty( - lp_token::contract::execute, - lp_token::contract::instantiate, - lp_token::contract::query, + dexter_lp_token::contract::execute, + dexter_lp_token::contract::instantiate, + dexter_lp_token::contract::query, )); app.store_code(token_contract) } fn store_stable5_pool_code(app: &mut App) -> u64 { let pool_contract = Box::new(ContractWrapper::new_with_empty( - stable_pool::contract::execute, - stable_pool::contract::instantiate, - stable_pool::contract::query, + dexter_stable_pool::contract::execute, + dexter_stable_pool::contract::instantiate, + dexter_stable_pool::contract::query, )); app.store_code(pool_contract) } fn store_weighted_pool_code(app: &mut App) -> u64 { let pool_contract = Box::new(ContractWrapper::new_with_empty( - weighted_pool::contract::execute, - weighted_pool::contract::instantiate, - weighted_pool::contract::query, + dexter_weighted_pool::contract::execute, + dexter_weighted_pool::contract::instantiate, + dexter_weighted_pool::contract::query, )); app.store_code(pool_contract) } @@ -252,12 +252,11 @@ fn initialize_stable_5_pool( denom: denom1.clone(), precision: 6u8, }], - init_params: Some(to_json_binary(&stable_pool::state::StablePoolParams { + init_params: Some(to_json_binary(&dexter_stable_pool::state::StablePoolParams { amp: 10u64, scaling_factors: vec![], supports_scaling_factors_update: false, scaling_factor_manager: None, - max_allowed_spread: Decimal::from_ratio(50u128, 100u128) }).unwrap()), fee_info: None, }; @@ -360,7 +359,7 @@ fn initialize_weighted_pool( } ], init_params: Some( - to_json_binary(&weighted_pool::state::WeightedParams { + to_json_binary(&dexter_weighted_pool::state::WeightedParams { weights: asset_infos_with_weights, exit_fee: Some(Decimal::from_ratio(1u128, 100u128)), }) @@ -789,9 +788,7 @@ fn test_router_functionality() { }, asset_out: AssetInfo::Token { contract_addr: token_instance1.clone(), - }, - max_spread: None, - belief_price: None, + } }, HopSwapRequest { pool_id: Uint128::from(weighted_pool_id), @@ -800,9 +797,7 @@ fn test_router_functionality() { }, asset_out: AssetInfo::Token { contract_addr: token_instance2.clone(), - }, - max_spread: None, - belief_price: None, + } }, HopSwapRequest { pool_id: Uint128::from(stable5_pool_id), @@ -811,9 +806,7 @@ fn test_router_functionality() { }, asset_out: AssetInfo::NativeToken { denom: denom0.clone(), - }, - max_spread: None, - belief_price: None, + } }, HopSwapRequest { pool_id: Uint128::from(weighted_pool_id), @@ -822,9 +815,7 @@ fn test_router_functionality() { }, asset_out: AssetInfo::Token { contract_addr: token_instance1.clone(), - }, - max_spread: None, - belief_price: None, + } }, ] .to_vec(); @@ -1055,9 +1046,7 @@ fn test_router_functionality() { }, asset_out: AssetInfo::NativeToken { denom: denom0.clone(), - }, - max_spread: None, - belief_price: None, + } }, HopSwapRequest { pool_id: Uint128::from(weighted_pool_id), @@ -1066,9 +1055,7 @@ fn test_router_functionality() { }, asset_out: AssetInfo::Token { contract_addr: token_instance2.clone(), - }, - max_spread: None, - belief_price: None, + } }, HopSwapRequest { pool_id: Uint128::from(stable5_pool_id), @@ -1077,9 +1064,7 @@ fn test_router_functionality() { }, asset_out: AssetInfo::Token { contract_addr: token_instance3.clone(), - }, - max_spread: None, - belief_price: None, + } }, ] .to_vec(); diff --git a/contracts/superfluid_lp/Cargo.toml b/contracts/superfluid_lp/Cargo.toml index 6de0a384..e582c5d9 100644 --- a/contracts/superfluid_lp/Cargo.toml +++ b/contracts/superfluid_lp/Cargo.toml @@ -18,7 +18,7 @@ dexter = { path = "../../packages/dexter", default-features = false } cw20 = "1.0.1" cw2 = "1.0.1" cw20-base = { version = "1.0.1", features = ["library"] } -cosmwasm-std = "1.5.0" +cosmwasm-std = "1.5.4" cw-storage-plus = "1.0.1" schemars = "0.8.11" thiserror = "1.0.38" @@ -33,7 +33,7 @@ cw-utils = "1.0.3" cw-multi-test = "0.16.2" dexter-vault = { path = "../vault"} dexter-multi-staking = { path = "../multi_staking"} -stable-pool = { path = "../pools/stable_pool" } -weighted-pool = { path = "../pools/weighted_pool"} -lp-token = { path = "../lp_token"} +dexter-stable-pool = { path = "../pools/stable_pool" } +dexter-weighted-pool = { path = "../pools/weighted_pool"} +dexter-lp-token = { path = "../lp_token"} cw20 = "1.0.1" diff --git a/contracts/superfluid_lp/schema/dexter-superfluid-lp.json b/contracts/superfluid_lp/schema/dexter-superfluid-lp.json index f438445d..cb7100d6 100644 --- a/contracts/superfluid_lp/schema/dexter-superfluid-lp.json +++ b/contracts/superfluid_lp/schema/dexter-superfluid-lp.json @@ -183,10 +183,6 @@ } ] }, - "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" - }, "HopSwapRequest": { "description": "This enum describes a swap operation.", "type": "object", @@ -212,26 +208,6 @@ } ] }, - "belief_price": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, - "max_spread": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, "pool_id": { "description": "Pool Id via which the swap is to be routed", "allOf": [ @@ -355,10 +331,6 @@ } ] }, - "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" - }, "HopSwapRequest": { "description": "This enum describes a swap operation.", "type": "object", @@ -384,26 +356,6 @@ } ] }, - "belief_price": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, - "max_spread": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, "pool_id": { "description": "Pool Id via which the swap is to be routed", "allOf": [ @@ -469,8 +421,21 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "MigrateMsg", "description": "This structure describes a migration message. We currently take no arguments for migrations.", - "type": "object", - "additionalProperties": false + "oneOf": [ + { + "type": "object", + "required": [ + "v1_1" + ], + "properties": { + "v1_1": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] }, "sudo": null, "responses": { diff --git a/contracts/superfluid_lp/tests/integration.rs b/contracts/superfluid_lp/tests/integration.rs index 9aaef066..47168c65 100644 --- a/contracts/superfluid_lp/tests/integration.rs +++ b/contracts/superfluid_lp/tests/integration.rs @@ -53,18 +53,18 @@ fn store_vault_code(app: &mut App) -> u64 { fn store_weighted_pool_code(app: &mut App) -> u64 { let weighted_pool_contract = Box::new(ContractWrapper::new_with_empty( - weighted_pool::contract::execute, - weighted_pool::contract::instantiate, - weighted_pool::contract::query, + dexter_weighted_pool::contract::execute, + dexter_weighted_pool::contract::instantiate, + dexter_weighted_pool::contract::query, )); app.store_code(weighted_pool_contract) } fn store_token_code(app: &mut App) -> u64 { let token_contract = Box::new(ContractWrapper::new_with_empty( - lp_token::contract::execute, - lp_token::contract::instantiate, - lp_token::contract::query, + dexter_lp_token::contract::execute, + dexter_lp_token::contract::instantiate, + dexter_lp_token::contract::query, )); app.store_code(token_contract) } @@ -261,7 +261,7 @@ fn test_superfluid_lp_locking() { protocol_fee_percent: 30, }), init_params: to_json_binary( - &weighted_pool::state::WeightedParams { + &dexter_weighted_pool::state::WeightedParams { weights: vec![ Asset { info: AssetInfo::NativeToken { diff --git a/contracts/vault/Cargo.toml b/contracts/vault/Cargo.toml index ba4f36a6..03677e6d 100644 --- a/contracts/vault/Cargo.toml +++ b/contracts/vault/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "dexter-vault" -version = "1.0.0" -authors = ["AstroTechLabs"] +version = "1.1.0" +authors = ["Persistence Labs"] edition = "2021" -description = "Persistence DEX Factory contract - entry point to create new pools. Maintains directory for all pools" +description = "Dexter Factory contract - entry point to create new pools. Maintains directory for all pools" license = "MIT" exclude = [ @@ -24,8 +24,8 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -dexter = { path = "../../packages/dexter", default-features = false } -cosmwasm-std = "1.5.0" +dexter = { version = "1.4.0", path = "../../packages/dexter", default-features = false } +cosmwasm-std = "1.5.4" cw-storage-plus = "1.0.1" cw2 = "1.0.1" cw20 = "1.0.1" @@ -39,9 +39,9 @@ cosmwasm-schema = "1.5.0" const_format = "0.2.30" [dev-dependencies] -stable-pool = { path = "../pools/stable_pool" } -weighted-pool = { path = "../pools/weighted_pool"} -lp-token = { path = "../lp_token"} +dexter-stable-pool = { path = "../pools/stable_pool" } +dexter-weighted-pool = { path = "../pools/weighted_pool"} +dexter-lp-token = { path = "../lp_token"} dexter-multi-staking = { path = "../multi_staking"} cw-multi-test = "0.16.2" diff --git a/contracts/vault/schema/dexter-vault.json b/contracts/vault/schema/dexter-vault.json index 863b12e4..57783302 100644 --- a/contracts/vault/schema/dexter-vault.json +++ b/contracts/vault/schema/dexter-vault.json @@ -1,6 +1,6 @@ { "contract_name": "dexter-vault", - "contract_version": "1.0.0", + "contract_version": "1.1.0", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", @@ -989,10 +989,6 @@ }, "additionalProperties": false }, - "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" - }, "FeeInfo": { "title": "Description - This struct describes the Fee configuration supported by a particular pool type.", "type": "object", @@ -1225,26 +1221,6 @@ "asset_out": { "$ref": "#/definitions/AssetInfo" }, - "belief_price": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, - "max_spread": { - "anyOf": [ - { - "$ref": "#/definitions/Decimal" - }, - { - "type": "null" - } - ] - }, "pool_id": { "$ref": "#/definitions/Uint128" }, @@ -1345,6 +1321,40 @@ }, "additionalProperties": false }, + { + "description": "Returns the info of all the pools matching the given pagination params", + "type": "object", + "required": [ + "pools" + ], + "properties": { + "pools": { + "type": "object", + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "start_after": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "description": "Returns the current stored state of the Pool in custom [`PoolInfoResponse`] struct", "type": "object", @@ -1468,8 +1478,178 @@ "migrate": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "MigrateMsg", - "type": "object", - "additionalProperties": false + "oneOf": [ + { + "type": "object", + "required": [ + "v1_1" + ], + "properties": { + "v1_1": { + "type": "object", + "required": [ + "updated_pool_type_configs" + ], + "properties": { + "updated_pool_type_configs": { + "type": "array", + "items": { + "$ref": "#/definitions/PoolTypeConfig" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "AllowPoolInstantiation": { + "type": "string", + "enum": [ + "everyone", + "only_whitelisted_addresses", + "nobody" + ] + }, + "FeeInfo": { + "title": "Description - This struct describes the Fee configuration supported by a particular pool type.", + "type": "object", + "required": [ + "protocol_fee_percent", + "total_fee_bps" + ], + "properties": { + "protocol_fee_percent": { + "type": "integer", + "format": "uint16", + "minimum": 0.0 + }, + "total_fee_bps": { + "type": "integer", + "format": "uint16", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PauseInfo": { + "type": "object", + "required": [ + "deposit", + "imbalanced_withdraw", + "swap" + ], + "properties": { + "deposit": { + "description": "True if deposits are paused", + "type": "boolean" + }, + "imbalanced_withdraw": { + "type": "boolean" + }, + "swap": { + "description": "True if swaps are paused", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "PoolType": { + "description": "This enum describes the key for the different Pool types supported by Dexter", + "oneOf": [ + { + "description": "Stable pool type", + "type": "object", + "required": [ + "stable_swap" + ], + "properties": { + "stable_swap": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Weighted pool type", + "type": "object", + "required": [ + "weighted" + ], + "properties": { + "weighted": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Custom pool type", + "type": "object", + "required": [ + "custom" + ], + "properties": { + "custom": { + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "PoolTypeConfig": { + "description": "This struct stores a pool type's configuration.", + "type": "object", + "required": [ + "allow_instantiation", + "code_id", + "default_fee_info", + "paused", + "pool_type" + ], + "properties": { + "allow_instantiation": { + "description": "Controls whether the pool can be created by anyone or only by whitelisted addresses (if any) or not at all", + "allOf": [ + { + "$ref": "#/definitions/AllowPoolInstantiation" + } + ] + }, + "code_id": { + "description": "ID of contract which is used to create pools of this type", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "default_fee_info": { + "$ref": "#/definitions/FeeInfo" + }, + "paused": { + "description": "The pause status for this pool type. This overrides the pause status of any pool id of this type.", + "allOf": [ + { + "$ref": "#/definitions/PauseInfo" + } + ] + }, + "pool_type": { + "description": "The pools type (provided in a [`PoolType`])", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + } + }, + "additionalProperties": false + } + } }, "sudo": null, "responses": { @@ -2470,6 +2650,260 @@ } } }, + "pools": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_PoolInfo", + "type": "array", + "items": { + "$ref": "#/definitions/PoolInfo" + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Asset": { + "title": "Description - This enum describes a asset (native or CW20).", + "type": "object", + "required": [ + "amount", + "info" + ], + "properties": { + "amount": { + "description": "A token amount", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "info": { + "description": "Information about an asset stored in a [`AssetInfo`] struct", + "allOf": [ + { + "$ref": "#/definitions/AssetInfo" + } + ] + } + }, + "additionalProperties": false + }, + "AssetInfo": { + "description": "This enum describes available Token types.", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "FeeInfo": { + "title": "Description - This struct describes the Fee configuration supported by a particular pool type.", + "type": "object", + "required": [ + "protocol_fee_percent", + "total_fee_bps" + ], + "properties": { + "protocol_fee_percent": { + "type": "integer", + "format": "uint16", + "minimum": 0.0 + }, + "total_fee_bps": { + "type": "integer", + "format": "uint16", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "PauseInfo": { + "type": "object", + "required": [ + "deposit", + "imbalanced_withdraw", + "swap" + ], + "properties": { + "deposit": { + "description": "True if deposits are paused", + "type": "boolean" + }, + "imbalanced_withdraw": { + "type": "boolean" + }, + "swap": { + "description": "True if swaps are paused", + "type": "boolean" + } + }, + "additionalProperties": false + }, + "PoolInfo": { + "description": "This struct stores a pool type's configuration.", + "type": "object", + "required": [ + "assets", + "fee_info", + "lp_token_addr", + "paused", + "pool_addr", + "pool_id", + "pool_type" + ], + "properties": { + "assets": { + "description": "Assets and their respective balances", + "type": "array", + "items": { + "$ref": "#/definitions/Asset" + } + }, + "fee_info": { + "description": "Fee charged by the pool for swaps", + "allOf": [ + { + "$ref": "#/definitions/FeeInfo" + } + ] + }, + "lp_token_addr": { + "description": "Address of the LP Token Contract", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "paused": { + "description": "Pause status for this pool", + "allOf": [ + { + "$ref": "#/definitions/PauseInfo" + } + ] + }, + "pool_addr": { + "description": "Address of the Pool Contract", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "pool_id": { + "description": "ID of this pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "pool_type": { + "description": "The pools type (provided in a [`PoolType`])", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + } + }, + "additionalProperties": false + }, + "PoolType": { + "description": "This enum describes the key for the different Pool types supported by Dexter", + "oneOf": [ + { + "description": "Stable pool type", + "type": "object", + "required": [ + "stable_swap" + ], + "properties": { + "stable_swap": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Weighted pool type", + "type": "object", + "required": [ + "weighted" + ], + "properties": { + "weighted": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Custom pool type", + "type": "object", + "required": [ + "custom" + ], + "properties": { + "custom": { + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + } + } + }, "query_registry": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Nullable_PoolTypeConfig", diff --git a/contracts/vault/src/contract.rs b/contracts/vault/src/contract.rs index be969a57..ec6cdcb8 100644 --- a/contracts/vault/src/contract.rs +++ b/contracts/vault/src/contract.rs @@ -16,7 +16,7 @@ use std::collections::HashSet; use const_format::concatcp; use dexter::asset::{addr_opt_validate, Asset, AssetInfo}; -use dexter::helper::{build_transfer_cw20_from_user_msg, claim_ownership, drop_ownership_proposal, EventExt, find_sent_native_token_balance, get_lp_token_name, get_lp_token_symbol, propose_new_owner}; +use dexter::helper::{build_transfer_cw20_from_user_msg, claim_ownership, DEFAULT_LIMIT, drop_ownership_proposal, EventExt, find_sent_native_token_balance, get_lp_token_name, get_lp_token_symbol, MAX_LIMIT, propose_new_owner}; use dexter::lp_token::InstantiateMsg as TokenInstantiateMsg; use dexter::pool::{FeeStructs, InstantiateMsg as PoolInstantiateMsg}; use dexter::vault::{AllowPoolInstantiation, AssetFeeBreakup, AutoStakeImpl, Config, ConfigResponse, Cw20HookMsg, ExecuteMsg, FeeInfo, InstantiateMsg, MigrateMsg, PauseInfo, PoolTypeConfigResponse, PoolInfo, PoolInfoResponse, PoolType, PoolTypeConfig, QueryMsg, SingleSwapRequest, TmpPoolInfo, PoolCreationFee, PauseInfoUpdateType, ExitType, NativeAssetPrecisionInfo}; @@ -29,6 +29,8 @@ use dexter::pool; const CONTRACT_NAME: &str = "dexter-vault"; /// Contract version that is used for migration. const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const CONTRACT_VERSION_V1: &str = "1.0.0"; + /// A `reply` call code ID of sub-message. const INSTANTIATE_LP_REPLY_ID: u64 = 1; const INSTANTIATE_POOL_REPLY_ID: u64 = 2; @@ -1650,9 +1652,7 @@ pub fn execute_swap( swap_type: swap_request.swap_type.clone(), offer_asset: swap_request.asset_in.clone(), ask_asset: swap_request.asset_out.clone(), - amount: swap_request.amount, - max_spread: swap_request.max_spread, - belief_price: swap_request.belief_price, + amount: swap_request.amount })?, }))?; @@ -1687,12 +1687,8 @@ pub fn execute_swap( .add_attribute("asset_in", serde_json_wasm::to_string(&offer_asset).unwrap()) .add_attribute("asset_out", serde_json_wasm::to_string(&ask_asset).unwrap()) .add_attribute("swap_type", swap_request.swap_type.to_string()); - if swap_request.max_spread.is_some() { - event = event.add_attribute("max_spread", swap_request.max_spread.unwrap().to_string()); - } - if swap_request.belief_price.is_some() { - event = event.add_attribute("belief_price", swap_request.belief_price.unwrap().to_string()); - } + + event = event.add_attribute("recipient", recipient.to_string()); if min_receive.is_some() { event = event.add_attribute("min_receive", min_receive.unwrap().to_string()); @@ -1861,6 +1857,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { QueryMsg::Config {} => to_json_binary(&query_config(deps)?), QueryMsg::QueryRegistry { pool_type } => to_json_binary(&query_registry(deps, pool_type)?), QueryMsg::GetPoolById { pool_id } => to_json_binary(&query_pool_by_id(deps, pool_id)?), + QueryMsg::Pools { start_after, limit } => to_json_binary(&query_pools(deps, start_after, limit)?), QueryMsg::GetPoolByAddress { pool_addr } => { to_json_binary(&query_pool_by_addr(deps, pool_addr)?) } @@ -1890,6 +1887,30 @@ pub fn query_registry(deps: Deps, pool_type: PoolType) -> StdResult, limit: Option) -> StdResult> { + let config = CONFIG.load(deps.storage)?; + + let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT); + let start = start_after.unwrap_or_default().u128() + 1u128; + + let mut end = start + Uint128::from(limit).u128(); + if end > config.next_pool_id.u128() { + end = config.next_pool_id.u128(); + } + + let mut response: Vec= vec![]; + for pool_id in start..end { + response.push(ACTIVE_POOLS.load(deps.storage, Uint128::from(pool_id).to_string().as_bytes())?); + } + + Ok(response) +} + /// ## Description - Returns the current stored state of the Pool in custom [`PoolInfoResponse`] structure /// /// ## Params @@ -1928,10 +1949,46 @@ pub fn query_pool_by_lp_token_addr(deps: Deps, lp_token_addr: String) -> StdResu /// ## Params /// * **_msg** is the object of type [`MigrateMsg`]. #[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { +pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result { let contract_version = get_contract_version(deps.storage)?; - set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + match msg { + MigrateMsg::V1_1 { updated_pool_type_configs } => { + // validate contract name + if contract_version.contract != CONTRACT_NAME { + return Err(ContractError::InvalidContractNameForMigration { + expected: CONTRACT_NAME.to_string(), + actual: contract_version.contract, + }); + } + + // validate that current version is v1.0 + if contract_version.version != CONTRACT_VERSION_V1 { + return Err(ContractError::InvalidContractVersionForUpgrade { + upgrade_version: CONTRACT_VERSION.to_string(), + expected: CONTRACT_VERSION_V1.to_string(), + actual: contract_version.version, + }); + } + // update pool type configs to new values. This makes sure we instantiate new pools with the new configs particularly the + // Code ID for each pool type which has been updated to a new value with the new version of the pool contracts + for pool_type_config in updated_pool_type_configs { + // Check if code id is valid + if pool_type_config.code_id == 0 { + return Err(ContractError::InvalidCodeId {}); + } + // validate fee bps limits + if !pool_type_config.default_fee_info.valid_fee_info() { + return Err(ContractError::InvalidFeeInfo {}); + } + REGISTRY.save(deps.storage, pool_type_config.pool_type.to_string(), &pool_type_config)?; + } + + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + } + } + Ok(Response::new() .add_attribute("previous_contract_name", &contract_version.contract) .add_attribute("previous_contract_version", &contract_version.version) diff --git a/contracts/vault/src/error.rs b/contracts/vault/src/error.rs index fc18b36c..38961907 100644 --- a/contracts/vault/src/error.rs +++ b/contracts/vault/src/error.rs @@ -170,6 +170,16 @@ pub enum ContractError { #[error("Imbalanced exit is paused. Normal exit for a pool is always allowed")] ImbalancedExitPaused, + + #[error("Invalid contract version for upgrade {upgrade_version}. Expected: {expected}, Actual: {actual}")] + InvalidContractVersionForUpgrade { + upgrade_version: String, + expected: String, + actual: String, + }, + + #[error("Invalid contract name for migration. Expected: {expected}, Actual: {actual}")] + InvalidContractNameForMigration { expected: String, actual: String }, } impl From for ContractError { diff --git a/contracts/vault/tests/initialization_and_config.rs b/contracts/vault/tests/initialization_and_config.rs index d8acfe37..e2f42668 100644 --- a/contracts/vault/tests/initialization_and_config.rs +++ b/contracts/vault/tests/initialization_and_config.rs @@ -1,6 +1,6 @@ pub mod utils; -use cosmwasm_std::{attr, coin, Addr, Coin, Uint128, to_json_binary, Decimal}; +use cosmwasm_std::{attr, coin, Addr, Coin, Uint128, to_json_binary}; use cw20::MinterResponse; use cw_multi_test::Executor; use dexter::asset::AssetInfo; @@ -10,7 +10,7 @@ use dexter::vault::{ ConfigResponse, ExecuteMsg, FeeInfo, InstantiateMsg, PauseInfo, PoolTypeConfigResponse, PoolInfoResponse, PoolType, PoolTypeConfig, QueryMsg, PoolCreationFee, AutoStakeImpl, PauseInfoUpdateType, }; -use stable_pool::state::StablePoolParams; +use dexter_stable_pool::state::StablePoolParams; use crate::utils::{initialize_3_tokens, initialize_stable_5_pool_2_asset, instantiate_contract, mock_app, store_stable5_pool_code, store_token_code, store_vault_code, store_weighted_pool_code}; @@ -531,7 +531,6 @@ fn test_pool_config_update() { supports_scaling_factors_update: false, scaling_factor_manager: None, scaling_factors: vec![], - max_allowed_spread: Decimal::from_ratio(50u128, 100u128), }).unwrap()), fee_info: None, }; diff --git a/contracts/vault/tests/pool_creation.rs b/contracts/vault/tests/pool_creation.rs index 2e8bb999..8f335378 100644 --- a/contracts/vault/tests/pool_creation.rs +++ b/contracts/vault/tests/pool_creation.rs @@ -2,14 +2,14 @@ pub mod utils; use std::vec; -use cosmwasm_std::{attr, coin, Addr, Coin, Uint128, to_json_binary, Decimal}; +use cosmwasm_std::{attr, coin, Addr, Coin, Uint128, to_json_binary}; use cw20::MinterResponse; use cw_multi_test::Executor; use dexter::asset::{Asset, AssetInfo}; use dexter::lp_token::InstantiateMsg as TokenInstantiateMsg; use dexter::vault::{AllowPoolInstantiation, ExecuteMsg, PoolInfo, PoolType, QueryMsg, PoolCreationFee}; -use stable_pool::state::StablePoolParams; +use dexter_stable_pool::state::StablePoolParams; use crate::utils::{dummy_pool_creation_msg, instantiate_contract, mock_app, store_token_code}; @@ -102,7 +102,6 @@ fn test_create_pool_instance() { scaling_factor_manager: None, supports_scaling_factors_update: false, scaling_factors: vec![], - max_allowed_spread: Decimal::from_ratio(50u64, 100u64) }).unwrap()), fee_info: None, }; @@ -481,7 +480,6 @@ fn test_pool_creation_fee() { scaling_factor_manager: None, supports_scaling_factors_update: false, scaling_factors: vec![], - max_allowed_spread: Decimal::from_ratio(50u128, 100u128) }).unwrap()), fee_info: None, }; diff --git a/contracts/vault/tests/pool_join.rs b/contracts/vault/tests/pool_join.rs index 517dec26..a75808de 100644 --- a/contracts/vault/tests/pool_join.rs +++ b/contracts/vault/tests/pool_join.rs @@ -8,7 +8,8 @@ use dexter::asset::{Asset, AssetInfo}; use dexter::pool::{ AfterJoinResponse, ConfigResponse as Pool_ConfigResponse, QueryMsg as PoolQueryMsg, }; -use dexter::vault::{ExecuteMsg, PauseInfo, PoolType}; +use dexter::vault::{ExecuteMsg, PauseInfo, PoolInfoResponse, PoolType, QueryMsg}; +use dexter::vault::PoolType::{StableSwap, Weighted}; use crate::utils::{ increase_token_allowance, initialize_3_tokens, @@ -93,6 +94,19 @@ fn test_join_pool() { Uint128::new(10000000_000000u128), ); + // check pools query before creating pools + let pool_infos: Vec = app + .wrap() + .query_wasm_smart( + &vault_instance, + &QueryMsg::Pools { + start_after: None, + limit: None + }, + ) + .unwrap(); + assert_eq!(pool_infos.len(), 0); + // Create STABLE-5-POOL pool let (stable5_pool_addr, stable5_lp_token_addr, stable5_pool_id) = initialize_stable_5_pool( &mut app, @@ -116,6 +130,48 @@ fn test_join_pool() { denom1.clone(), ); + // check pools query after creating pools + let pool_infos: Vec = app + .wrap() + .query_wasm_smart( + &vault_instance, + &QueryMsg::Pools { + start_after: None, + limit: None + }, + ) + .unwrap(); + assert_eq!(pool_infos.len(), 2); + assert_eq!(pool_infos[0].pool_type, StableSwap {}); + assert_eq!(pool_infos[1].pool_type, Weighted {}); + + // check pools query with custom start & limit + let pool_infos: Vec = app + .wrap() + .query_wasm_smart( + &vault_instance, + &QueryMsg::Pools { + start_after: Some(Uint128::one()), + limit: Some(1) + }, + ) + .unwrap(); + assert_eq!(pool_infos.len(), 1); + assert_eq!(pool_infos[0].pool_type, Weighted {}); + + // check pools query for non-existent pools + let pool_infos: Vec = app + .wrap() + .query_wasm_smart( + &vault_instance, + &QueryMsg::Pools { + start_after: Some(Uint128::from(2u128)), + limit: None + }, + ) + .unwrap(); + assert_eq!(pool_infos.len(), 0); + // -------x---------- STABLE-5-POOL -::- PROVIDE LIQUIDITY -------x---------- // -------x---------- -------x---------- -------x---------- -------x---------- diff --git a/contracts/vault/tests/pool_param_update.rs b/contracts/vault/tests/pool_param_update.rs index 9fc625a6..8ca9abf8 100644 --- a/contracts/vault/tests/pool_param_update.rs +++ b/contracts/vault/tests/pool_param_update.rs @@ -3,7 +3,7 @@ pub mod utils; use std::vec; -use cosmwasm_std::{attr, coin, Addr, Coin, Uint128, to_json_binary, Decimal, from_json}; +use cosmwasm_std::{attr, coin, Addr, Coin, Uint128, to_json_binary, from_json}; use cw20::MinterResponse; use cw_multi_test::Executor; use dexter::asset::{Asset, AssetInfo}; @@ -11,7 +11,7 @@ use dexter::lp_token::InstantiateMsg as TokenInstantiateMsg; use dexter::pool::ConfigResponse; use dexter::vault::{ExecuteMsg, PoolInfo, PoolType, QueryMsg}; -use stable_pool::state::{StablePoolParams, StablePoolUpdateParams}; +use dexter_stable_pool::state::{StablePoolParams, StablePoolUpdateParams}; use crate::utils::{instantiate_contract, mock_app, store_token_code}; @@ -101,10 +101,9 @@ fn update_pool_params() { native_asset_precisions: vec![], init_params: Some(to_json_binary(&StablePoolParams { amp: 100u64, - scaling_factor_manager: None, - supports_scaling_factors_update: false, + scaling_factor_manager: Some(Addr::unchecked("manager1".to_string())), + supports_scaling_factors_update: true, scaling_factors: vec![], - max_allowed_spread: Decimal::from_ratio(50u64, 100u64) }).unwrap()), fee_info: None, }; @@ -159,11 +158,11 @@ fn update_pool_params() { let pool_addr = Addr::unchecked("contract4".to_string()); - // Let's update the pool params: max_allowed_spread + // Let's update the pool params: scaling factor manager let msg = ExecuteMsg::UpdatePoolParams { pool_id: Uint128::from(1u128), - params: to_json_binary(&StablePoolUpdateParams::UpdateMaxAllowedSpread { - max_allowed_spread: Decimal::from_ratio(10u64, 100u64) + params: to_json_binary(&StablePoolUpdateParams::UpdateScalingFactorManager { + manager: Addr::unchecked("manager2".to_string()), }).unwrap(), }; @@ -187,13 +186,13 @@ fn update_pool_params() { // unmarshal the pool params let pool_params: StablePoolParams = from_json(&pool_res.additional_params.unwrap()).unwrap(); - assert_eq!(Decimal::from_ratio(10u64, 100u64), pool_params.max_allowed_spread); + assert_eq!(Addr::unchecked("manager2".to_string()), pool_params.scaling_factor_manager.unwrap()); // Try to update the pool params with a non owner let msg = ExecuteMsg::UpdatePoolParams { pool_id: Uint128::from(1u128), - params: to_json_binary(&StablePoolUpdateParams::UpdateMaxAllowedSpread { - max_allowed_spread: Decimal::from_ratio(50u64, 100u64) + params: to_json_binary(&StablePoolUpdateParams::UpdateScalingFactorManager { + manager: Addr::unchecked("manager3".to_string()) }).unwrap(), }; diff --git a/contracts/vault/tests/pool_swap.rs b/contracts/vault/tests/pool_swap.rs index 5eb0644a..4adc3b16 100644 --- a/contracts/vault/tests/pool_swap.rs +++ b/contracts/vault/tests/pool_swap.rs @@ -1,6 +1,6 @@ pub mod utils; -use cosmwasm_std::{Addr, Coin, Decimal, Timestamp, Uint128}; +use cosmwasm_std::{Addr, Coin, Timestamp, Uint128}; use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg}; use cw_multi_test::Executor; use dexter::asset::{Asset, AssetInfo}; @@ -281,9 +281,7 @@ fn test_swap() { asset_out: AssetInfo::Token { contract_addr: token_instance2.clone(), }, - amount: Uint128::from(252_000000u128), - max_spread: Some(Decimal::percent(50)), - belief_price: None, + amount: Uint128::from(252_000000u128) }, recipient: None, min_receive: None, @@ -470,9 +468,7 @@ fn test_swap() { asset_out: AssetInfo::Token { contract_addr: token_instance2.clone(), }, - amount: Uint128::from(252_000000u128), - max_spread: Some(Decimal::percent(50)), - belief_price: None, + amount: Uint128::from(252_000000u128) }, recipient: None, min_receive: None, @@ -586,9 +582,7 @@ fn test_swap() { asset_out: AssetInfo::Token { contract_addr: token_instance2.clone(), }, - amount: Uint128::from(252_000000u128), - max_spread: Some(Decimal::percent(50)), - belief_price: None, + amount: Uint128::from(252_000000u128) }, recipient: None, min_receive: None, @@ -629,9 +623,7 @@ fn test_swap() { asset_out: AssetInfo::Token { contract_addr: token_instance2.clone(), }, - amount: Uint128::from(252_000000u128), - max_spread: Some(Decimal::percent(50)), - belief_price: None, + amount: Uint128::from(252_000000u128) }, recipient: None, min_receive: None, diff --git a/contracts/vault/tests/utils/mod.rs b/contracts/vault/tests/utils/mod.rs index bf10584c..0292afac 100644 --- a/contracts/vault/tests/utils/mod.rs +++ b/contracts/vault/tests/utils/mod.rs @@ -9,7 +9,7 @@ use dexter::vault::{ ConfigResponse, ExecuteMsg, FeeInfo, InstantiateMsg, PoolInfoResponse, PoolType, PoolTypeConfig, QueryMsg, PoolCreationFee, PauseInfo, NativeAssetPrecisionInfo, }; -use stable_pool::state::StablePoolParams; +use dexter_stable_pool::state::StablePoolParams; const EPOCH_START: u64 = 1_000_000; @@ -39,27 +39,27 @@ pub fn store_vault_code(app: &mut App) -> u64 { pub fn store_token_code(app: &mut App) -> u64 { let token_contract = Box::new(ContractWrapper::new_with_empty( - lp_token::contract::execute, - lp_token::contract::instantiate, - lp_token::contract::query, + dexter_lp_token::contract::execute, + dexter_lp_token::contract::instantiate, + dexter_lp_token::contract::query, )); app.store_code(token_contract) } pub fn store_stable5_pool_code(app: &mut App) -> u64 { let pool_contract = Box::new(ContractWrapper::new_with_empty( - stable_pool::contract::execute, - stable_pool::contract::instantiate, - stable_pool::contract::query, + dexter_stable_pool::contract::execute, + dexter_stable_pool::contract::instantiate, + dexter_stable_pool::contract::query, )); app.store_code(pool_contract) } pub fn store_weighted_pool_code(app: &mut App) -> u64 { let pool_contract = Box::new(ContractWrapper::new_with_empty( - weighted_pool::contract::execute, - weighted_pool::contract::instantiate, - weighted_pool::contract::query, + dexter_weighted_pool::contract::execute, + dexter_weighted_pool::contract::instantiate, + dexter_weighted_pool::contract::query, )); app.store_code(pool_contract) } @@ -272,7 +272,6 @@ pub fn dummy_pool_creation_msg(asset_infos: &[AssetInfo]) -> ExecuteMsg { scaling_factor_manager: None, scaling_factors: vec![], supports_scaling_factors_update: false, - max_allowed_spread: Decimal::from_ratio(50u64, 100u64) }).unwrap()), fee_info: Some(FeeInfo { total_fee_bps: 1_000u16, @@ -317,7 +316,6 @@ pub fn initialize_stable_5_pool_2_asset( scaling_factor_manager: None, scaling_factors: vec![], supports_scaling_factors_update: false, - max_allowed_spread: Decimal::from_ratio(50u64, 100u64) }).unwrap()), fee_info: None, }; @@ -392,7 +390,6 @@ pub fn initialize_stable_5_pool( scaling_factor_manager: None, scaling_factors: vec![], supports_scaling_factors_update: false, - max_allowed_spread: Decimal::from_ratio(50u64, 100u64) }).unwrap()), fee_info: None, }; @@ -494,7 +491,7 @@ pub fn initialize_weighted_pool( precision: 6u8, },], init_params: Some( - to_json_binary(&weighted_pool::state::WeightedParams { + to_json_binary(&dexter_weighted_pool::state::WeightedParams { weights: asset_infos_with_weights, exit_fee: Some(Decimal::from_ratio(1u128, 100u128)), }) diff --git a/packages/dexter/Cargo.toml b/packages/dexter/Cargo.toml index e806cd56..55b11b8a 100644 --- a/packages/dexter/Cargo.toml +++ b/packages/dexter/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "dexter" -version = "1.3.0" -authors = ["PersistenceLabs"] +version = "1.4.0" +authors = ["Persistence Labs"] edition = "2021" description = "Dex optimized for liquid staked assets" repository = "https://github.com/dexter-zone/dexter_core" +license = "MIT OR Apache-2.0" [features] @@ -15,7 +16,7 @@ backtraces = ["cosmwasm-std/backtraces"] [dependencies] cw20 = "1.0.1" cw20-base = { version = "1.0.1", features = ["library"] } -cosmwasm-std = "1.5.3" +cosmwasm-std = "1.5.4" schemars = "0.8.11" serde = { version = "1.0.152", default-features = false, features = ["derive"] } cw-storage-plus = "1.0.1" diff --git a/packages/dexter/src/helper.rs b/packages/dexter/src/helper.rs index 65ca9a81..4a206209 100644 --- a/packages/dexter/src/helper.rs +++ b/packages/dexter/src/helper.rs @@ -10,6 +10,13 @@ use cw20_base::msg::ExecuteMsg as CW20ExecuteMsg; use cw_storage_plus::Item; use itertools::Itertools; +// ----------------x----------------x----------------x----------------x----------------x---------------- +// ----------------x Pagination settings x---------------- +// ----------------x----------------x----------------x----------------x----------------x---------------- + +pub const MAX_LIMIT: u32 = 30; +pub const DEFAULT_LIMIT: u32 = 10; + // ----------------x----------------x----------------x----------------x----------------x---------------- // ----------------x Event related helpers x---------------- // ----------------x----------------x----------------x----------------x----------------x---------------- diff --git a/packages/dexter/src/pool.rs b/packages/dexter/src/pool.rs index 44f75d0f..e8c3fb21 100644 --- a/packages/dexter/src/pool.rs +++ b/packages/dexter/src/pool.rs @@ -4,7 +4,7 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use crate::asset::{Asset, AssetExchangeRate, AssetInfo}; use crate::vault::{PoolType, SwapType, NativeAssetPrecisionInfo}; -use cosmwasm_std::{Addr, Binary, Decimal, Decimal256, DepsMut, Env, Event, MessageInfo, Response, StdError, StdResult, Uint128}; +use cosmwasm_std::{Addr, Binary, Decimal256, DepsMut, Env, Event, MessageInfo, Response, StdError, StdResult, Uint128}; use std::fmt::{Display, Formatter, Result}; use cw_storage_plus::{Item, Map}; use crate::helper::EventExt; @@ -168,11 +168,7 @@ pub enum QueryMsg { swap_type: SwapType, offer_asset: AssetInfo, ask_asset: AssetInfo, - amount: Uint128, - // DEPRECATED: not used in any pool type. use min received for slippage protection - max_spread: Option, - // DEPRECATED: not used in any pool type. use min received for slippage protection - belief_price: Option, + amount: Uint128 }, /// ## Description - Returns the spot price of the asset in a [`SpotPrice`] object. #[returns(SpotPrice)] @@ -206,7 +202,13 @@ pub enum ExitType { /// This struct describes a migration message. /// We currently take no arguments for migrations. #[cw_serde] -pub struct MigrateMsg {} +pub enum MigrateMsg { + // migrates to v1.1 of the contract + // This introduces following changes to the contracts: + // Weighted Pool: Spot Price API, updates to Cumulative Price functions + // Stable Pool: Spot Price API, updates to Cumulative Price functions, migration to Integer based invariant math, removal of max spread checks + V1_1 {} +} // ----------------x----------------x----------------x----------------x----------------x---------------- // ----------------x----------------x Response Types x----------------x----------------x------ diff --git a/packages/dexter/src/router.rs b/packages/dexter/src/router.rs index 8fe6f0a1..389293ce 100644 --- a/packages/dexter/src/router.rs +++ b/packages/dexter/src/router.rs @@ -2,7 +2,7 @@ use crate::asset::{Asset, AssetInfo}; use crate::pool::ResponseType; use crate::vault::SwapType; use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{to_json_binary, Addr, CosmosMsg, Decimal, StdResult, Uint128, WasmMsg}; +use cosmwasm_std::{to_json_binary, Addr, CosmosMsg, StdResult, Uint128, WasmMsg}; pub const MAX_SWAP_OPERATIONS: usize = 50; @@ -27,8 +27,6 @@ pub struct HopSwapRequest { pub asset_in: AssetInfo, /// The ask asset pub asset_out: AssetInfo, - pub max_spread: Option, - pub belief_price: Option, } /// This structure describes the execute messages available in the contract. @@ -108,7 +106,9 @@ pub struct SimulatedTrade { /// This structure describes a migration message. /// We currently take no arguments for migrations. #[cw_serde] -pub struct MigrateMsg {} +pub enum MigrateMsg { + V1_1 {} +} pub fn return_swap_sim_failure( suc_swaps: Vec, diff --git a/packages/dexter/src/vault.rs b/packages/dexter/src/vault.rs index f76d10f3..fa880554 100644 --- a/packages/dexter/src/vault.rs +++ b/packages/dexter/src/vault.rs @@ -244,8 +244,6 @@ pub struct SingleSwapRequest { pub asset_out: AssetInfo, pub swap_type: SwapType, pub amount: Uint128, - pub max_spread: Option, - pub belief_price: Option, } // ----------------x----------------x----------------x----------------x----------------x---------------- @@ -436,6 +434,9 @@ pub enum QueryMsg { /// Return PoolConfig #[returns(PoolTypeConfigResponse)] QueryRegistry { pool_type: PoolType }, + /// Returns the info of all the pools matching the given pagination params + #[returns(Vec)] + Pools { start_after: Option, limit: Option }, /// Returns the current stored state of the Pool in custom [`PoolInfoResponse`] struct #[returns(PoolInfoResponse)] GetPoolById { pool_id: Uint128 }, @@ -449,7 +450,12 @@ pub enum QueryMsg { /// ## Description - This struct describes a migration message. #[cw_serde] -pub struct MigrateMsg {} +pub enum MigrateMsg { + + V1_1 { + updated_pool_type_configs: Vec, + } +} // ----------------x----------------x----------------x----------------x----------------x---------------- // ----------------x----------------x Response Types x----------------x----------------x--------