diff --git a/Cargo.lock b/Cargo.lock index c0a88a9..68a25ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,16 +284,6 @@ dependencies = [ "uint", ] -[[package]] -name = "cosmwasm-storage" -version = "1.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9e21c4f58986fd20184d7685e1c43c5732c9309337b09307d5952fd34dba6e" -dependencies = [ - "cosmwasm-std", - "serde", -] - [[package]] name = "cpufeatures" version = "0.2.8" @@ -344,20 +334,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "cw-controllers" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64bfeaf55f8dba5646cc3daddce17cd23a60f8e0c3fbacbe6735d287d7a6e33a" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus 0.11.1", - "cw-utils 0.11.1", - "schemars", - "serde", - "thiserror", -] - [[package]] name = "cw-controllers" version = "1.0.1" @@ -366,8 +342,8 @@ checksum = "91440ce8ec4f0642798bc8c8cb6b9b53c1926c6dadaf0eed267a5145cd529071" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", + "cw-storage-plus", + "cw-utils", "schemars", "serde", "thiserror", @@ -381,8 +357,8 @@ checksum = "127c7bb95853b8e828bdab97065c81cb5ddc20f7339180b61b2300565aaa99d1" dependencies = [ "anyhow", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", + "cw-storage-plus", + "cw-utils", "derivative", "itertools", "k256", @@ -399,8 +375,8 @@ source = "git+https://github.com/wynddao/wynddex?tag=v2.1.0#a578f8b645433e108a10 dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw2 1.0.1", + "cw-storage-plus", + "cw2", "thiserror", ] @@ -410,8 +386,8 @@ version = "2.2.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw2 1.0.1", + "cw-storage-plus", + "cw2", "thiserror", ] @@ -422,36 +398,14 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "thiserror", ] -[[package]] -name = "cw-storage-plus" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b8b840947313c1a1cccf056836cd79a60b4526bdcd6582995be37dc97be4ae" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-storage-plus" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7ee1963302b0ac2a9d42fe0faec826209c17452bfd36fbfd9d002a88929261" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - [[package]] name = "cw-storage-plus" version = "1.1.0" @@ -463,18 +417,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cw-utils" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef842a1792e4285beff7b3b518705f760fa4111dc1e296e53f3e92d1ef7f6220" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - [[package]] name = "cw-utils" version = "1.0.1" @@ -483,49 +425,13 @@ checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2 1.0.1", + "cw2", "schemars", "semver", "serde", "thiserror", ] -[[package]] -name = "cw0" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae676b6cced78a3d38ad4b01ab4ed66fc78ac191c3c0d6bfd5372cb2efd473b" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7002e6f9c1a1ef3915dca704a6306ba00c39495efd928551d6077c734f9a3d8" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus 0.10.3", - "schemars", - "serde", -] - -[[package]] -name = "cw2" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d81d7c359d6c1fba3aa83dad7ec6f999e512571380ae62f81257c3db569743" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus 0.11.1", - "schemars", - "serde", -] - [[package]] name = "cw2" version = "1.0.1" @@ -534,31 +440,7 @@ checksum = "8fb70cee2cf0b4a8ff7253e6bc6647107905e8eb37208f87d54f67810faa62f8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "schemars", - "serde", -] - -[[package]] -name = "cw20" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56fc9d54b9b365801beb101a5c0375dceaa5a285bfc14438a7b6007f9d362142" -dependencies = [ - "cosmwasm-std", - "cw0", - "schemars", - "serde", -] - -[[package]] -name = "cw20" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9671d7edef5608acaf5b2f1e473ee3f501eced2cd4f7392e2106c8cf02ba0720" -dependencies = [ - "cosmwasm-std", - "cw-utils 0.11.1", + "cw-storage-plus", "schemars", "serde", ] @@ -571,43 +453,11 @@ checksum = "91666da6c7b40c8dd5ff94df655a28114efc10c79b70b4d06f13c31e37d60609" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils 1.0.1", + "cw-utils", "schemars", "serde", ] -[[package]] -name = "cw20-base" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5df0a946a4a58dd4fdb158ff1595c55774beeef76d09f108b547bce572dcf" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus 0.10.3", - "cw0", - "cw2 0.10.3", - "cw20 0.10.3", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw20-base" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f6fc8c4cd451b418fa4f1ac2ea70595811fa9d8b4033617fe47953d7a93ceb" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus 0.11.1", - "cw-utils 0.11.1", - "cw2 0.11.1", - "cw20 0.11.1", - "schemars", - "serde", - "thiserror", -] - [[package]] name = "cw20-base" version = "1.0.1" @@ -616,10 +466,10 @@ checksum = "afcd279230b08ed8afd8be5828221622bd5b9ce25d0b01d58bad626c6ce0169c" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", "schemars", "semver", "serde", @@ -797,10 +647,10 @@ dependencies = [ "cosmwasm-std", "cw-multi-test", "cw-placeholder 2.2.0", - "cw-storage-plus 1.1.0", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw2", + "cw20", + "cw20-base", "palomadex", "palomadex-factory", "palomadex-pair", @@ -925,32 +775,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" -[[package]] -name = "junoswap-staking" -version = "2.2.0" -dependencies = [ - "anyhow", - "cosmwasm-schema", - "cosmwasm-std", - "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 0.11.1", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 0.10.3", - "cw20 1.0.1", - "cw20-base 0.10.3", - "cw20-base 1.0.1", - "palomadex", - "palomadex-factory", - "palomadex-pair", - "palomadex-stake", - "serde", - "stake-cw20", - "thiserror", - "wasmswap", -] - [[package]] name = "k256" version = "0.11.6" @@ -1001,10 +825,10 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw2", + "cw20", + "cw20-base", "palomadex", "palomadex-factory", "palomadex-pair", @@ -1027,11 +851,11 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "palomadex", "palomadex-factory", "palomadex-multi-hop", @@ -1069,10 +893,10 @@ version = "2.2.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw20", + "cw20-base", "itertools", "thiserror", "uint", @@ -1087,11 +911,11 @@ dependencies = [ "cosmwasm-std", "cw-multi-test", "cw-placeholder 2.2.0", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "itertools", "palomadex", "palomadex-pair", @@ -1108,11 +932,11 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "palomadex", "palomadex-factory", "palomadex-pair", @@ -1127,11 +951,11 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "palomadex", "palomadex-factory", "palomadex-stake", @@ -1146,11 +970,11 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "derivative", "itertools", "palomadex", @@ -1167,13 +991,13 @@ dependencies = [ "anyhow", "cosmwasm-schema", "cosmwasm-std", - "cw-controllers 1.0.1", + "cw-controllers", "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "lp-converter", "palomadex", "serde", @@ -1347,32 +1171,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "raw-migration" -version = "2.2.0" -dependencies = [ - "anyhow", - "cosmwasm-schema", - "cosmwasm-std", - "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 0.11.1", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 0.10.3", - "cw20 1.0.1", - "cw20-base 0.10.3", - "cw20-base 1.0.1", - "palomadex", - "palomadex-factory", - "palomadex-pair", - "palomadex-stake", - "serde", - "stake-cw20", - "thiserror", - "wasmswap", -] - [[package]] name = "redox_syscall" version = "0.3.5" @@ -1595,24 +1393,6 @@ dependencies = [ "quickcheck", ] -[[package]] -name = "stake-cw20" -version = "0.2.6" -source = "git+https://github.com/DA0-DA0/dao-contracts?tag=v0.3.0#5d46fc6f4a9a2fed3a85e700215d0421e1c196be" -dependencies = [ - "cosmwasm-std", - "cosmwasm-storage", - "cw-controllers 0.11.1", - "cw-storage-plus 0.11.1", - "cw-utils 0.11.1", - "cw2 0.11.1", - "cw20 0.11.1", - "cw20-base 0.11.1", - "schemars", - "serde", - "thiserror", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -1697,8 +1477,8 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-multi-test", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw20", + "cw20-base", "palomadex", "palomadex-factory", "palomadex-multi-hop", @@ -1783,23 +1563,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasmswap" -version = "1.1.2-beta" -source = "git+https://github.com/Wasmswap/wasmswap-contracts?tag=v1.1.2-beta#621197915656ace61c5cb31f3305a0abf058c62d" -dependencies = [ - "cosmwasm-std", - "cosmwasm-storage", - "cw-storage-plus 0.10.3", - "cw0", - "cw2 0.11.1", - "cw20 0.10.3", - "cw20-base 0.10.3", - "schemars", - "serde", - "thiserror", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -1873,12 +1636,12 @@ source = "git+https://github.com/wynddao/wynd-lsd.git#cbb30b5c521f80848209a36f57 dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-controllers 1.0.1", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-controllers", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "cw20-base", "semver", "thiserror", ] @@ -1912,10 +1675,10 @@ source = "git+https://github.com/wynddao/wynddex?tag=v2.0.2#592cee00712aa0c7840a dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw20", + "cw20-base", "itertools", "thiserror", "uint", @@ -1928,10 +1691,10 @@ source = "git+https://github.com/wynddao/wynddex?tag=v2.1.0#a578f8b645433e108a10 dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw20 1.0.1", - "cw20-base 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw20", + "cw20-base", "itertools", "thiserror", "uint", @@ -1945,9 +1708,9 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-placeholder 2.1.0", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", + "cw-storage-plus", + "cw-utils", + "cw2", "itertools", "thiserror", "wyndex 2.1.0", @@ -1961,11 +1724,11 @@ source = "git+https://github.com/wynddao/wynddex?tag=v2.0.2#592cee00712aa0c7840a dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-controllers 1.0.1", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", + "cw-controllers", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", "serde", "thiserror", "wynd-utils 1.6.0 (git+https://github.com/cosmorama/wynddao.git?tag=v1.6.0)", @@ -1979,11 +1742,11 @@ source = "git+https://github.com/wynddao/wynddex?tag=v2.1.0#a578f8b645433e108a10 dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-controllers 1.0.1", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.0.1", - "cw20 1.0.1", + "cw-controllers", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", "serde", "thiserror", "wynd-utils 1.6.0 (git+https://github.com/cosmorama/wynddao.git?tag=v1.6.0)", diff --git a/contracts/cw-placeholder/src/contract.rs b/contracts/cw-placeholder/src/contract.rs index e8dbaff..8a41ac2 100644 --- a/contracts/cw-placeholder/src/contract.rs +++ b/contracts/cw-placeholder/src/contract.rs @@ -7,7 +7,7 @@ use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( - deps: DepsMut, + _deps: DepsMut, _env: Env, _info: MessageInfo, _msg: InstantiateMsg, diff --git a/contracts/factory/src/contract.rs b/contracts/factory/src/contract.rs index 88d49fb..690f916 100644 --- a/contracts/factory/src/contract.rs +++ b/contracts/factory/src/contract.rs @@ -9,9 +9,9 @@ use palomadex::common::{ claim_ownership, drop_ownership_proposal, propose_new_owner, validate_addresses, }; use palomadex::factory::{ - ConfigResponse, DistributionFlow, ExecuteMsg, FeeInfoResponse, InstantiateMsg, MigrateMsg, - PairConfig, PairType, PairsResponse, PartialDefaultStakeConfig, PartialStakeConfig, QueryMsg, - ReceiveMsg, ROUTE, + ConfigResponse, DistributionFlow, ExecuteMsg, FeeInfoResponse, InstantiateMsg, PairConfig, + PairType, PairsResponse, PartialDefaultStakeConfig, PartialStakeConfig, QueryMsg, ReceiveMsg, + ROUTE, }; use palomadex::fee_config::FeeConfig; use palomadex::stake::UnbondingPeriod; @@ -693,8 +693,8 @@ pub fn deregister_pool_and_staking( Ok(pairs .unwrap_or_default() .iter() + .filter(|&pair| pair != pair_addr) .cloned() - .filter(|pair| pair != pair_addr) .collect::>()) }, )?; diff --git a/contracts/factory/tests/integration.rs b/contracts/factory/tests/integration.rs index 4560ee6..14b83fe 100644 --- a/contracts/factory/tests/integration.rs +++ b/contracts/factory/tests/integration.rs @@ -3,8 +3,8 @@ mod factory_helper; use cosmwasm_std::{attr, from_slice, Addr, Decimal, StdError, Uint128}; use palomadex::asset::AssetInfo; use palomadex::factory::{ - ConfigResponse, DefaultStakeConfig, ExecuteMsg, FeeInfoResponse, InstantiateMsg, MigrateMsg, - PairConfig, PairType, PartialDefaultStakeConfig, QueryMsg, + ConfigResponse, DefaultStakeConfig, ExecuteMsg, FeeInfoResponse, InstantiateMsg, PairConfig, + PairType, PartialDefaultStakeConfig, QueryMsg, }; use palomadex::fee_config::FeeConfig; use palomadex::pair::PairInfo; @@ -12,22 +12,11 @@ use palomadex_factory::{error::ContractError, state::Config}; use crate::factory_helper::{instantiate_token, FactoryHelper}; use cw_multi_test::{App, ContractWrapper, Executor}; -use cw_placeholder::msg::InstantiateMsg as PlaceholderContractInstantiateMsg; use palomadex::pair::ExecuteMsg as PairExecuteMsg; fn mock_app() -> App { App::default() } -fn store_placeholder_code(app: &mut App) -> u64 { - let placeholder_contract = Box::new(ContractWrapper::new_with_empty( - cw_placeholder::contract::execute, - cw_placeholder::contract::instantiate, - cw_placeholder::contract::query, - )); - - app.store_code(placeholder_contract) -} - fn store_factory_code(app: &mut App) -> u64 { let factory_contract = Box::new( ContractWrapper::new_with_empty( @@ -868,79 +857,3 @@ fn check_update_owner() { assert_eq!(res.owner, new_owner) } - -#[test] -fn can_migrate_the_placeholder_to_a_factory_properly() { - let mut app = mock_app(); - - let owner = Addr::unchecked("owner"); - - let place_holder_id = store_placeholder_code(&mut app); - let factory_id = store_factory_code(&mut app); - - let pair_configs = vec![PairConfig { - code_id: 321, - pair_type: PairType::Xyk {}, - fee_config: FeeConfig { - total_fee_bps: 100, - protocol_fee_bps: 10, - }, - is_disabled: false, - }]; - // Instantiate an instance of the placeholder contract which we will migrate - let placeholder = app - .instantiate_contract( - place_holder_id, - owner.clone(), - &PlaceholderContractInstantiateMsg {}, - &[], - "placeholder", - Some(owner.clone().into_string()), - ) - .unwrap(); - - let factory_msg = InstantiateMsg { - pair_configs: pair_configs.clone(), - token_code_id: 123, - fee_address: None, - owner: owner.to_string(), - max_referral_commission: Decimal::one(), - default_stake_config: default_stake_config(), - trading_starts: None, - }; - // Migrate the contract - app.migrate_contract( - owner.clone(), - placeholder.clone(), - &MigrateMsg::Init(factory_msg.clone()), - factory_id, - ) - .unwrap(); - - // Now instantiate a normal factory directly - let factory_instance = app - .instantiate_contract( - factory_id, - Addr::unchecked(owner.clone()), - &factory_msg, - &[], - "factory", - None, - ) - .unwrap(); - // To verify we will check configs, confirming its the same ConfigResponse and the same values - let msg = QueryMsg::Config {}; - // Query the 'placeholder' which is now a Factory - let migrated_factory_config: ConfigResponse = - app.wrap().query_wasm_smart(&placeholder, &msg).unwrap(); - let direct_factory_config: ConfigResponse = - app.wrap().query_wasm_smart(factory_instance, &msg).unwrap(); - - assert_eq!(123, migrated_factory_config.token_code_id); - assert_eq!(pair_configs, migrated_factory_config.pair_configs); - assert_eq!(owner, migrated_factory_config.owner); - - assert_eq!(123, direct_factory_config.token_code_id); - assert_eq!(pair_configs, direct_factory_config.pair_configs); - assert_eq!(owner, direct_factory_config.owner); -} diff --git a/contracts/gauge-adapter/src/contract.rs b/contracts/gauge-adapter/src/contract.rs index 90fd08f..5b751f3 100644 --- a/contracts/gauge-adapter/src/contract.rs +++ b/contracts/gauge-adapter/src/contract.rs @@ -11,7 +11,7 @@ use palomadex::stake::{FundingInfo, ReceiveMsg as StakeReceiveDelegationMsg}; use palomadex_stake::msg::ExecuteMsg as StakeExecuteMsg; use crate::error::ContractError; -use crate::msg::{AdapterQueryMsg, ExecuteMsg, InstantiateMsg, MigrateMsg}; +use crate::msg::{AdapterQueryMsg, ExecuteMsg, InstantiateMsg}; use crate::state::{Config, CONFIG}; #[cfg_attr(not(feature = "library"), entry_point)] diff --git a/contracts/gauge-adapter/src/multitest/sample.rs b/contracts/gauge-adapter/src/multitest/sample.rs index dbeeca8..db1b247 100644 --- a/contracts/gauge-adapter/src/multitest/sample.rs +++ b/contracts/gauge-adapter/src/multitest/sample.rs @@ -166,26 +166,6 @@ fn cw20_rewards_work_direct() { cw20_rewards_work(suite); } -#[test] -// Like the above test, but here we create the adapter via migration -fn cw20_rewards_work_via_migration() { - let suite = SuiteBuilder::new() - .with_funds("owner", &[]) - .with_stake_config(DefaultStakeConfig { - staking_code_id: 0, - tokens_per_power: 1000u128.into(), - min_bond: 1000u128.into(), - unbonding_periods: vec![SECONDS_PER_DAY * 7], - max_distributions: 5, - converter: None, - }) - .with_cw20_reward(100) - .via_placeholder() - .build(); - - cw20_rewards_work(suite); -} - fn cw20_rewards_work(mut suite: Suite) { // FIXME: how does this work? AssetInfo::to_string() ?? not a cleaner way to unwrap the enum? let reward_contract = Addr::unchecked(suite.reward.info.to_string()); diff --git a/contracts/gauge-adapter/src/multitest/suite.rs b/contracts/gauge-adapter/src/multitest/suite.rs index 8cf8221..3ff815e 100644 --- a/contracts/gauge-adapter/src/multitest/suite.rs +++ b/contracts/gauge-adapter/src/multitest/suite.rs @@ -126,11 +126,6 @@ impl SuiteBuilder { self } - pub fn via_placeholder(mut self) -> Self { - self.via_placeholder = true; - self - } - pub fn with_native_reward(mut self, amount: u128, denom: &str) -> Self { self.reward = Asset { amount: amount.into(), diff --git a/contracts/junoswap-staking/.cargo/config b/contracts/junoswap-staking/.cargo/config deleted file mode 100644 index de2d36a..0000000 --- a/contracts/junoswap-staking/.cargo/config +++ /dev/null @@ -1,5 +0,0 @@ -[alias] -wasm = "build --release --lib --target wasm32-unknown-unknown" -wasm-debug = "build --lib --target wasm32-unknown-unknown" -unit-test = "test --lib" -schema = "run --bin schema" diff --git a/contracts/junoswap-staking/Cargo.toml b/contracts/junoswap-staking/Cargo.toml deleted file mode 100644 index 892c0d9..0000000 --- a/contracts/junoswap-staking/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "junoswap-staking" -authors = ["Volume Fi"] -version = { workspace = true } -edition = { workspace = true } -description = "Contract aimed just for migration - take JunoSwap staked LP and migrate to PALOMA DEX" -license = { workspace = true } -repository = { workspace = true } -homepage = "https://www.palomachain.com" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -# for more explicit tests, cargo test --features=backtraces -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all instantiate/execute/query exports -library = [] - -[dependencies] -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw-storage-plus = { workspace = true } -cw2 = { workspace = true } -cw20 = { workspace = true } -cw-utils = { workspace = true } -thiserror = { workspace = true } - -palomadex = { workspace = true } -palomadex-factory = { workspace = true } -palomadex-stake = { workspace = true } -# this is old version of cw20 used by wasmswap -wasmswap_cw20 = { package = "cw20", version = "0.10.0" } -# this is the staking contract we are migrating from (use the state variables there) -stake-cw20 = { git="https://github.com/DA0-DA0/dao-contracts", tag="v0.3.0" } -# this is the pool contract we will withdraw from -wasmswap = { git="https://github.com/Wasmswap/wasmswap-contracts", tag="v1.1.2-beta" } - -[dev-dependencies] -anyhow = { workspace = true } -cw-multi-test = { workspace = true } -serde = { workspace = true } -wasmswap_cw20-base = { package = "cw20-base", version = "0.10.0" } -wasmswap_cw-utils = { package = "cw-utils", version = "0.11" } -palomadex-factory = { workspace = true } -palomadex-pair = { workspace = true } -cw20-base = { workspace = true } diff --git a/contracts/junoswap-staking/README.md b/contracts/junoswap-staking/README.md deleted file mode 100644 index 4c3b105..0000000 --- a/contracts/junoswap-staking/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# JunoSwap Staking Migration - -This contract is intended as a migration target for an existing JunoSwap staking contract. -Upon migration it will prepare for a future transfer (we don't know the exact pool address, -as we want to perform the migration proposal concurrently with the pool deployment proposal). - -Once it is migrated, the staking contract will be locked, and the only action is that -a nominated migrator account can trigger the transfer of the LP controlled by the staking pool -to a palomadex pool. We add some constraints to ensure this is transferred to a valid target contract -to minimize any trust requirements on the migrator (they just have "censorship" power). - diff --git a/contracts/junoswap-staking/src/bin/schema.rs b/contracts/junoswap-staking/src/bin/schema.rs deleted file mode 100644 index 617c526..0000000 --- a/contracts/junoswap-staking/src/bin/schema.rs +++ /dev/null @@ -1,12 +0,0 @@ -use cosmwasm_schema::write_api; -use cosmwasm_std::Empty; -use junoswap_staking::msg::{ExecuteMsg, MigrateMsg, QueryMsg}; - -fn main() { - write_api! { - instantiate: Empty, - query: QueryMsg, - execute: ExecuteMsg, - migrate: MigrateMsg, - } -} diff --git a/contracts/junoswap-staking/src/contract.rs b/contracts/junoswap-staking/src/contract.rs deleted file mode 100644 index c88af48..0000000 --- a/contracts/junoswap-staking/src/contract.rs +++ /dev/null @@ -1,448 +0,0 @@ -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; -use cosmwasm_std::{ - coin, ensure_eq, to_binary, Addr, Binary, Coin, Deps, DepsMut, Empty, Env, MessageInfo, Order, - Reply, Response, StdResult, SubMsg, Uint128, WasmMsg, -}; - -use cw2::{get_contract_version, set_contract_version}; -use cw_utils::ensure_from_older_version; -use palomadex::asset::{Asset, AssetInfo}; -use wasmswap::msg::InfoResponse; - -use crate::error::ContractError; -use crate::msg::{ExecuteMsg, MigrateMsg, QueryMsg}; -use crate::state::{MigrateConfig, MigrateStakersConfig, DESTINATION, MIGRATION}; - -// this is the contract we are migrating from -pub const STAKE_CW20_NAME: &str = "crates.io:stake_cw20"; - -// version info for migration info -const CONTRACT_NAME: &str = "crates.io:junoswap-staking"; -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: Empty, -) -> Result { - Err(ContractError::NotImplemented) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> Result { - match msg { - QueryMsg::MigrationFinished {} => { - let no_stakers = stake_cw20::state::STAKED_BALANCES - .keys(_deps.storage, None, None, Order::Ascending) - .next() - .is_none(); - Ok(to_binary(&no_stakers)?) - } - } -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: ExecuteMsg, -) -> Result { - match msg { - ExecuteMsg::MigrateTokens { palomadex_pool } => migrate_tokens(deps, env, info, palomadex_pool), - ExecuteMsg::MigrateStakers { limit } => migrate_stakers(deps, env, info, limit), - } -} - -/// Allow `migrator` to pull out LP positions and send them to paloma dex pool -/// First step figures out how many LPs we have and withdraws them. -/// Follow up via reply. -pub fn migrate_tokens( - deps: DepsMut, - env: Env, - info: MessageInfo, - palomadex_pool: String, -) -> Result { - // make sure called by proper account - let mut migration = MIGRATION.load(deps.storage)?; - if info.sender != migration.migrator { - return Err(ContractError::Unauthorized); - } - - // ensure the requested target pool is valid - let w_pool = deps.api.addr_validate(&palomadex_pool)?; - if let Some(ref target) = migration.palomadex_pool { - if target != w_pool { - return Err(ContractError::InvalidDestination(palomadex_pool)); - } - } - let ci = deps.querier.query_wasm_contract_info(&w_pool)?; - if ci.creator != migration.factory { - return Err(ContractError::InvalidDestination(palomadex_pool)); - } - - // save target pool for later reply block - DESTINATION.save(deps.storage, &w_pool)?; - - // calculate LP tokens owner by staking contract, - // for withdrawal and for future distribution - let stake_cfg = stake_cw20::state::CONFIG.load(deps.storage)?; - let token = cw20::Cw20Contract(stake_cfg.token_address); - let balance = token.balance(&deps.querier, env.contract.address)?; - - // fill in most of the migration data now (minus paloma dex LP) - let palomadex::pair::PairInfo { - liquidity_token, - staking_addr, - .. - } = deps - .querier - .query_wasm_smart(&w_pool, &palomadex::pair::QueryMsg::Pair {})?; - - // total_staked is same a balance of junoswap lp token held by this contract - migration.migrate_stakers_config = Some(MigrateStakersConfig { - lp_token: liquidity_token, - staking_addr, - total_lp_tokens: Uint128::zero(), - total_staked: balance, - }); - MIGRATION.save(deps.storage, &migration)?; - - // trigger withdrawal of LP tokens - // we need to assign a cw20 allowance to let the pool burn LP - let allowance = WasmMsg::Execute { - contract_addr: token.0.to_string(), - funds: vec![], - msg: to_binary(&cw20::Cw20ExecuteMsg::IncreaseAllowance { - spender: migration.junoswap_pool.to_string(), - amount: balance, - expires: None, - })?, - }; - - // then craft the LP withdrawal message - let withdraw = WasmMsg::Execute { - contract_addr: migration.junoswap_pool.into_string(), - funds: vec![], - msg: to_binary(&wasmswap::msg::ExecuteMsg::RemoveLiquidity { - amount: balance, - min_token1: Uint128::zero(), - min_token2: Uint128::zero(), - expiration: None, - })?, - }; - - // execute these and handle the next step in reply - let res = Response::new() - .add_message(allowance) - .add_submessage(SubMsg::reply_on_success(withdraw, REPLY_ONE)); - Ok(res) -} - -pub fn migrate_stakers( - mut deps: DepsMut, - env: Env, - info: MessageInfo, - limit: u32, -) -> Result { - // make sure called by proper account - let migration = MIGRATION.load(deps.storage)?; - ensure_eq!(info.sender, migration.migrator, ContractError::Unauthorized); - - let config = migration - .migrate_stakers_config - .ok_or(ContractError::TokensNotMigrated)?; - - // calculate next `limit` stakers and their shares - let stakers = find_stakers(deps.as_ref(), limit)?; - - // remove the processed stakers from the state - remove_stakers(deps.branch(), &env, stakers.iter().map(|(addr, _)| addr))?; - - let staker_lps: Vec<_> = stakers - .into_iter() - .map(|(addr, stake)| { - ( - addr.to_string(), - stake * config.total_lp_tokens / config.total_staked, - ) - }) - .filter(|(_, x)| !x.is_zero()) - .collect(); - - // the amount of LP tokens we are migrating in this message - let batch_lp: Uint128 = staker_lps.iter().map(|(_, x)| x).sum(); - - // bonding has full info on who receives the delegation - let bond_msg = palomadex::stake::ReceiveMsg::MassDelegate { - unbonding_period: migration.unbonding_period, - delegate_to: staker_lps, - }; - - // stake it all - let stake_msg = WasmMsg::Execute { - contract_addr: config.lp_token.to_string(), - funds: vec![], - msg: to_binary(&cw20::Cw20ExecuteMsg::Send { - contract: config.staking_addr.into_string(), - amount: batch_lp, - msg: to_binary(&bond_msg)?, - })?, - }; - - Ok(Response::new().add_message(stake_msg)) -} - -const REPLY_ONE: u64 = 111; -const REPLY_TWO: u64 = 222; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { - if msg.result.is_err() { - return Err(ContractError::ErrorReply); - } - match msg.id { - REPLY_ONE => reply_one(deps, env), - REPLY_TWO => reply_two(deps, env), - x => Err(ContractError::UnknownReply(x)), - } -} - -/// In this step, we deposit the new raw tokens (eg. JUNO-ATOM) into PALOMA DEX -/// And get some liquid PALOMA DEX LP tokens -pub fn reply_one(deps: DepsMut, env: Env) -> Result { - let migration = MIGRATION.load(deps.storage)?; - let destination = DESTINATION.load(deps.storage)?; - - // get the JS asset types and convert to PALOMA DEX types - let info: InfoResponse = deps - .querier - .query_wasm_smart(migration.junoswap_pool, &wasmswap::msg::QueryMsg::Info {})?; - let assets = to_palomadex_assets(deps.as_ref(), env.contract.address, info)?; - - // figure out how to transfer these... previous cw20 allowances or - // sending native funds inline with providing liquidity - let (allowances, funds) = prepare_denom_deposits(&destination, &assets)?; - let deposit = WasmMsg::Execute { - contract_addr: destination.into_string(), - funds, - msg: to_binary(&palomadex::pair::ExecuteMsg::ProvideLiquidity { - assets, - // TODO: set some value here? - slippage_tolerance: None, - receiver: None, - })?, - }; - - // add any cw20 allowances, then call to deposit the tokens and get LP - let res = Response::new() - .add_messages(allowances) - .add_submessage(SubMsg::reply_on_success(deposit, REPLY_TWO)); - Ok(res) -} - -fn prepare_denom_deposits( - destination: &Addr, - assets: &[Asset], -) -> Result<(Vec, Vec), ContractError> { - let mut msgs = vec![]; - let mut funds = vec![]; - prepare_denom_deposit(destination, &assets[0], &mut msgs, &mut funds)?; - prepare_denom_deposit(destination, &assets[1], &mut msgs, &mut funds)?; - // sort denoms for deposit - funds.sort_by(|coin1, coin2| coin1.denom.cmp(&coin2.denom)); - Ok((msgs, funds)) -} - -fn prepare_denom_deposit( - destination: &Addr, - asset: &Asset, - msgs: &mut Vec, - funds: &mut Vec, -) -> Result<(), ContractError> { - // build allowance msg or funds to transfer for this asset - match &asset.info { - AssetInfo::Token(token) => { - let embed = cw20::Cw20ExecuteMsg::IncreaseAllowance { - spender: destination.to_string(), - amount: asset.amount, - expires: None, - }; - let msg = WasmMsg::Execute { - contract_addr: token.to_string(), - msg: to_binary(&embed)?, - funds: vec![], - }; - msgs.push(msg); - } - AssetInfo::Native(denom) => { - let coin = coin(asset.amount.u128(), denom); - funds.push(coin); - } - } - Ok(()) -} - -fn to_palomadex_assets( - deps: Deps, - me: Addr, - info: InfoResponse, -) -> Result, ContractError> { - let asset1 = to_palomadex_asset(deps, &me, info.token1_denom)?; - let asset2 = to_palomadex_asset(deps, &me, info.token2_denom)?; - Ok(vec![asset1, asset2]) -} - -fn to_palomadex_asset( - deps: Deps, - me: &Addr, - token: wasmswap_cw20::Denom, -) -> Result { - let asset = match token { - wasmswap_cw20::Denom::Native(denom) => { - let balance = deps.querier.query_balance(me, denom)?; - Asset { - info: AssetInfo::Native(balance.denom), - amount: balance.amount, - } - } - wasmswap_cw20::Denom::Cw20(addr) => { - let token = cw20::Cw20Contract(addr); - let amount = token.balance(&deps.querier, me)?; - Asset { - info: AssetInfo::Token(token.0.into_string()), - amount, - } - } - }; - Ok(asset) -} - -/// Finally, with those PALOMA DEX LP tokens, we will take them all on behalf -/// of the original JunoSwap LP stakers. -pub fn reply_two(deps: DepsMut, env: Env) -> Result { - // load config for LP token and staking contract - let mut migration = MIGRATION.load(deps.storage)?; - let config = migration.migrate_stakers_config.as_mut().unwrap(); - - // how many LP do we have total - let lp_token = cw20::Cw20Contract(config.lp_token.clone()); - let total_lp_tokens = lp_token.balance(&deps.querier, env.contract.address)?; - - // store this for `migrate_stakers` to use - config.total_lp_tokens = total_lp_tokens; - MIGRATION.save(deps.storage, &migration)?; - - Ok(Response::new()) -} - -// query logic taken from https://github.com/cosmorama/wyndex-priv/pull/109 -fn find_stakers(deps: Deps, limit: impl Into>) -> StdResult> { - let balances = stake_cw20::state::STAKED_BALANCES - .range(deps.storage, None, None, Order::Ascending) - .map(|stake| { - let (addr, amount) = stake?; - - // query all pending claims and bond them as well - let claims = stake_cw20::state::CLAIMS.query_claims(deps, &addr)?; - let claims_sum = claims.claims.iter().map(|c| c.amount).sum::(); - - Ok((addr, amount + claims_sum)) - }); - match limit.into() { - Some(limit) => balances.take(limit as usize).collect(), - None => balances.collect(), - } -} - -fn remove_stakers<'a>( - deps: DepsMut, - env: &Env, - stakers: impl Iterator, -) -> Result<(), ContractError> { - for staker in stakers { - stake_cw20::state::STAKED_BALANCES.remove(deps.storage, staker, env.block.height)?; - } - Ok(()) -} -#[cfg(test)] -mod tests { - use super::*; - - use cosmwasm_std::coin; - - #[test] - fn prepare_denom_deposits_sorted() { - let destination = Addr::unchecked("destination"); - let assets = vec![ - Asset { - info: AssetInfo::Native("uusdc".to_owned()), - amount: Uint128::new(9_000_000_000u128), - }, - Asset { - info: AssetInfo::Native("ujuno".to_owned()), - amount: Uint128::new(5_000_000_000u128), - }, - ]; - - let (_, rcoins) = prepare_denom_deposits(&destination, &assets).unwrap(); - assert_eq!( - rcoins, - vec![ - coin(5_000_000_000u128, "ujuno".to_owned()), - coin(9_000_000_000u128, "uusdc".to_owned()) - ] - ); - - let assets = vec![ - Asset { - info: AssetInfo::Native("uusdc".to_owned()), - amount: Uint128::new(9_000_000_000u128), - }, - Asset { - info: AssetInfo::Native( - "ibc/0C1FFD27A01B116F10F0BC624A6A24190BC9C57B27837E23E3B43C34A193967C" - .to_owned(), - ), - amount: Uint128::new(1_000_000_000u128), - }, - ]; - let (_, rcoins) = prepare_denom_deposits(&destination, &assets).unwrap(); - assert_eq!( - rcoins, - vec![ - coin( - 1_000_000_000u128, - "ibc/0C1FFD27A01B116F10F0BC624A6A24190BC9C57B27837E23E3B43C34A193967C" - .to_owned() - ), - coin(9_000_000_000u128, "uusdc".to_owned()) - ] - ); - - let assets = vec![ - Asset { - info: AssetInfo::Token("paloma1paloma".to_owned()), - amount: Uint128::new(69_000_000_000u128), - }, - Asset { - info: AssetInfo::Native( - "ibc/0C1FFD27A01B116F10F0BC624A6A24190BC9C57B27837E23E3B43C34A193967C" - .to_owned(), - ), - amount: Uint128::new(1_000_000_000u128), - }, - ]; - let (_, rcoins) = prepare_denom_deposits(&destination, &assets).unwrap(); - assert_eq!( - rcoins, - vec![coin( - 1_000_000_000u128, - "ibc/0C1FFD27A01B116F10F0BC624A6A24190BC9C57B27837E23E3B43C34A193967C".to_owned() - ),] - ); - } -} diff --git a/contracts/junoswap-staking/src/error.rs b/contracts/junoswap-staking/src/error.rs deleted file mode 100644 index ea2a527..0000000 --- a/contracts/junoswap-staking/src/error.rs +++ /dev/null @@ -1,32 +0,0 @@ -use cosmwasm_std::StdError; -use thiserror::Error; - -#[derive(Error, Debug, PartialEq)] -pub enum ContractError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("Unauthorized")] - Unauthorized, - - #[error("Tokens have to be migrated before stakers")] - TokensNotMigrated, - - #[error("{0} isn't an authorized pool to withdraw into")] - InvalidDestination(String), - - #[error("Method not implemented - only intended for migration")] - NotImplemented, - - #[error("Cannot migrate contract type: `{0}`. Only works for wasmswap staking")] - CannotMigrate(String), - - #[error("Got reply with unknown ID: {0}")] - UnknownReply(u64), - - #[error("Target factory doesn't have unbonding period: {0}")] - InvalidUnbondingPeriod(u64), - - #[error("Got reply with error, only handle success case")] - ErrorReply, -} diff --git a/contracts/junoswap-staking/src/junoswap.rs b/contracts/junoswap-staking/src/junoswap.rs deleted file mode 100644 index a239263..0000000 --- a/contracts/junoswap-staking/src/junoswap.rs +++ /dev/null @@ -1,2 +0,0 @@ -// This is state and message definitions copied from the junoswap contracts we migrate from - diff --git a/contracts/junoswap-staking/src/lib.rs b/contracts/junoswap-staking/src/lib.rs deleted file mode 100644 index a3d2c2f..0000000 --- a/contracts/junoswap-staking/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -pub mod contract; -mod error; -pub mod msg; -pub mod state; - -#[cfg(test)] -mod multitest; - -pub use error::ContractError; - -// #[cfg(test)] -// mod multitest; diff --git a/contracts/junoswap-staking/src/msg.rs b/contracts/junoswap-staking/src/msg.rs deleted file mode 100644 index 0141c70..0000000 --- a/contracts/junoswap-staking/src/msg.rs +++ /dev/null @@ -1,46 +0,0 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; - -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - /// Checks whether all stakers have been migrated - #[returns(bool)] - MigrationFinished {}, -} - -#[cw_serde] -pub struct MigrateMsg { - /// This must be Some the first migration (from JunoSwap contracts). - /// This must be None if upgrading from junoswap-staking to junoswap-staking - pub init: Option, -} - -/// For existing contract, we need to specify which pool it can be withdrawn into -#[cw_serde] -pub struct OrigMigrateMsg { - /// This is the address that can run ExecuteMsg::MigrateTokens - pub migrator: String, - /// This is how long it will be staked on PALOMA DEX - pub unbonding_period: u64, - - /// This is the junoswap pool where the LP will be withdrawn from - pub junoswap_pool: String, - - /// Can be deposited in any pool created by this factory - pub factory: String, - /// If set, only can be deposited in this pool (which must also be created by the factory) - pub palomadex_pool: Option, -} - -#[cw_serde] -pub enum ExecuteMsg { - /// Migrate tokens to this pool. - /// This moves the LP tokens to this contract, which are later given to the stakers in `MigrateStakers`. - /// Must be called by migrator. - /// Target pool must match constraints above - MigrateTokens { palomadex_pool: String }, - - /// Give the next `limit` stakers their LP tokens. - /// Must be called by migrator. - MigrateStakers { limit: u32 }, -} diff --git a/contracts/junoswap-staking/src/multitest.rs b/contracts/junoswap-staking/src/multitest.rs deleted file mode 100644 index c5348f3..0000000 --- a/contracts/junoswap-staking/src/multitest.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod migration; -mod suite; diff --git a/contracts/junoswap-staking/src/multitest/migration.rs b/contracts/junoswap-staking/src/multitest/migration.rs deleted file mode 100644 index 106ca51..0000000 --- a/contracts/junoswap-staking/src/multitest/migration.rs +++ /dev/null @@ -1,658 +0,0 @@ -use crate::{multitest::suite::PoolDenom, ContractError}; - -use super::suite::SuiteBuilder; - -use wasmswap_cw20::Denom; - -use cosmwasm_std::{assert_approx_eq, coin, Addr, Coin, Decimal, Uint128}; - -#[test] -fn testsuite_instantiation() { - let ujuno = "ujuno"; - let uluna = "uluna"; - let user = "user"; - - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Native(ujuno.to_owned()), - PoolDenom::Native(uluna.to_owned()), - ) - .build(); - - suite - .provide_liquidity_to_junoswap_pool( - user, - 1_000_000u128, - 1_000_000u128, - None, - None, - vec![coin(1_000_000, "ujuno"), coin(1_000_000, "uluna")], - ) - .unwrap(); - - // stake some of these tokens - let lp = suite.junoswap_lp(user, None).unwrap(); - assert_eq!(lp.u128(), 1_000_000u128); - let to_stake = lp * Decimal::percent(30); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - let new_lp = suite.junoswap_lp(user, None).unwrap(); - assert_eq!(new_lp, lp - to_stake); -} - -#[test] -fn partial_migration() { - let ujuno = "ujuno"; - let uluna = "uluna"; - let users = (0..10).map(|i| format!("user{}", i)).collect::>(); - - let suite = SuiteBuilder::new().with_denoms( - PoolDenom::Native(ujuno.to_owned()), - PoolDenom::Native(uluna.to_owned()), - ); - let mut suite = suite.build(); - - for (i, user) in users.iter().enumerate() { - // Provide (roughly) 1m of each asset - suite - .provide_liquidity_to_junoswap_pool( - user, - 1_000_000u128, - 1_000_000 + i as u128, - None, - None, - vec![coin(1_000_000, ujuno), coin(1_000_000 + i as u128, uluna)], - ) - .unwrap(); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - } - - // migrate the tokens - suite - .migrate_tokens_with_self_upgrade(None, None, None) - .unwrap(); - - assert!( - !suite.migration_finished().unwrap(), - "stakers not migrated yet" - ); - - suite.migrate_stakers(5).unwrap(); - - // only 5 stakers should have tokens now - let lp_tokens: Vec<_> = users - .iter() - .map(|u| suite.palomadex_staked(u, suite.migration_unbonding_period())) - .filter(|lp| *lp > 0) - .collect(); - assert_eq!(lp_tokens.len(), 5); - assert!(lp_tokens.iter().all(|lp| *lp == 799900)); - - assert!(!suite.migration_finished().unwrap(), "still stakers left"); - - suite.migrate_stakers(5).unwrap(); - - // next 5 stakers should also have tokens now - let lp_tokens: Vec<_> = users - .iter() - .map(|u| suite.palomadex_staked(u, suite.migration_unbonding_period())) - .filter(|lp| *lp > 0) - .collect(); - assert_eq!(lp_tokens.len(), 10); - assert!(lp_tokens.iter().all(|lp| *lp == 799900)); - - assert!(suite.migration_finished().unwrap(), "all stakers migrated"); -} - -#[test] -fn migration_sanity_check() { - // This just does a basic migration of one staked user with no claims - let ujuno = "ujuno"; - let uluna = "uluna"; - let user = "user"; - let liquidity = vec![coin(1_000_000, ujuno), coin(1_000_000, uluna)]; - - let mut suite = setup_basic_suite(ujuno, uluna, user, liquidity.clone()); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - - // make sure no lp before the deposit - let palomadex_total = suite.total_palomadex_lp(); - assert_eq!(palomadex_total, 0u128); - - // cross our fingers this works ;) - suite.migrate_to_palomadex(None, None, None).unwrap(); - - // 80% of liquidity moved to palomadex pool - let palomadex = suite - .app - .wrap() - .query_all_balances(&suite.palomadex_pair_contract) - .unwrap(); - let expected = liquidity - .iter() - .map(|Coin { amount, denom }| coin(amount.u128() * 4 / 5, denom)) - .collect::>(); - assert_eq!(palomadex, expected); - - // 20% of liquidity still in junoswap - let junoswap = suite - .app - .wrap() - .query_all_balances(&suite.junoswap_pool_contract) - .unwrap(); - let expected = liquidity - .iter() - .map(|Coin { amount, denom }| coin(amount.u128() / 5, denom)) - .collect::>(); - assert_eq!(junoswap, expected); - - // ensure all lp belong to the staking contract - // except for the MINIMUM_LIQUIDITY_DEPOSIT - held by pool - // https://github.com/cosmorama/wyndex-priv/blob/d39f7369d22d458a85c6828d151bc3844a1604bf/contracts/pair/src/contract.rs#L381-L395 - let palomadex_total = suite.total_palomadex_lp(); - let palomadex_staked = suite.total_palomadex_staked(); - let pool = suite.palomadex_pair_contract.to_string(); - let pool_own_lp = suite.palomadex_lp(&pool); - assert_eq!(palomadex_total, palomadex_staked + pool_own_lp); - assert_eq!( - pool_own_lp, - palomadex::asset::MINIMUM_LIQUIDITY_AMOUNT.u128() - ); - - // ensure all staked tokens belong to the migrated user - let user_staked = suite.palomadex_staked(user, suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked); -} - -#[test] -fn non_migrator_cant_migrate() { - let ujuno = "ujuno"; - let uluna = "uluna"; - let user = "user"; - let liquidity = vec![coin(1_000_000, ujuno), coin(1_000_000, uluna)]; - - let mut suite = setup_basic_suite(ujuno, uluna, user, liquidity); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - - // this won't work, not the migrator - let err = suite - .migrate_to_palomadex(Some(Addr::unchecked("notthemigrator")), None, None) - .unwrap_err(); - assert_eq!(ContractError::Unauthorized {}, err.downcast().unwrap()) -} -#[test] -fn migrator_cant_migrate_to_own_addr() { - let ujuno = "ujuno"; - let uluna = "uluna"; - let user = "user"; - let liquidity = vec![coin(1_000_000, ujuno), coin(1_000_000, uluna)]; - - let mut suite = setup_basic_suite(ujuno, uluna, user, liquidity); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - - // this won't work, we can only migrate to a deployed pool contract. - let err = suite - .migrate_to_palomadex( - Some(Addr::unchecked("owner")), - Some(suite.palomadex_pair_contract.clone()), - Some(Addr::unchecked("owner")), - ) - .unwrap_err(); - - assert_eq!( - ContractError::InvalidDestination("owner".to_string()), - err.downcast().unwrap() - ); -} - -fn setup_basic_suite( - ujuno: &str, - uluna: &str, - user: &str, - liquidity: Vec, -) -> super::suite::Suite { - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Native(ujuno.to_owned()), - PoolDenom::Native(uluna.to_owned()), - ) - .build(); - suite - .provide_liquidity_to_junoswap_pool( - user, - 1_000_000u128, - 1_000_000u128, - None, - None, - liquidity.clone(), - ) - .unwrap(); - // check balances of pool - let junoswap = suite - .app - .wrap() - .query_all_balances(&suite.junoswap_pool_contract) - .unwrap(); - assert_eq!(junoswap, liquidity); - suite -} - -#[test] -fn migration_multiple_users() { - let ujuno = "ujuno"; - let uluna = "uluna"; - let users = ["user", "user2", "user3"]; - // Setup Pools with initial liquidity - let liquidity = vec![coin(5_000_000, ujuno), coin(5_000_003, uluna)]; - - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Native(ujuno.to_owned()), - PoolDenom::Native(uluna.to_owned()), - ) - .build(); - // First user to provide 1.5m of each asset - suite - .provide_liquidity_to_junoswap_pool( - users[0], - 1_500_000u128, - 1_500_000u128, - None, - None, - vec![coin(1_500_000, ujuno), coin(1_500_000, uluna)], - ) - .unwrap(); - - // Need more coins this time on asset 2, because of this: https://github.com/Wasmswap/wasmswap-contracts/blob/cbca1f2bd8088b2ac6784c47a4509227a227c755/src/contract.rs#L278 - suite - .provide_liquidity_to_junoswap_pool( - users[1], - 500_000u128, - 500_001u128, - None, - None, - vec![coin(500_000, ujuno), coin(500_001, uluna)], - ) - .unwrap(); - - suite - .provide_liquidity_to_junoswap_pool( - users[2], - 3_000_000u128, - 3_000_002u128, - None, - None, - vec![coin(3_000_000, ujuno), coin(3_000_002, uluna)], - ) - .unwrap(); - - // check balances of pool - let junoswap = suite - .app - .wrap() - .query_all_balances(&suite.junoswap_pool_contract) - .unwrap(); - assert_eq!(junoswap, liquidity); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(users[0], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp(users[0], to_stake, None, None) - .unwrap(); - let to_stake = suite.junoswap_lp(users[1], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp(users[1], to_stake, None, None) - .unwrap(); - let to_stake = suite.junoswap_lp(users[2], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp(users[2], to_stake, None, None) - .unwrap(); - - // perform the migration of liquidity - suite.migrate_to_palomadex(None, None, None).unwrap(); - - // 80% of liquidity moved to palomadex pool - let palomadex = suite - .app - .wrap() - .query_all_balances(&suite.palomadex_pair_contract) - .unwrap(); - let expected = liquidity - .iter() - .map(|Coin { amount, denom }| coin(amount.u128() * 4 / 5, denom)) - .collect::>(); - assert_eq!(palomadex, expected); - - // ensure all lp belong to the staking contract - let palomadex_total = suite.total_palomadex_lp(); - let palomadex_staked = suite.total_palomadex_staked(); - assert_approx_eq!(palomadex_total, palomadex_staked, "0.01"); - // ensure all staked tokens belong to the migrated user - let user_staked = suite.palomadex_staked(users[0], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 10 * 3); - // user 2 staked 500k so they should have about 10% of the staked tokens - let user_staked = suite.palomadex_staked(users[1], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 10,); - // user 3 did 3m and should have 60% - let user_staked = suite.palomadex_staked(users[2], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 10 * 6); -} - -#[test] -fn migrate_with_mixed_pairs() { - let ujuno = "ujuno"; - let uraw = "rawtoken"; - let users = ["user", "user2", "user3"]; - // Setup Pools with initial liquidity - let liquidity = vec![coin(3_000_000, ujuno)]; - let liquidity_cw20 = 3_000_002u128; - - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Native(ujuno.to_owned()), - PoolDenom::Cw20(uraw.to_owned()), - ) - .build(); - - let raw_denom = suite.pool_denom2.clone(); - let raw_address = match &raw_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - - // Provide Liquidity to the CW20 Native pair - // Note: Second deposits need 1 extra cw20 similar to the above rounding errors - suite - .provide_liquidity_to_junoswap_pool( - users[0], - 1_000_000u128, - 1_000_000u128, - Some(Denom::Native(ujuno.to_owned())), - Some(raw_denom.clone()), - vec![coin(1_000_000, ujuno)], - ) - .unwrap(); - - suite - .provide_liquidity_to_junoswap_pool( - users[1], - 1_000_000u128, - 1_000_001u128, - Some(Denom::Native(ujuno.to_owned())), - Some(raw_denom.clone()), - vec![coin(1_000_000, ujuno)], - ) - .unwrap(); - suite - .provide_liquidity_to_junoswap_pool( - users[2], - 1_000_000u128, - 1_000_001u128, - Some(Denom::Native(ujuno.to_owned())), - Some(raw_denom.clone()), - vec![coin(1_000_000, ujuno)], - ) - .unwrap(); - - // check balances of pool - let junoswap = suite - .app - .wrap() - .query_all_balances(&suite.junoswap_pool_contract) - .unwrap(); - assert_eq!(junoswap, liquidity); - let junoswap = cw20::Cw20Contract(raw_address.clone()) - .balance(&suite.app.wrap(), suite.junoswap_pool_contract.clone()) - .unwrap(); - assert_eq!(junoswap.u128(), liquidity_cw20); - - suite.palomadex_lp_holders(); - - // stake some of these tokens - 80% of liquidity should be moved - // users[0] will keep everything staked - let to_stake = suite.junoswap_lp(users[0], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - users[0], - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - // users[1] will unstake half - let to_stake = suite.junoswap_lp(users[1], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - users[1], - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - suite - .unstake_junoswap_lp( - users[1], - to_stake / Uint128::new(2), - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - // users[2] will unstake all - let to_stake = suite.junoswap_lp(users[2], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - users[2], - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - suite - .unstake_junoswap_lp( - users[2], - to_stake, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - - // perform the migration of liquidity - suite.migrate_to_palomadex(None, None, None).unwrap(); - - // 80% of native liquidity moved to palomadex pool - let palomadex = suite - .app - .wrap() - .query_all_balances(&suite.palomadex_pair_contract) - .unwrap(); - let expected = liquidity - .iter() - .map(|Coin { amount, denom }| coin(amount.u128() * 4 / 5, denom)) - .collect::>(); - assert_eq!(palomadex, expected); - - // 80% of cw20 liquidity moved to palomadex pool - let palomadex = cw20::Cw20Contract(raw_address.clone()) - .balance(&suite.app.wrap(), suite.palomadex_pair_contract.clone()) - .unwrap(); - let expected = liquidity_cw20 * 4 / 5; - assert_eq!(palomadex.u128(), expected); - - // ensure all lp belong to the staking contract - let palomadex_total = suite.total_palomadex_lp(); - let palomadex_staked = suite.total_palomadex_staked(); - assert_approx_eq!(palomadex_total, palomadex_staked, "0.001"); - // ensure all staked tokens belong to the migrated user - let user_staked = suite.palomadex_staked(users[0], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 3); - // user 2 staked 500k so they should have about 10% of the staked tokens - let user_staked = suite.palomadex_staked(users[1], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 3); - // user 3 did 3m and should have 60% - let user_staked = suite.palomadex_staked(users[2], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 3); -} - -#[test] -fn migrate_with_unbonding_claims() { - let ujuno = "ujuno"; - let uluna = "uluna"; - let user = "user"; - let liquidity = vec![coin(1_000_000, ujuno), coin(1_000_000, uluna)]; - - let mut suite = setup_basic_suite(ujuno, uluna, user, liquidity.clone()); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - - // Process an unstake request to generate a claim - suite - .unstake_junoswap_lp(user, 800_000u128.into(), None) - .unwrap(); - assert_eq!( - suite - .query_stake_claims_for_pair(user.to_string()) - .claims - .len(), - 1 - ); - - // make sure no lp before the deposit - let palomadex_total = suite.total_palomadex_lp(); - assert_eq!(palomadex_total, 0u128); - - // Migrate the liquidity to Palomadex, the liquidity includes 1 pair with 1 user who is currently unstaking - suite.migrate_to_palomadex(None, None, None).unwrap(); - - // 80% of liquidity moved to palomadex pool - let palomadex = suite - .app - .wrap() - .query_all_balances(&suite.palomadex_pair_contract) - .unwrap(); - let expected = liquidity - .iter() - .map(|Coin { amount, denom }| coin(amount.u128() * 4 / 5, denom)) - .collect::>(); - assert_eq!(palomadex, expected); - - // 20% of liquidity still in junoswap - let junoswap = suite - .app - .wrap() - .query_all_balances(&suite.junoswap_pool_contract) - .unwrap(); - let expected = liquidity - .iter() - .map(|Coin { amount, denom }| coin(amount.u128() / 5, denom)) - .collect::>(); - assert_eq!(junoswap, expected); - - // ensure all lp belong to the staking contract - // except for the MINIMUM_LIQUIDITY_DEPOSIT - held by pool - // https://github.com/cosmorama/wyndex-priv/blob/d39f7369d22d458a85c6828d151bc3844a1604bf/contracts/pair/src/contract.rs#L381-L395 - let palomadex_total = suite.total_palomadex_lp(); - let palomadex_staked = suite.total_palomadex_staked(); - let pool = suite.palomadex_pair_contract.to_string(); - let pool_own_lp = suite.palomadex_lp(&pool); - assert_eq!(palomadex_total, palomadex_staked + pool_own_lp); - assert_eq!( - pool_own_lp, - palomadex::asset::MINIMUM_LIQUIDITY_AMOUNT.u128() - ); - - // ensure all staked tokens belong to the migrated user - let user_staked = suite.palomadex_staked(user, suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked); -} - -#[test] -fn migration_two_cw20() { - let user = "user"; - let liquidity = 2_000_000u128; - - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Cw20("raw".to_owned()), - PoolDenom::Cw20("cwt".to_owned()), - ) - .build(); - - let raw_denom = suite.pool_denom1.clone(); - let raw_address = match &raw_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - let cw20_denom = suite.pool_denom2.clone(); - let cw20_address = match &cw20_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - - // Provide Liquidity to the CW20 pair - suite - .provide_liquidity_to_junoswap_pool( - user, - 2_000_000u128, - 2_000_000u128, - Some(cw20_denom.clone()), - Some(raw_denom.clone()), - vec![], - ) - .unwrap(); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - user, - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - - // make sure no lp before the deposit - let palomadex_total = suite.total_palomadex_lp(); - assert_eq!(palomadex_total, 0u128); - - // cross our fingers this works ;) - suite.migrate_to_palomadex(None, None, None).unwrap(); - - // 80% of liquidity moved to palomadex pool - let palomadex = cw20::Cw20Contract(raw_address.clone()) - .balance(&suite.app.wrap(), suite.palomadex_pair_contract.clone()) - .unwrap(); - let expected = liquidity * 4 / 5; - assert_eq!(palomadex.u128(), expected); - let palomadex = cw20::Cw20Contract(cw20_address.clone()) - .balance(&suite.app.wrap(), suite.palomadex_pair_contract.clone()) - .unwrap(); - let expected = liquidity * 4 / 5; - assert_eq!(palomadex.u128(), expected); - - // ensure all lp belong to the staking contract - let palomadex_total = suite.total_palomadex_lp(); - let palomadex_staked = suite.total_palomadex_staked(); - let pool = suite.palomadex_pair_contract.to_string(); - let pool_own_lp = suite.palomadex_lp(&pool); - assert_eq!(palomadex_total, palomadex_staked + pool_own_lp); - assert_eq!( - pool_own_lp, - palomadex::asset::MINIMUM_LIQUIDITY_AMOUNT.u128() - ); - - // ensure all staked tokens belong to the migrated user - let user_staked = suite.palomadex_staked(user, suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked); -} diff --git a/contracts/junoswap-staking/src/multitest/suite.rs b/contracts/junoswap-staking/src/multitest/suite.rs deleted file mode 100644 index 6438cbb..0000000 --- a/contracts/junoswap-staking/src/multitest/suite.rs +++ /dev/null @@ -1,753 +0,0 @@ -use anyhow::Result as AnyResult; - -use cw20::MinterResponse; -use palomadex::asset::AssetInfo; -use palomadex::factory::{ - DefaultStakeConfig, ExecuteMsg as FactoryExecuteMsg, InstantiateMsg as FactoryInstantiateMsg, - PairConfig, PairType, PartialStakeConfig, QueryMsg as FactoryQueryMsg, -}; -use palomadex::fee_config::FeeConfig; -use palomadex::pair::PairInfo; - -use crate::msg::{MigrateMsg, OrigMigrateMsg, QueryMsg}; -use cosmwasm_std::{coin, to_binary, Addr, Coin, Decimal, Uint128}; -use cw20_base::msg::InstantiateMsg as Cw20BaseInstantiateMsg; -use cw_multi_test::{next_block, App, AppResponse, BankSudo, ContractWrapper, Executor, SudoMsg}; -use stake_cw20::msg::{ClaimsResponse, InstantiateMsg as StakeCw20IntantiateMsg}; -use wasmswap::msg::{ - ExecuteMsg as WasmswapExecuteMsg, InfoResponse, InstantiateMsg as WasmswapInstantiateMsg, - QueryMsg as WasmswapQueryMsg, -}; -use wasmswap_cw20::{Cw20ExecuteMsg, Denom}; -use wasmswap_cw_utils::Duration; - -pub const ONE_DAY: u64 = 86_400; - -pub fn store_stake_cw20(app: &mut App) -> u64 { - let contract = Box::new(ContractWrapper::new( - stake_cw20::contract::execute, - stake_cw20::contract::instantiate, - stake_cw20::contract::query, - )); - app.store_code(contract) -} - -pub fn store_junoswap_pool(app: &mut App) -> u64 { - let contract = Box::new( - ContractWrapper::new( - wasmswap::contract::execute, - wasmswap::contract::instantiate, - wasmswap::contract::query, - ) - .with_reply_empty(wasmswap::contract::reply), - ); - app.store_code(contract) -} - -pub fn store_cw20(app: &mut App) -> u64 { - let contract = Box::new(ContractWrapper::new( - wasmswap_cw20_base::contract::execute, - wasmswap_cw20_base::contract::instantiate, - wasmswap_cw20_base::contract::query, - )); - app.store_code(contract) -} - -pub fn store_palomadex_staking(app: &mut App) -> u64 { - let contract = Box::new(ContractWrapper::new( - palomadex_stake::contract::execute, - palomadex_stake::contract::instantiate, - palomadex_stake::contract::query, - )); - app.store_code(contract) -} - -fn store_palomadex_factory(app: &mut App) -> u64 { - let factory_contract = Box::new( - ContractWrapper::new_with_empty( - palomadex_factory::contract::execute, - palomadex_factory::contract::instantiate, - palomadex_factory::contract::query, - ) - .with_reply_empty(palomadex_factory::contract::reply), - ); - - app.store_code(factory_contract) -} - -fn store_palomadex_pair(app: &mut App) -> u64 { - let factory_contract = Box::new( - ContractWrapper::new_with_empty( - palomadex_pair::contract::execute, - palomadex_pair::contract::instantiate, - palomadex_pair::contract::query, - ) - .with_reply_empty(palomadex_pair::contract::reply), - ); - - app.store_code(factory_contract) -} - -pub fn store_migrator(app: &mut App) -> u64 { - let contract = Box::new( - ContractWrapper::new( - crate::contract::execute, - crate::contract::instantiate, - crate::contract::query, - ) - .with_reply(crate::contract::reply), - ); - app.store_code(contract) -} - -/// Helper to be able to specify a non-existing cw20 token -#[derive(Debug, Clone)] -pub enum PoolDenom { - Native(String), - /// The string is not the contract address, but the symbol / name of the token. - /// A new token will be instantiated using this name. - Cw20(String), -} - -impl PoolDenom { - pub fn into_denom( - self, - app: &mut App, - owner: impl Into + Clone, - cw20_code_id: u64, - ) -> Denom { - match self { - PoolDenom::Native(denom) => Denom::Native(denom), - PoolDenom::Cw20(symbol) => { - // create cw20 token - let cw20_token = app - .instantiate_contract( - cw20_code_id, - Addr::unchecked(owner.clone()), - &Cw20BaseInstantiateMsg { - name: symbol.clone(), - symbol: symbol.clone(), - decimals: 6, - initial_balances: vec![], - mint: Some(MinterResponse { - minter: owner.into(), - cap: None, - }), - marketing: None, - }, - &[], - symbol, - None, - ) - .unwrap(); - Denom::Cw20(cw20_token) - } - } - } -} - -#[derive(Debug)] -pub struct SuiteBuilder { - funds: Vec<(Addr, Vec)>, - unbonding_periods: Vec, - pool_denom1: PoolDenom, - pool_denom2: PoolDenom, -} - -impl SuiteBuilder { - pub fn new() -> SuiteBuilder { - SuiteBuilder { - unbonding_periods: vec![100, 200, 300], - pool_denom1: PoolDenom::Native("ujuno".to_string()), - pool_denom2: PoolDenom::Native("uluna".to_string()), - funds: vec![], - } - } - - /// Specify the pool denoms. For cw20 denoms, the - pub fn with_denoms(mut self, denom1: PoolDenom, denom2: PoolDenom) -> Self { - self.pool_denom1 = denom1; - self.pool_denom2 = denom2; - self - } - - #[track_caller] - pub fn build(self) -> Suite { - let mut app = App::default(); - let owner = Addr::unchecked("owner"); - - let cw20_code_id = store_cw20(&mut app); - - let pool_denom1 = self - .pool_denom1 - .into_denom(&mut app, owner.clone(), cw20_code_id); - let pool_denom2 = self - .pool_denom2 - .into_denom(&mut app, owner.clone(), cw20_code_id); - - // Instantiate junoswap pool - let junoswap_pool_code_id = store_junoswap_pool(&mut app); - let junoswap_pool_contract = app - .instantiate_contract( - junoswap_pool_code_id, - owner.clone(), - &WasmswapInstantiateMsg { - token1_denom: pool_denom1.clone(), - token2_denom: pool_denom2.clone(), - lp_token_code_id: cw20_code_id, - owner: Some(owner.to_string()), - lp_fee_percent: Decimal::zero(), - protocol_fee_percent: Decimal::zero(), - protocol_fee_recipient: owner.to_string(), - }, - &[], - "wasmswap-pool", - Some(owner.to_string()), - ) - .unwrap(); - app.update_block(next_block); - - // Check address of created token contract - let junoswap_token_contract = Addr::unchecked( - app.wrap() - .query_wasm_smart::( - &junoswap_pool_contract, - &WasmswapQueryMsg::Info {}, - ) - .unwrap() - .lp_token_address, - ); - - // Instantiate junoswap staking contract - let junoswap_staking_code_id = store_stake_cw20(&mut app); - let junoswap_staking_contract = app - .instantiate_contract( - junoswap_staking_code_id, - owner.clone(), - &StakeCw20IntantiateMsg { - owner: Some(owner.to_string()), - manager: Some("manager".to_string()), - token_address: junoswap_token_contract.to_string(), - unstaking_duration: Some(Duration::Time(ONE_DAY * 14)), - }, - &[], - "staking", - Some(owner.to_string()), - ) - .unwrap(); - app.update_block(next_block); - - // Instantiate palomadex factory - let palomadex_stake_code_id = store_palomadex_staking(&mut app); - let palomadex_pair_code_id = store_palomadex_pair(&mut app); - let palomadex_factory_code_id = store_palomadex_factory(&mut app); - let factory_contract = app - .instantiate_contract( - palomadex_factory_code_id, - owner.clone(), - &FactoryInstantiateMsg { - pair_configs: vec![PairConfig { - pair_type: PairType::Xyk {}, - code_id: palomadex_pair_code_id, - fee_config: FeeConfig { - total_fee_bps: 0, - protocol_fee_bps: 0, - }, - is_disabled: false, - }], - token_code_id: cw20_code_id, - fee_address: Some(owner.to_string()), - owner: owner.to_string(), - max_referral_commission: Decimal::one(), - default_stake_config: DefaultStakeConfig { - staking_code_id: palomadex_stake_code_id, - tokens_per_power: Uint128::new(1000), - min_bond: Uint128::new(1000), - unbonding_periods: self.unbonding_periods.clone(), - max_distributions: 6, - converter: None, - }, - trading_starts: None, - }, - &[], - "palomadex-factory", - Some(owner.to_string()), - ) - .unwrap(); - - // Wasmswap is using older version of cw20, so specific From impl - // would have to be created - IMO not worth it - let asset_infos = vec![ - match pool_denom1.clone() { - Denom::Native(s) => AssetInfo::Native(s), - Denom::Cw20(s) => AssetInfo::Token(s.to_string()), - }, - match pool_denom2.clone() { - Denom::Native(s) => AssetInfo::Native(s), - Denom::Cw20(s) => AssetInfo::Token(s.to_string()), - }, - ]; - - // Instantiate palomadex pair contract through factory - app.execute_contract( - owner.clone(), - factory_contract.clone(), - &FactoryExecuteMsg::CreatePair { - pair_type: PairType::Xyk {}, - asset_infos: asset_infos.clone(), - init_params: None, - total_fee_bps: None, - // accept defaults, but ensure there is a staking contract - staking_config: PartialStakeConfig { - staking_code_id: None, - tokens_per_power: None, - min_bond: None, - unbonding_periods: None, - max_distributions: None, - converter: None, - }, - }, - &[], - ) - .unwrap(); - let pair_info = app - .wrap() - .query_wasm_smart::( - Addr::unchecked(&factory_contract), - &FactoryQueryMsg::Pair { asset_infos }, - ) - .unwrap(); - - let palomadex_pair_contract = pair_info.contract_addr; - let palomadex_staking_contract = pair_info.staking_addr; - let palomadex_token_contract = pair_info.liquidity_token; - - // add funds to the contract - let funds = self.funds; - app.init_modules(|router, _, storage| -> AnyResult<()> { - for (addr, coin) in funds { - router.bank.init_balance(storage, &addr, coin)?; - } - Ok(()) - }) - .unwrap(); - - let migrator_code_id = store_migrator(&mut app); - - Suite { - owner, - app, - junoswap_token_contract, - junoswap_pool_contract, - junoswap_staking_contract, - factory_contract, - palomadex_pair_contract, - palomadex_staking_contract, - palomadex_token_contract, - migrator_code_id, - cw20_code_id, - pool_denom1, - pool_denom2, - unbonding_periods: self.unbonding_periods, - } - } -} - -pub struct Suite { - pub owner: Addr, - pub app: App, - pub migrator_code_id: u64, - pub cw20_code_id: u64, - pub unbonding_periods: Vec, - - pub junoswap_token_contract: Addr, - pub junoswap_pool_contract: Addr, - pub junoswap_staking_contract: Addr, - pub palomadex_token_contract: Addr, - pub palomadex_staking_contract: Addr, - pub palomadex_pair_contract: Addr, - pub pool_denom1: Denom, - pub pool_denom2: Denom, - - pub factory_contract: Addr, -} - -#[derive(Debug)] -#[allow(dead_code)] -struct SuiteInfo<'a> { - pub junoswap_token_contract: &'a Addr, - pub junoswap_pool_contract: &'a Addr, - pub junoswap_staking_contract: &'a Addr, - pub factory_contract: &'a Addr, - pub palomadex_token_contract: &'a Addr, - pub palomadex_staking_contract: &'a Addr, - pub palomadex_pair_contract: &'a Addr, -} - -impl Suite { - // for debugging tests - #[allow(dead_code)] - pub fn info(&self) { - let info = SuiteInfo { - junoswap_token_contract: &self.junoswap_token_contract, - junoswap_pool_contract: &self.junoswap_pool_contract, - junoswap_staking_contract: &self.junoswap_staking_contract, - factory_contract: &self.factory_contract, - palomadex_token_contract: &self.palomadex_token_contract, - palomadex_staking_contract: &self.palomadex_staking_contract, - palomadex_pair_contract: &self.palomadex_pair_contract, - }; - println!("{:?}", info); - } - - pub fn migration_unbonding_period(&self) -> u64 { - self.unbonding_periods[1] - } - - /// Returns true if migration is finished - /// Only makes sense to call after the junoswap staking contract has been migrated - pub fn migration_finished(&self) -> AnyResult { - self.app - .wrap() - .query_wasm_smart( - self.junoswap_staking_contract.clone(), - &QueryMsg::MigrationFinished {}, - ) - .map_err(Into::into) - } - - // Like `migrate_tokens`, but after the first migration (from junoswap), - // it migrates to a newer version of this contract - pub fn migrate_tokens_with_self_upgrade( - &mut self, - migrator: Option, - palomadex_pair_migrate: Option, - palomadex_pair: Option, - ) -> AnyResult { - // first set up the migration - self.app.migrate_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &MigrateMsg { - init: Some(OrigMigrateMsg { - migrator: migrator.unwrap_or_else(|| self.owner.clone()).to_string(), - unbonding_period: self.migration_unbonding_period(), - junoswap_pool: self.junoswap_pool_contract.to_string(), - factory: self.factory_contract.to_string(), - palomadex_pool: palomadex_pair_migrate.map(|p| p.to_string()), - }), - }, - self.migrator_code_id, - )?; - - // then migrate again (self-migrate) - self.app.migrate_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &MigrateMsg { init: None }, - self.migrator_code_id, - )?; - - // then trigger the actual migration - self.app.execute_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &crate::msg::ExecuteMsg::MigrateTokens { - palomadex_pool: palomadex_pair - .unwrap_or_else(|| self.palomadex_pair_contract.clone()) - .to_string(), - }, - &[], - ) - } - - /// Migrates the junoswap staking contract to our migration contract and migrates the tokens - pub fn migrate_tokens( - &mut self, - migrator: Option, - palomadex_pair_migrate: Option, - palomadex_pair: Option, - ) -> AnyResult { - // first set up the migration - self.app.migrate_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &MigrateMsg { - init: Some(OrigMigrateMsg { - migrator: migrator.unwrap_or_else(|| self.owner.clone()).to_string(), - unbonding_period: self.migration_unbonding_period(), - junoswap_pool: self.junoswap_pool_contract.to_string(), - factory: self.factory_contract.to_string(), - palomadex_pool: palomadex_pair_migrate.map(|p| p.to_string()), - }), - }, - self.migrator_code_id, - )?; - - // then trigger the actual migration - self.app.execute_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &crate::msg::ExecuteMsg::MigrateTokens { - palomadex_pool: palomadex_pair - .unwrap_or_else(|| self.palomadex_pair_contract.clone()) - .to_string(), - }, - &[], - ) - } - - /// Migrates the next `limit` staker's LP tokens. - /// Only makes sense to call after the junoswap staking contract has been migrated. - pub fn migrate_stakers(&mut self, limit: u32) -> AnyResult { - self.app.execute_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &crate::msg::ExecuteMsg::MigrateStakers { limit }, - &[], - ) - } - - pub fn migrate_to_palomadex( - &mut self, - migrator: Option, - palomadex_pair_migrate: Option, - palomadex_pair: Option, - ) -> AnyResult<()> { - self.migrate_tokens(migrator, palomadex_pair_migrate, palomadex_pair)?; - - // now migrate all the stakers - while !self.migration_finished()? { - self.migrate_stakers(10)?; - } - - Ok(()) - } - - fn increase_allowance( - &mut self, - owner: &str, - contract: &Addr, - spender: &str, - amount: u128, - ) -> AnyResult { - self.app.execute_contract( - Addr::unchecked(owner), - contract.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: spender.to_owned(), - amount: amount.into(), - expires: None, - }, - &[], - ) - } - - pub fn mint_cw20( - &mut self, - owner: &str, - token: &Addr, - amount: u128, - recipient: &str, - ) -> AnyResult { - self.app.execute_contract( - Addr::unchecked(owner), - token.clone(), - &Cw20ExecuteMsg::Mint { - recipient: recipient.to_owned(), - amount: amount.into(), - }, - &[], - ) - } - - pub fn junoswap_lp(&mut self, user: &str, lp_contract: Option<&Addr>) -> AnyResult { - let query = cw20::Cw20QueryMsg::Balance { - address: user.to_string(), - }; - println!("querying junoswap lp: {:?}", lp_contract); - let cw20::BalanceResponse { balance } = self - .app - .wrap() - .query_wasm_smart(lp_contract.unwrap_or(&self.junoswap_token_contract), &query)?; - Ok(balance) - } - - /// Requirement: if using native token provide coins to sent as last argument - #[allow(clippy::too_many_arguments)] - pub fn provide_liquidity_to_junoswap_pool( - &mut self, - user: &str, - first_asset: u128, - second_asset: u128, - first_denom: Option, - second_denom: Option, - native_tokens: Vec, - ) -> AnyResult { - let owner = self.owner.to_string(); - - let assets = vec![ - ( - first_denom.unwrap_or_else(|| self.pool_denom1.clone()), - first_asset, - ), - ( - second_denom.unwrap_or_else(|| self.pool_denom2.clone()), - second_asset, - ), - ]; - for (denom, amount) in assets { - match denom { - Denom::Cw20(addr) => { - // Mint some initial balances for whale user - self.mint_cw20(&owner, &addr, amount, user).unwrap(); - // Increases allowances for given LP contracts in order to provide liquidity to pool - let spender = self.junoswap_pool_contract.to_string(); - self.increase_allowance(user, &addr, &spender, amount) - .unwrap(); - } - Denom::Native(denom) => { - self.app - .sudo(SudoMsg::Bank(BankSudo::Mint { - to_address: user.to_owned(), - amount: vec![coin(amount, denom)], - })) - .unwrap(); - } - } - } - - self.app.execute_contract( - Addr::unchecked(user), - self.junoswap_pool_contract.clone(), - &WasmswapExecuteMsg::AddLiquidity { - token1_amount: first_asset.into(), - min_liquidity: Uint128::new(100), - max_token2: second_asset.into(), - expiration: None, - }, - &native_tokens, - ) - } - - pub fn stake_junoswap_lp( - &mut self, - user: &str, - amount: Uint128, - lp_contract: Option<&Addr>, - staking_contract: Option<&Addr>, - ) -> AnyResult { - let msg = to_binary(&stake_cw20::msg::ReceiveMsg::Stake {})?; - self.app.execute_contract( - Addr::unchecked(user), - lp_contract - .unwrap_or(&self.junoswap_token_contract.clone()) - .to_owned(), - &cw20::Cw20ExecuteMsg::Send { - contract: staking_contract - .unwrap_or(&self.junoswap_staking_contract.clone()) - .to_string(), - amount, - msg, - }, - &[], - ) - } - - pub fn unstake_junoswap_lp( - &mut self, - user: &str, - amount: Uint128, - staking_contract: Option<&Addr>, - ) -> AnyResult { - self.app.execute_contract( - Addr::unchecked(user), - staking_contract - .unwrap_or(&self.junoswap_staking_contract) - .clone(), - &stake_cw20::msg::ExecuteMsg::Unstake { amount }, - &[], - ) - } - - pub fn query_stake_claims_for_pair(&mut self, address: String) -> ClaimsResponse { - let resp: ClaimsResponse = self - .app - .wrap() - .query_wasm_smart( - &self.junoswap_staking_contract, - &stake_cw20::msg::QueryMsg::Claims { address }, - ) - .unwrap(); - resp - } - - pub fn total_palomadex_lp(&mut self) -> u128 { - let cw20::TokenInfoResponse { total_supply, .. } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_token_contract, - &cw20::Cw20QueryMsg::TokenInfo {}, - ) - .unwrap(); - - total_supply.u128() - } - - pub fn palomadex_lp(&mut self, user: &str) -> u128 { - let cw20::BalanceResponse { balance } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_token_contract, - &cw20::Cw20QueryMsg::Balance { - address: user.to_string(), - }, - ) - .unwrap(); - - balance.u128() - } - - // for debugging tests - #[allow(dead_code)] - pub fn palomadex_lp_holders(&mut self) -> Vec<(String, u128)> { - let cw20::AllAccountsResponse { accounts } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_token_contract, - &cw20::Cw20QueryMsg::AllAccounts { - start_after: None, - limit: None, - }, - ) - .unwrap(); - accounts - .into_iter() - .map(|addr| (addr.clone(), self.palomadex_lp(&addr))) - .collect() - } - - pub fn total_palomadex_staked(&mut self) -> u128 { - let addr = self.palomadex_staking_contract.clone(); - self.palomadex_lp(addr.as_str()) - } - - pub fn palomadex_staked(&mut self, user: &str, unbonding_period: u64) -> u128 { - let palomadex_stake::msg::StakedResponse { stake, .. } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_staking_contract, - &palomadex_stake::msg::QueryMsg::Staked { - address: user.to_string(), - unbonding_period, - }, - ) - .unwrap(); - - stake.u128() - } -} diff --git a/contracts/junoswap-staking/src/state.rs b/contracts/junoswap-staking/src/state.rs deleted file mode 100644 index 804de3b..0000000 --- a/contracts/junoswap-staking/src/state.rs +++ /dev/null @@ -1,42 +0,0 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Uint128}; -use cw_storage_plus::Item; - -#[cw_serde] -pub struct MigrateConfig { - /// This is the address that can run ExecuteMsg::MigrateTokens - pub migrator: Addr, - /// This is how long it will be staked on PALOMA DEX - pub unbonding_period: u64, - - /// This is the junoswap pool where the LP will be withdrawn from - pub junoswap_pool: Addr, - - /// Can be deposited in any pool created by this factory - pub factory: Addr, - /// If set, only can be deposited in this pool (which must also be created by the factory) - pub palomadex_pool: Option, - - /// This is set when token migration is finished. - /// It is used to calculate the amount of LP tokens to give to each staker. - pub migrate_stakers_config: Option, -} - -/// The necessary information to migrate stakers. -#[cw_serde] -pub struct MigrateStakersConfig { - /// The palomadex LP token contract - pub lp_token: Addr, - /// The palomadex LP staking contract - pub staking_addr: Addr, - /// The total amount of palomadex LP tokens this contract received after token migration. - pub total_lp_tokens: Uint128, - /// The total amount of staked junoswap LP tokens. - pub total_staked: Uint128, -} - -/// Stores the contract configuration at the given key -pub const MIGRATION: Item = Item::new("migration"); - -/// This is set once MigrateTokens is called -pub const DESTINATION: Item = Item::new("destination"); diff --git a/contracts/lp-converter/src/contract.rs b/contracts/lp-converter/src/contract.rs index db351a0..9a1366d 100644 --- a/contracts/lp-converter/src/contract.rs +++ b/contracts/lp-converter/src/contract.rs @@ -1,7 +1,6 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult}; -use cw2::set_contract_version; use palomadex::lp_converter::ExecuteMsg; use wynd_lsd_hub::msg::{ ConfigResponse as HubConfigResponse, QueryMsg as HubQueryMsg, SupplyResponse, diff --git a/contracts/lp-converter/src/multitest/migrate_stake.rs b/contracts/lp-converter/src/multitest/migrate_stake.rs index 81a25f7..4bcc75d 100644 --- a/contracts/lp-converter/src/multitest/migrate_stake.rs +++ b/contracts/lp-converter/src/multitest/migrate_stake.rs @@ -1,5 +1,4 @@ -use palomadex::{asset::MINIMUM_LIQUIDITY_AMOUNT, stake::ConverterConfig}; -use palomadex_stake::msg::MigrateMsg; +use palomadex::asset::MINIMUM_LIQUIDITY_AMOUNT; use super::suite::{juno, uusd, Pair, SuiteBuilder, DAY}; @@ -72,75 +71,6 @@ fn migrate_to_existing_pool() { ); } -#[test] -fn migrate_converter_config() { - let user = "user"; - - let ujuno_amount = 1_000_000u128; - let uusd_amount = 1_000_000u128; - - let unbonding_period = 14 * DAY; - - let mut suite = SuiteBuilder::new() - .with_native_balances("ujuno", vec![(user, ujuno_amount)]) - .with_native_balances("uusd", vec![(user, uusd_amount)]) - .without_converter() - .build(); - - // provide some liquidity to the native pair - let native_lp = suite - .provide_liquidity(user, juno(ujuno_amount), uusd(uusd_amount)) - .unwrap(); - - // stake native LP - suite - .stake_lp(Pair::Native, user, native_lp, unbonding_period) - .unwrap(); - - // migrating the liquidity before the converter is set should fail - let err = suite - .migrate_stake(Pair::Native, user, native_lp, unbonding_period) - .unwrap_err(); - assert_eq!( - palomadex_stake::ContractError::NoConverter {}, - err.downcast().unwrap() - ); - - // migrate the staking contract to add the converter - suite - .migrate_staking_contract( - Pair::Native, - MigrateMsg { - unbonder: None, - converter: Some(ConverterConfig { - contract: suite.converter.to_string(), - pair_to: suite.lsd_pair.to_string(), - }), - unbond_all: false, - }, - ) - .unwrap(); - - // migrate liquidity to lsd pair - suite - .migrate_stake(Pair::Native, user, native_lp, unbonding_period) - .unwrap(); - - // check that the stake was migrated - let stake = suite - .query_stake(Pair::Native, user, unbonding_period) - .unwrap(); - assert_eq!(stake.stake.u128(), 0); - let stake = suite - .query_stake(Pair::Lsd, user, unbonding_period) - .unwrap(); - assert_eq!( - stake.stake.u128(), - ujuno_amount - 2 * MINIMUM_LIQUIDITY_AMOUNT.u128(), // 2x because we lp'd twice on empty pools - "all of the stake that was previously in native LP should now be migrated to lsd LP" - ); -} - #[test] fn partial_migration() { let user = "user"; diff --git a/contracts/lp-converter/src/multitest/suite.rs b/contracts/lp-converter/src/multitest/suite.rs index f5789ca..9a1e7db 100644 --- a/contracts/lp-converter/src/multitest/suite.rs +++ b/contracts/lp-converter/src/multitest/suite.rs @@ -121,11 +121,6 @@ impl SuiteBuilder { } } - pub fn without_converter(mut self) -> Self { - self.no_converter = true; - self - } - pub fn with_native_balances(mut self, denom: &str, balances: Vec<(&str, u128)>) -> Self { self.native_balances .extend(balances.into_iter().map(|(addr, amount)| { @@ -352,8 +347,6 @@ impl SuiteBuilder { Suite { app, - staking_code_id, - converter, factory, native_pair, @@ -369,7 +362,6 @@ impl SuiteBuilder { pub struct Suite { pub app: App, - staking_code_id: u64, pub converter: Addr, factory: Addr, pub native_pair: Addr, @@ -549,19 +541,6 @@ impl Suite { ) } - pub fn migrate_staking_contract( - &mut self, - pair: Pair, - msg: palomadex_stake::msg::MigrateMsg, - ) -> AnyResult { - self.app.migrate_contract( - Addr::unchecked("owner"), - pair.staking_addr(self), - &msg, - self.staking_code_id, // same code id - ) - } - pub fn query_stake( &self, pair: Pair, diff --git a/contracts/multi-hop/src/contract.rs b/contracts/multi-hop/src/contract.rs index a37dce7..aa67341 100644 --- a/contracts/multi-hop/src/contract.rs +++ b/contracts/multi-hop/src/contract.rs @@ -5,10 +5,9 @@ use cosmwasm_std::{ DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, WasmMsg, }; use cw20::{Cw20ExecuteMsg, Cw20ReceiveMsg}; -use cw_utils::ensure_from_older_version; use crate::msg::{ - ConfigResponse, Cw20HookMsg, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, + ConfigResponse, Cw20HookMsg, ExecuteMsg, InstantiateMsg, QueryMsg, SimulateSwapOperationsResponse, SwapOperation, MAX_SWAP_OPERATIONS, }; use palomadex::asset::{addr_opt_validate, Asset, AssetInfo, AssetInfoExt}; diff --git a/contracts/pair/src/testing.rs b/contracts/pair/src/testing.rs index 204917b..a9380b4 100644 --- a/contracts/pair/src/testing.rs +++ b/contracts/pair/src/testing.rs @@ -9,17 +9,15 @@ use cw_utils::MsgInstantiateContractResponse; use proptest::prelude::*; use cw20_base::msg::InstantiateMsg as TokenInstantiateMsg; -use palomadex::asset::{ - Asset, AssetInfo, AssetInfoValidated, AssetValidated, MINIMUM_LIQUIDITY_AMOUNT, -}; +use palomadex::asset::{Asset, AssetInfo, AssetInfoValidated, AssetValidated}; use palomadex::factory::PairType; use palomadex::fee_config::FeeConfig; use palomadex::oracle::{SamplePeriod, TwapResponse}; +use palomadex::pair::QueryMsg; use palomadex::pair::{ assert_max_spread, ContractError, Cw20HookMsg, ExecuteMsg, InstantiateMsg, PairInfo, PoolResponse, ReverseSimulationResponse, SimulationResponse, StakeConfig, TWAP_PRECISION, }; -use palomadex::pair::{MigrateMsg, QueryMsg}; use crate::contract::{ accumulate_prices, compute_swap, execute, instantiate, query_pool, query_reverse_simulation, @@ -132,294 +130,6 @@ fn proper_initialization() { ); } -// Rather long test the does a few things -// First for sanity, does a provide liquidity -// Then through migration marks the contract as frozen and assigns addr0000 as the circuit_breaker, the one who can unfreeze the contract and refreeze via an ExecuteMsg -// Then we try to provide liquidity again, which should fail -// We also try a native swap, a cw20 swap and an UpdateFees, all fails with ContractFrozen -// However, withdraw liquidity is not frozen and people can still withdraw -// We then try to unfreeze with addr0001, which should fail -// We then try to unfreeze with addr0000, which should succeed and to prove this we try to -// provide liquidity again and swap, which should both succeed -#[test] -fn test_freezing_a_pool_blocking_actions_then_unfreeze() { - let mut deps = mock_dependencies(&[Coin { - denom: "uusd".to_string(), - amount: Uint128::new(200_000000000000000000u128), - }]); - let offer_amount = Uint128::new(1500000000u128); - - deps.querier.with_token_balances(&[ - ( - &String::from("asset0000"), - &[(&String::from(MOCK_CONTRACT_ADDR), &Uint128::new(0))], - ), - ( - &String::from("liquidity0000"), - &[(&String::from(MOCK_CONTRACT_ADDR), &Uint128::new(0))], - ), - ]); - - let msg = InstantiateMsg { - asset_infos: vec![ - AssetInfo::Native("uusd".to_string()), - AssetInfo::Token("asset0000".to_string()), - ], - token_code_id: 10u64, - factory_addr: String::from("factory"), - init_params: None, - staking_config: default_stake_config(), - trading_starts: 0, - fee_config: FeeConfig { - total_fee_bps: 0, - protocol_fee_bps: 0, - }, - circuit_breaker: None, - }; - - let env = mock_env(); - let info = mock_info("addr0000", &[]); - // We can just call .unwrap() to assert this was a success - let _res = instantiate(deps.as_mut(), env, info, msg).unwrap(); - - // Store liquidity token - store_liquidity_token(deps.as_mut(), "liquidity0000".to_string()); - - // Successfully provide liquidity for the existing pool - let msg = ExecuteMsg::ProvideLiquidity { - assets: vec![ - Asset { - info: AssetInfo::Token("asset0000".to_string()), - amount: Uint128::from(100_000000000000000000u128), - }, - Asset { - info: AssetInfo::Native("uusd".to_string()), - amount: Uint128::from(100_000000000000000000u128), - }, - ], - slippage_tolerance: None, - receiver: None, - }; - - let env = mock_env(); - let info = mock_info( - "addr0000", - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(100_000000000000000000u128), - }], - ); - // Do one successful action before freezing just for sanity - execute(deps.as_mut(), env.clone(), info, msg).unwrap(); - - // Manually set the correct balances for the pool - deps.querier.with_balance(&[( - &String::from(MOCK_CONTRACT_ADDR), - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000000000000000000), - }], - )]); - deps.querier.with_token_balances(&[ - ( - &String::from("liquidity0000"), - &[ - (&String::from(MOCK_CONTRACT_ADDR), &MINIMUM_LIQUIDITY_AMOUNT), - ( - &String::from("addr0000"), - &(Uint128::new(100_000000000000000000) - MINIMUM_LIQUIDITY_AMOUNT), - ), - ], - ), - ( - &String::from("asset0000"), - &[( - &String::from(MOCK_CONTRACT_ADDR), - &Uint128::new(100_000000000000000000), - )], - ), - ]); - - // Failing Execute Actions due to frozen - - // This should now fail, its a good TX with all the normal setup done but because of freezing it should fail - let msg = ExecuteMsg::ProvideLiquidity { - assets: vec![ - Asset { - info: AssetInfo::Token("asset0000".to_string()), - amount: Uint128::from(100_000000000000000000u128), - }, - Asset { - info: AssetInfo::Native("uusd".to_string()), - amount: Uint128::from(200_000000000000000000u128), - }, - ], - slippage_tolerance: Some(Decimal::percent(50)), - receiver: None, - }; - - let env = mock_env_with_block_time(env.block.time.seconds() + 1000); - let info = mock_info( - "addr0000", - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(200_000000000000000000u128), - }], - ); - - // Assert an error and that its frozen - let res: ContractError = execute(deps.as_mut(), env.clone(), info, msg).unwrap_err(); - assert_eq!(res, ContractError::ContractFrozen {}); - // Also do a swap, which should also fail - let msg = ExecuteMsg::Swap { - offer_asset: Asset { - info: AssetInfo::Native("uusd".to_string()), - amount: 1_000u128.into(), - }, - to: None, - max_spread: None, - belief_price: None, - ask_asset_info: None, - referral_address: None, - referral_commission: None, - }; - - let info = mock_info( - "addr0000", - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(1000u128), - }], - ); - // Assert an error and that its frozen - let res: ContractError = execute(deps.as_mut(), env.clone(), info.clone(), msg).unwrap_err(); - assert_eq!(res, ContractError::ContractFrozen {}); - - let msg = ExecuteMsg::UpdateFees { - fee_config: FeeConfig { - total_fee_bps: 5, - protocol_fee_bps: 5, - }, - }; - let res = execute(deps.as_mut(), env.clone(), info, msg).unwrap_err(); - assert_eq!(res, ContractError::ContractFrozen {}); - - // Normal sell but with CW20 - let msg = ExecuteMsg::Receive(Cw20ReceiveMsg { - sender: String::from("addr0000"), - amount: offer_amount, - msg: to_binary(&Cw20HookMsg::Swap { - ask_asset_info: None, - belief_price: None, - max_spread: Some(Decimal::percent(50)), - to: None, - referral_address: None, - referral_commission: None, - }) - .unwrap(), - }); - let info = mock_info("asset0000", &[]); - - let res = execute(deps.as_mut(), env.clone(), info, msg).unwrap_err(); - assert_eq!(res, ContractError::ContractFrozen {}); - - // But we can withdraw liquidity - - // Withdraw liquidity - let msg = ExecuteMsg::Receive(Cw20ReceiveMsg { - sender: String::from("addr0000"), - msg: to_binary(&Cw20HookMsg::WithdrawLiquidity { assets: vec![] }).unwrap(), - amount: Uint128::new(100u128), - }); - - let info = mock_info("liquidity0000", &[]); - // We just want to ensure it doesn't fail with a ContractFrozen error - execute(deps.as_mut(), env.clone(), info, msg).unwrap(); - - // Unfreeze the pool again using the Freeze message rather than another migrate - let msg = ExecuteMsg::Freeze { frozen: false }; - // First try a failing case with addr0001 - let info = mock_info("addr0001", &[]); - // Rather than being unfrozen it returns unauthorized as addr0000 is the only addr that can currently call Freeze unless another migration changes that - let err = execute(deps.as_mut(), env.clone(), info, msg.clone()).unwrap_err(); - assert_eq!(err, ContractError::Unauthorized {}); - // But the assigned circuit_breaker address can do an unfreeze with the ExecuteMsg variant - let info = mock_info("addr0000", &[]); - // And it works - execute(deps.as_mut(), env.clone(), info, msg).unwrap(); - - // Testing actions working again after unfreeze - - // Initialize token balance to 1:1 - deps.querier.with_balance(&[( - &String::from(MOCK_CONTRACT_ADDR), - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::new(100_000000000000000000 + 99_000000000000000000 /* user deposit must be pre-applied */), - }], - )]); - - deps.querier.with_token_balances(&[ - ( - &String::from("liquidity0000"), - &[( - &String::from(MOCK_CONTRACT_ADDR), - &Uint128::new(100_000000000000000000), - )], - ), - ( - &String::from("asset0000"), - &[( - &String::from(MOCK_CONTRACT_ADDR), - &Uint128::new(100_000000000000000000), - )], - ), - ]); - - // Successfully provides liquidity - let msg = ExecuteMsg::ProvideLiquidity { - assets: vec![ - Asset { - info: AssetInfo::Token("asset0000".to_string()), - amount: Uint128::from(100_000000000000000000u128), - }, - Asset { - info: AssetInfo::Native("uusd".to_string()), - amount: Uint128::from(99_000000000000000000u128), - }, - ], - slippage_tolerance: Some(Decimal::percent(1)), - receiver: None, - }; - - let info = mock_info( - "addr0001", - &[Coin { - denom: "uusd".to_string(), - amount: Uint128::from(99_000000000000000000u128), - }], - ); - execute(deps.as_mut(), env.clone(), info, msg).unwrap(); - - // Normal sell but with CW20 - let msg = ExecuteMsg::Receive(Cw20ReceiveMsg { - sender: String::from("addr0000"), - amount: offer_amount, - msg: to_binary(&Cw20HookMsg::Swap { - ask_asset_info: None, - belief_price: None, - max_spread: Some(Decimal::percent(50)), - to: None, - referral_address: None, - referral_commission: None, - }) - .unwrap(), - }); - let info = mock_info("asset0000", &[]); - - execute(deps.as_mut(), env, info, msg).unwrap(); -} - #[test] fn provide_liquidity() { let mut deps = mock_dependencies(&[Coin { diff --git a/contracts/raw-migration/.cargo/config b/contracts/raw-migration/.cargo/config deleted file mode 100644 index de2d36a..0000000 --- a/contracts/raw-migration/.cargo/config +++ /dev/null @@ -1,5 +0,0 @@ -[alias] -wasm = "build --release --lib --target wasm32-unknown-unknown" -wasm-debug = "build --lib --target wasm32-unknown-unknown" -unit-test = "test --lib" -schema = "run --bin schema" diff --git a/contracts/raw-migration/Cargo.toml b/contracts/raw-migration/Cargo.toml deleted file mode 100644 index e003a0b..0000000 --- a/contracts/raw-migration/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -name = "raw-migration" -authors = ["Volume Fi"] -version = { workspace = true } -edition = { workspace = true } -description = "Contract aimed just for migration - take JunoSwap RAW paired tokens and swap them to PALOMA" -license = { workspace = true } -repository = { workspace = true } -homepage = "https://www.palomachain.com" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -# for more explicit tests, cargo test --features=backtraces -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all instantiate/execute/query exports -library = [] - -[dependencies] -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw-storage-plus = { workspace = true } -cw2 = { workspace = true } -cw20 = { workspace = true } -cw-utils = { workspace = true } -thiserror = { workspace = true } - -palomadex = { workspace = true } -palomadex-factory = { workspace = true } -palomadex-stake = { workspace = true } - -# this is old version of cw20 used by wasmswap -wasmswap_cw20 = { package = "cw20", version = "0.10.0" } -# this is the staking contract we are migrating from (use the state variables there) -stake-cw20 = { git="https://github.com/DA0-DA0/dao-contracts", tag="v0.3.0" } -# this is the pool contract we will withdraw from -wasmswap = { git="https://github.com/Wasmswap/wasmswap-contracts", tag="v1.1.2-beta" } - -[dev-dependencies] -anyhow = { workspace = true } -cw20-base = { workspace = true } -cw-multi-test = { workspace = true } -serde = { workspace = true } -wasmswap_cw20-base = { package = "cw20-base", version = "0.10.0" } -wasmswap_cw-utils = { package = "cw-utils", version = "0.11" } -palomadex-factory = { workspace = true } -palomadex-pair = { workspace = true } diff --git a/contracts/raw-migration/README.md b/contracts/raw-migration/README.md deleted file mode 100644 index cf65945..0000000 --- a/contracts/raw-migration/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# JunoSwap RAW Staking Migration - -This contract is intended as a migration target for an existing JunoSwap staking contract -that are configure for RAW pools. -Upon migration it will prepare for a future transfer (we don't know the exact pool address, -as we want to perform the migration proposal concurrently with the pool deployment proposal). - -Once it is migrated, the staking contract will be locked, and the only action is that -a nominated migrator account can trigger the transfer - all RAW tokens will be burned, and in its place -Grain tokens will be staked using predefined exchange rate from configuration. -We add some constraints to ensure this is transferred to a valid target contract -to minimize any trust requirements on the migrator (they just have "censorship" power). - diff --git a/contracts/raw-migration/src/bin/schema.rs b/contracts/raw-migration/src/bin/schema.rs deleted file mode 100644 index 33b4f1a..0000000 --- a/contracts/raw-migration/src/bin/schema.rs +++ /dev/null @@ -1,12 +0,0 @@ -use cosmwasm_schema::write_api; -use cosmwasm_std::Empty; -use raw_migration::msg::{ExecuteMsg, MigrateMsg, QueryMsg}; - -fn main() { - write_api! { - instantiate: Empty, - query: QueryMsg, - execute: ExecuteMsg, - migrate: MigrateMsg, - } -} diff --git a/contracts/raw-migration/src/contract.rs b/contracts/raw-migration/src/contract.rs deleted file mode 100644 index f479f62..0000000 --- a/contracts/raw-migration/src/contract.rs +++ /dev/null @@ -1,413 +0,0 @@ -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; -use cosmwasm_std::{ - coin, ensure_eq, to_binary, Addr, Binary, Coin, Deps, DepsMut, Empty, Env, MessageInfo, Order, - Reply, Response, StdResult, SubMsg, Uint128, WasmMsg, -}; - -use cw20::Cw20ExecuteMsg; -use palomadex::asset::{Asset, AssetInfo}; -use wasmswap::msg::InfoResponse; - -use crate::error::ContractError; -use crate::msg::{ExecuteMsg, QueryMsg}; -use crate::state::{MigrateStakersConfig, DESTINATION, EXCHANGE_CONFIG, MIGRATION}; - -// this is the contract we are migrating from -pub const STAKE_CW20_NAME: &str = "crates.io:stake_cw20"; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: Empty, -) -> Result { - Err(ContractError::NotImplemented) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> Result { - match msg { - QueryMsg::MigrationFinished {} => { - let no_stakers = stake_cw20::state::STAKED_BALANCES - .keys(_deps.storage, None, None, Order::Ascending) - .next() - .is_none(); - Ok(to_binary(&no_stakers)?) - } - } -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: ExecuteMsg, -) -> Result { - match msg { - ExecuteMsg::MigrateTokens { palomadex_pool } => migrate_tokens(deps, env, info, palomadex_pool), - ExecuteMsg::MigrateStakers { limit } => migrate_stakers(deps, env, info, limit), - } -} - -/// Allow `migrator` to pull out LP positions and send them to paloma dex pool -/// First step figures out how many LPs we have and withdraws them. -/// Follow up via reply. -pub fn migrate_tokens( - deps: DepsMut, - env: Env, - info: MessageInfo, - palomadex_pool: String, -) -> Result { - // make sure called by proper account - let mut migration = MIGRATION.load(deps.storage)?; - if info.sender != migration.migrator { - return Err(ContractError::Unauthorized); - } - - // ensure the requested target pool is valid - let w_pool = deps.api.addr_validate(&palomadex_pool)?; - if let Some(ref target) = migration.palomadex_pool { - if target != w_pool { - return Err(ContractError::InvalidDestination(palomadex_pool)); - } - } - let ci = deps.querier.query_wasm_contract_info(&w_pool)?; - if ci.creator != migration.factory { - return Err(ContractError::InvalidDestination(palomadex_pool)); - } - - // save target pool for later reply block - DESTINATION.save(deps.storage, &w_pool)?; - - // calculate LP tokens owner by staking contract, - // for withdrawal and for future distribution - let stake_cfg = stake_cw20::state::CONFIG.load(deps.storage)?; - let token = cw20::Cw20Contract(stake_cfg.token_address); - let balance = token.balance(&deps.querier, env.contract.address)?; - - // fill in most of the migration data now (minus paloma dex LP) - let palomadex::pair::PairInfo { - liquidity_token, - staking_addr, - .. - } = deps - .querier - .query_wasm_smart(&w_pool, &palomadex::pair::QueryMsg::Pair {})?; - - // total_staked is same a balance of junoswap lp token held by this contract - migration.migrate_stakers_config = Some(MigrateStakersConfig { - lp_token: liquidity_token, - staking_addr, - total_lp_tokens: Uint128::zero(), - total_staked: balance, - }); - MIGRATION.save(deps.storage, &migration)?; - - // trigger withdrawal of LP tokens - // we need to assign a cw20 allowance to let the pool burn LP - let allowance = WasmMsg::Execute { - contract_addr: token.0.to_string(), - funds: vec![], - msg: to_binary(&cw20::Cw20ExecuteMsg::IncreaseAllowance { - spender: migration.junoswap_pool.to_string(), - amount: balance, - expires: None, - })?, - }; - - // then craft the LP withdrawal message - let withdraw = WasmMsg::Execute { - contract_addr: migration.junoswap_pool.into_string(), - funds: vec![], - msg: to_binary(&wasmswap::msg::ExecuteMsg::RemoveLiquidity { - amount: balance, - min_token1: Uint128::zero(), - min_token2: Uint128::zero(), - expiration: None, - })?, - }; - - // execute these and handle the next step in reply - let res = Response::new() - .add_message(allowance) - .add_submessage(SubMsg::reply_on_success(withdraw, REPLY_ONE)); - Ok(res) -} - -pub fn migrate_stakers( - mut deps: DepsMut, - env: Env, - info: MessageInfo, - limit: u32, -) -> Result { - // make sure called by proper account - let migration = MIGRATION.load(deps.storage)?; - ensure_eq!(info.sender, migration.migrator, ContractError::Unauthorized); - - let config = migration - .migrate_stakers_config - .ok_or(ContractError::TokensNotMigrated)?; - - // calculate next `limit` stakers and their shares - let stakers = find_stakers(deps.as_ref(), limit)?; - - // remove the processed stakers from the state - remove_stakers(deps.branch(), &env, stakers.iter().map(|(addr, _)| addr))?; - - let staker_lps: Vec<_> = stakers - .into_iter() - .map(|(addr, stake)| { - ( - addr.to_string(), - stake * config.total_lp_tokens / config.total_staked, - ) - }) - .filter(|(_, x)| !x.is_zero()) - .collect(); - - // the amount of LP tokens we are migrating in this message - let batch_lp: Uint128 = staker_lps.iter().map(|(_, x)| x).sum(); - - // bonding has full info on who receives the delegation - let bond_msg = palomadex::stake::ReceiveMsg::MassDelegate { - unbonding_period: migration.unbonding_period, - delegate_to: staker_lps, - }; - - // stake it all - let stake_msg = WasmMsg::Execute { - contract_addr: config.lp_token.to_string(), - funds: vec![], - msg: to_binary(&cw20::Cw20ExecuteMsg::Send { - contract: config.staking_addr.into_string(), - amount: batch_lp, - msg: to_binary(&bond_msg)?, - })?, - }; - - Ok(Response::new().add_message(stake_msg)) -} - -const REPLY_ONE: u64 = 111; -const REPLY_TWO: u64 = 222; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { - if msg.result.is_err() { - return Err(ContractError::ErrorReply); - } - match msg.id { - REPLY_ONE => reply_one(deps, env), - REPLY_TWO => reply_two(deps, env), - x => Err(ContractError::UnknownReply(x)), - } -} - -/// In this step, we deposit the new raw tokens (eg. JUNO-ATOM) into PALOMA DEX -/// And get some liquid PALOMA DEX LP tokens -pub fn reply_one(deps: DepsMut, env: Env) -> Result { - let migration = MIGRATION.load(deps.storage)?; - let destination = DESTINATION.load(deps.storage)?; - - // get the JS asset types and convert to PALOMA DEX types - let info: InfoResponse = deps - .querier - .query_wasm_smart(migration.junoswap_pool, &wasmswap::msg::QueryMsg::Info {})?; - let assets = to_palomadex_assets(deps.as_ref(), env.contract.address, info)?; - - // figure out how to transfer these... previous cw20 allowances or - // sending native funds inline with providing liquidity - let DenomDeposits { - allowances, - funds, - new_assets, - } = prepare_denom_deposits(deps.as_ref(), &destination, &assets)?; - let deposit = WasmMsg::Execute { - contract_addr: destination.into_string(), - funds, - msg: to_binary(&palomadex::pair::ExecuteMsg::ProvideLiquidity { - assets: new_assets, - // TODO: set some value here? - slippage_tolerance: None, - receiver: None, - })?, - }; - - // add any cw20 allowances, then call to deposit the tokens and get LP - let res = Response::new() - .add_messages(allowances) - .add_submessage(SubMsg::reply_on_success(deposit, REPLY_TWO)); - Ok(res) -} - -struct DenomDeposits { - allowances: Vec, - funds: Vec, - new_assets: Vec, -} - -/// Checks if one of the denoms matches RAW address, then prepares extra BurnMsg -/// and provides PALOMA equivalent given by specified exchange rate -fn prepare_denom_deposits( - deps: Deps, - destination: &Addr, - assets: &[Asset], -) -> Result { - let mut allowances = vec![]; - let mut funds = vec![]; - - let exchange_config = EXCHANGE_CONFIG.load(deps.storage)?; - - let raw_asset = AssetInfo::Token(exchange_config.raw_token.to_string()); - let new_assets = assets - .iter() - .map(|asset| { - if asset.info == raw_asset { - // first burn raw tokens - let burn_msg = WasmMsg::Execute { - contract_addr: exchange_config.raw_token.to_string(), - msg: to_binary(&Cw20ExecuteMsg::Burn { - amount: asset.amount, - })?, - funds: vec![], - }; - // add BurnMsg to messages - allowances.push(burn_msg); - // now return grain tokens instead - Ok(Asset { - info: AssetInfo::Token(exchange_config.grain_token.to_string()), - amount: asset.amount * exchange_config.raw_to_grain_exchange_rate, - }) - } else { - Ok(asset.clone()) - } - }) - .collect::>>()?; - - // sanity check - debug_assert_eq!(new_assets.len(), 2); - - prepare_denom_deposit(destination, &new_assets[0], &mut allowances, &mut funds)?; - prepare_denom_deposit(destination, &new_assets[1], &mut allowances, &mut funds)?; - - Ok(DenomDeposits { - allowances, - funds, - new_assets, - }) -} - -fn prepare_denom_deposit( - destination: &Addr, - asset: &Asset, - msgs: &mut Vec, - funds: &mut Vec, -) -> Result<(), ContractError> { - // build allowance msg or funds to transfer for this asset - match &asset.info { - AssetInfo::Token(token) => { - let embed = cw20::Cw20ExecuteMsg::IncreaseAllowance { - spender: destination.to_string(), - amount: asset.amount, - expires: None, - }; - let msg = WasmMsg::Execute { - contract_addr: token.to_string(), - msg: to_binary(&embed)?, - funds: vec![], - }; - msgs.push(msg); - } - AssetInfo::Native(denom) => { - let coin = coin(asset.amount.u128(), denom); - funds.push(coin); - } - } - Ok(()) -} - -fn to_palomadex_assets( - deps: Deps, - me: Addr, - info: InfoResponse, -) -> Result, ContractError> { - let asset1 = to_palomadex_asset(deps, &me, info.token1_denom)?; - let asset2 = to_palomadex_asset(deps, &me, info.token2_denom)?; - Ok(vec![asset1, asset2]) -} - -fn to_palomadex_asset( - deps: Deps, - me: &Addr, - token: wasmswap_cw20::Denom, -) -> Result { - let asset = match token { - wasmswap_cw20::Denom::Native(denom) => { - let balance = deps.querier.query_balance(me, denom)?; - Asset { - info: AssetInfo::Native(balance.denom), - amount: balance.amount, - } - } - wasmswap_cw20::Denom::Cw20(addr) => { - let token = cw20::Cw20Contract(addr); - let amount = token.balance(&deps.querier, me)?; - Asset { - info: AssetInfo::Token(token.0.into_string()), - amount, - } - } - }; - Ok(asset) -} - -/// Finally, with those PALOMA DEX LP tokens, we will take them all on behalf -/// of the original JunoSwap LP stakers. -pub fn reply_two(deps: DepsMut, env: Env) -> Result { - // load config for LP token and staking contract - let mut migration = MIGRATION.load(deps.storage)?; - let config = migration.migrate_stakers_config.as_mut().unwrap(); - - // how many LP do we have total - let lp_token = cw20::Cw20Contract(config.lp_token.clone()); - let total_lp_tokens = lp_token.balance(&deps.querier, env.contract.address)?; - - // store this for `migrate_stakers` to use - config.total_lp_tokens = total_lp_tokens; - MIGRATION.save(deps.storage, &migration)?; - - Ok(Response::new()) -} - -// query logic taken from https://github.com/cosmorama/wyndex-priv/pull/109 -fn find_stakers(deps: Deps, limit: impl Into>) -> StdResult> { - let balances = stake_cw20::state::STAKED_BALANCES - .range(deps.storage, None, None, Order::Ascending) - .map(|stake| { - let (addr, amount) = stake?; - - // query all pending claims and bond them as well - let claims = stake_cw20::state::CLAIMS.query_claims(deps, &addr)?; - let claims_sum = claims.claims.iter().map(|c| c.amount).sum::(); - - Ok((addr, amount + claims_sum)) - }); - match limit.into() { - Some(limit) => balances.take(limit as usize).collect(), - None => balances.collect(), - } -} - -fn remove_stakers<'a>( - deps: DepsMut, - env: &Env, - stakers: impl Iterator, -) -> Result<(), ContractError> { - for staker in stakers { - stake_cw20::state::STAKED_BALANCES.remove(deps.storage, staker, env.block.height)?; - } - Ok(()) -} diff --git a/contracts/raw-migration/src/error.rs b/contracts/raw-migration/src/error.rs deleted file mode 100644 index b91d5dc..0000000 --- a/contracts/raw-migration/src/error.rs +++ /dev/null @@ -1,32 +0,0 @@ -use cosmwasm_std::StdError; -use thiserror::Error; - -#[derive(Debug, Error, PartialEq)] -pub enum ContractError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("Unauthorized")] - Unauthorized, - - #[error("Tokens have to be migrated before stakers")] - TokensNotMigrated, - - #[error("{0} isn't an authorized pool to withdraw into")] - InvalidDestination(String), - - #[error("Method not implemented - only intended for migration")] - NotImplemented, - - #[error("Cannot migrate contract type: `{0}`. Only works for wasmswap staking")] - CannotMigrate(String), - - #[error("Got reply with unknown ID: {0}")] - UnknownReply(u64), - - #[error("Target factory doesn't have unbonding period: {0}")] - InvalidUnbondingPeriod(u64), - - #[error("Got reply with error, only handle success case")] - ErrorReply, -} diff --git a/contracts/raw-migration/src/junoswap.rs b/contracts/raw-migration/src/junoswap.rs deleted file mode 100644 index a239263..0000000 --- a/contracts/raw-migration/src/junoswap.rs +++ /dev/null @@ -1,2 +0,0 @@ -// This is state and message definitions copied from the junoswap contracts we migrate from - diff --git a/contracts/raw-migration/src/lib.rs b/contracts/raw-migration/src/lib.rs deleted file mode 100644 index a3d2c2f..0000000 --- a/contracts/raw-migration/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -pub mod contract; -mod error; -pub mod msg; -pub mod state; - -#[cfg(test)] -mod multitest; - -pub use error::ContractError; - -// #[cfg(test)] -// mod multitest; diff --git a/contracts/raw-migration/src/msg.rs b/contracts/raw-migration/src/msg.rs deleted file mode 100644 index a5e9e38..0000000 --- a/contracts/raw-migration/src/msg.rs +++ /dev/null @@ -1,60 +0,0 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::Decimal; - -#[cw_serde] -pub struct InstantiateMsg {} - -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - /// Checks whether all stakers have been migrated - #[returns(bool)] - MigrationFinished {}, -} - -/// For existing contract, we need to specify which pool it can be withdrawn into -#[cw_serde] -pub struct MigrateMsg { - /// This must be Some the first migration (from JunoSwap contracts). - /// This must be None if upgrading from raw-migration to raw-migration - pub init: Option, -} - -/// For existing contract, we need to specify which pool it can be withdrawn into -#[cw_serde] -pub struct OrigMigrateMsg { - /// This is the address that can run ExecuteMsg::MigrateTokens - pub migrator: String, - /// This is how long it will be staked on PALOMA DEX - pub unbonding_period: u64, - - /// This is the junoswap pool where the LP will be withdrawn from - pub junoswap_pool: String, - - /// Can be deposited in any pool created by this factory - pub factory: String, - /// If set, only can be deposited in this pool (which must also be created by the factory) - pub palomadex_pool: Option, - // Multiplier applied on amount of RAW to get Grain tokens. - // Example: - // exchange_rate = 1.5 - // 10 RAW * exchange_rate = 15 PALOMA - pub raw_to_grain_exchange_rate: Decimal, - // Address of cw20 RAW token - pub raw_address: String, - // Address of cw20 Grain token - pub grain_address: String, -} - -#[cw_serde] -pub enum ExecuteMsg { - /// Migrate tokens to this pool. - /// This moves the LP tokens to this contract, which are later given to the stakers in `MigrateStakers`. - /// Must be called by migrator. - /// Target pool must match constraints above - MigrateTokens { palomadex_pool: String }, - - /// Give the next `limit` stakers their LP tokens. - /// Must be called by migrator. - MigrateStakers { limit: u32 }, -} diff --git a/contracts/raw-migration/src/multitest.rs b/contracts/raw-migration/src/multitest.rs deleted file mode 100644 index c5348f3..0000000 --- a/contracts/raw-migration/src/multitest.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod migration; -mod suite; diff --git a/contracts/raw-migration/src/multitest/migration.rs b/contracts/raw-migration/src/multitest/migration.rs deleted file mode 100644 index 63eb70b..0000000 --- a/contracts/raw-migration/src/multitest/migration.rs +++ /dev/null @@ -1,430 +0,0 @@ -use super::suite::SuiteBuilder; -use crate::{multitest::suite::PoolDenom, ContractError}; - -use palomadex::asset::{AssetInfoValidated, AssetValidated}; - -use wasmswap_cw20::Denom; - -use cosmwasm_std::{assert_approx_eq, coin, Addr, Coin, Decimal, Uint128}; - -#[test] -fn migrate_raw_with_native() { - let ujuno = "ujuno"; - let raw = "RAW"; - let users = ["user", "user2", "user3"]; - // Setup Pools with initial liquidity - let liquidity = vec![coin(3_000_000, ujuno)]; - let liquidity_cw20 = 3_000_002u128; - - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Native(ujuno.to_owned()), - PoolDenom::Cw20(raw.to_owned()), - ) - .build(); - - let raw_denom = suite.pool_denom2.clone(); - let raw_address = match &raw_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - - let grain_token = suite.grain_cw20_token.clone(); - - // mint PALOMA tokens for migration contract - let junoswap_staking_contract = suite.junoswap_staking_contract.to_string(); - suite - .mint_cw20( - "owner", - &grain_token, - 5_000_000u128, - &junoswap_staking_contract, - ) - .unwrap(); - - // Provide Liquidity to the CW20 Native pair - // Note: Second deposits need 1 extra cw20 similar to the above rounding errors - suite - .provide_liquidity_to_junoswap_pool( - users[0], - 1_000_000u128, - 1_000_000u128, - Some(Denom::Native(ujuno.to_owned())), - Some(raw_denom.clone()), - vec![coin(1_000_000, ujuno)], - ) - .unwrap(); - - suite - .provide_liquidity_to_junoswap_pool( - users[1], - 1_000_000u128, - 1_000_001u128, - Some(Denom::Native(ujuno.to_owned())), - Some(raw_denom.clone()), - vec![coin(1_000_000, ujuno)], - ) - .unwrap(); - suite - .provide_liquidity_to_junoswap_pool( - users[2], - 1_000_000u128, - 1_000_001u128, - Some(Denom::Native(ujuno.to_owned())), - Some(raw_denom.clone()), - vec![coin(1_000_000, ujuno)], - ) - .unwrap(); - - // check balances of pool - let junoswap = suite - .app - .wrap() - .query_all_balances(&suite.junoswap_pool_contract) - .unwrap(); - assert_eq!(junoswap, liquidity); - let junoswap = cw20::Cw20Contract(raw_address.clone()) - .balance(&suite.app.wrap(), suite.junoswap_pool_contract.clone()) - .unwrap(); - assert_eq!(junoswap.u128(), liquidity_cw20); - - suite.palomadex_lp_holders(); - - // stake some of these tokens - 80% of liquidity should be moved - // users[0] will keep everything staked - let to_stake = suite.junoswap_lp(users[0], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - users[0], - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - // users[1] will unstake half - let to_stake = suite.junoswap_lp(users[1], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - users[1], - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - suite - .unstake_junoswap_lp( - users[1], - to_stake / Uint128::new(2), - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - // users[2] will unstake all - let to_stake = suite.junoswap_lp(users[2], None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - users[2], - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - suite - .unstake_junoswap_lp( - users[2], - to_stake, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - - // perform the migration of liquidity - let raw_to_grain_exchange_rate = Decimal::percent(200); - suite - .migrate_to_palomadex( - None, - None, - None, - raw_to_grain_exchange_rate, - raw_address.clone(), - ) - .unwrap(); - - // 80% of native liquidity moved to palomadex pool - let palomadex = suite - .app - .wrap() - .query_all_balances(&suite.palomadex_pair_contract) - .unwrap(); - let expected = liquidity - .iter() - .map(|Coin { amount, denom }| coin(amount.u128() * 4 / 5, denom)) - .collect::>(); - assert_eq!(palomadex, expected); - - // 80% of cw20 liquidity moved to palomadex pool - // RAW token is now GONE, it was swapped in prepare_denom_deposits at a rate of 200% (set above) - // Check the balance of PALOMA token instead, it should have been swapped at a 2-1 rate (200%) - let palomadex = cw20::Cw20Contract(grain_token.clone()) - .balance(&suite.app.wrap(), suite.palomadex_pair_contract.clone()) - .unwrap(); - let expected = liquidity_cw20 * 4 / 5; - assert_eq!(palomadex.u128(), expected * 2); - - // ensure all lp belong to the staking contract - let palomadex_total = suite.total_palomadex_lp(); - let palomadex_staked = suite.total_palomadex_staked(); - assert_approx_eq!(palomadex_total, palomadex_staked, "0.001"); - // ensure all staked tokens belong to the migrated user - let user_staked = suite.palomadex_staked(users[0], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 3); - // user 2 staked 500k so they should have about 10% of the staked tokens - let user_staked = suite.palomadex_staked(users[1], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 3); - // user 3 did 3m and should have 60% - let user_staked = suite.palomadex_staked(users[2], suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked / 3); - - // now to the meat - check assets of the pool and balance - // verify amounts here, for cw20 its 3mil * 2 (exchange rate) * 4/5 (80% of liquidity was moved) = 4.8M - // for native, just the 3 mil * 4/5 (80% of liquidity was moved) = 2.4M - let pool_info = suite.query_palomadex_pool(); - assert_eq!( - pool_info.assets, - vec![ - AssetValidated { - info: AssetInfoValidated::Native(ujuno.to_string()), - amount: Uint128::new(2_400_000) - }, - AssetValidated { - info: AssetInfoValidated::Token(grain_token.clone()), - amount: Uint128::new(4_800_002) - } - ] - ); -} - -#[test] -fn non_migrator_cant_migrate() { - let user = "user"; - - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Cw20("raw".to_owned()), - PoolDenom::Cw20("cwt".to_owned()), - ) - .build(); - - let raw_denom = suite.pool_denom1.clone(); - let raw_address = match &raw_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - let cw20_denom = suite.pool_denom2.clone(); - let grain_token = suite.grain_cw20_token.clone(); - - // mint PALOMA tokens for migration contract - let junoswap_staking_contract = suite.junoswap_staking_contract.to_string(); - suite - .mint_cw20( - "owner", - &grain_token, - 5_000_000u128, - &junoswap_staking_contract, - ) - .unwrap(); - - // Provide Liquidity to the CW20 pair - suite - .provide_liquidity_to_junoswap_pool( - user, - 2_000_000u128, - 2_000_000u128, - Some(cw20_denom), - Some(raw_denom.clone()), - vec![], - ) - .unwrap(); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - - // this won't work, not the migrator - let err = suite - .migrate_to_palomadex( - Some(Addr::unchecked("notthemigrator")), - None, - None, - Decimal::percent(100), - raw_address.clone(), - ) - .unwrap_err(); - assert_eq!(ContractError::Unauthorized {}, err.downcast().unwrap()) -} -#[test] -fn migrator_cant_migrate_to_own_addr() { - let user = "user"; - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Cw20("cwt".to_owned()), - PoolDenom::Cw20("raw".to_owned()), - ) - .build(); - - let raw_denom = suite.pool_denom1.clone(); - let cw20_denom = suite.pool_denom2.clone(); - let raw_address = match &cw20_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - let grain_token = suite.grain_cw20_token.clone(); - - // mint PALOMA tokens for migration contract - let junoswap_staking_contract = suite.junoswap_staking_contract.to_string(); - suite - .mint_cw20( - "owner", - &grain_token, - 5_000_000u128, - &junoswap_staking_contract, - ) - .unwrap(); - - // Provide Liquidity to the CW20 pair - suite - .provide_liquidity_to_junoswap_pool( - user, - 2_000_000u128, - 2_000_000u128, - Some(cw20_denom.clone()), - Some(raw_denom), - vec![], - ) - .unwrap(); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite.stake_junoswap_lp(user, to_stake, None, None).unwrap(); - - // this won't work, we can only migrate to a deployed pool contract. - let err = suite - .migrate_to_palomadex( - Some(Addr::unchecked("owner")), - Some(suite.palomadex_pair_contract.clone()), - Some(Addr::unchecked("owner")), - Decimal::percent(100), - raw_address.clone(), - ) - .unwrap_err(); - - assert_eq!( - ContractError::InvalidDestination("owner".to_string()), - err.downcast().unwrap() - ); -} - -#[test] -fn migration_two_cw20() { - let user = "user"; - let liquidity = 2_000_000u128; - - let mut suite = SuiteBuilder::new() - .with_denoms( - PoolDenom::Cw20("cwt".to_owned()), - PoolDenom::Cw20("raw".to_owned()), - ) - .build(); - - let cw20_denom = suite.pool_denom1.clone(); - let cw20_address = match &cw20_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - let raw_denom = suite.pool_denom2.clone(); - let raw_address = match &raw_denom { - Denom::Cw20(address) => address, - _ => panic!("expected cw20 denom"), - }; - let grain_token = suite.grain_cw20_token.clone(); - - // mint PALOMA tokens for migration contract - let junoswap_staking_contract = suite.junoswap_staking_contract.to_string(); - suite - .mint_cw20( - "owner", - &grain_token, - 5_000_000u128, - &junoswap_staking_contract, - ) - .unwrap(); - - // Provide Liquidity to the CW20 pair - suite - .provide_liquidity_to_junoswap_pool( - user, - 2_000_000u128, - 2_000_000u128, - Some(cw20_denom.clone()), - Some(raw_denom.clone()), - vec![], - ) - .unwrap(); - - // stake some of these tokens - 80% of liquidity should be moved - let to_stake = suite.junoswap_lp(user, None).unwrap() * Decimal::percent(80); - suite - .stake_junoswap_lp( - user, - to_stake, - None, - Some(&suite.junoswap_staking_contract.clone()), - ) - .unwrap(); - - // make sure no lp before the deposit - let palomadex_total = suite.total_palomadex_lp(); - assert_eq!(palomadex_total, 0u128); - - // perform the migration of liquidity - let raw_to_grain_exchange_rate = Decimal::percent(200); - suite - .migrate_to_palomadex( - None, - None, - None, - raw_to_grain_exchange_rate, - raw_address.clone(), - ) - .unwrap(); - // 80% of liquidity moved to palomadex pool - let cw20_token_liquidity = cw20::Cw20Contract(cw20_address.clone()) - .balance(&suite.app.wrap(), suite.palomadex_pair_contract.clone()) - .unwrap(); - let expected = liquidity * 4 / 5; - assert_eq!(cw20_token_liquidity.u128(), expected); - // Grin given for RAW tokens - let palomadex = cw20::Cw20Contract(grain_token.clone()) - .balance(&suite.app.wrap(), suite.palomadex_pair_contract.clone()) - .unwrap(); - let expected = Uint128::from(liquidity * 4 / 5) * raw_to_grain_exchange_rate; - assert_eq!(palomadex, expected); - - let raw = cw20::Cw20Contract(raw_address.clone()) - .balance(&suite.app.wrap(), suite.palomadex_pair_contract.clone()) - .unwrap(); - assert_eq!(raw.u128(), 0u128); - - // ensure all lp belong to the staking contract - let palomadex_total = suite.total_palomadex_lp(); - let palomadex_staked = suite.total_palomadex_staked(); - let pool = suite.palomadex_pair_contract.to_string(); - let pool_own_lp = suite.palomadex_lp(&pool); - assert_eq!(palomadex_total, palomadex_staked + pool_own_lp); - assert_eq!( - pool_own_lp, - palomadex::asset::MINIMUM_LIQUIDITY_AMOUNT.u128() - ); - - // ensure all staked tokens belong to the migrated user - let user_staked = suite.palomadex_staked(user, suite.migration_unbonding_period()); - assert_eq!(user_staked, palomadex_staked); -} diff --git a/contracts/raw-migration/src/multitest/suite.rs b/contracts/raw-migration/src/multitest/suite.rs deleted file mode 100644 index d8d0f62..0000000 --- a/contracts/raw-migration/src/multitest/suite.rs +++ /dev/null @@ -1,761 +0,0 @@ -use anyhow::Result as AnyResult; - -use cw20::MinterResponse; -use palomadex::asset::AssetInfo; -use palomadex::factory::{ - DefaultStakeConfig, ExecuteMsg as FactoryExecuteMsg, InstantiateMsg as FactoryInstantiateMsg, - PairConfig, PairType, PartialStakeConfig, QueryMsg as FactoryQueryMsg, -}; -use palomadex::fee_config::FeeConfig; -use palomadex::pair::{PairInfo, PoolResponse, QueryMsg as PairQueryMsg}; - -use crate::msg::{MigrateMsg, OrigMigrateMsg, QueryMsg}; -use cosmwasm_std::{coin, to_binary, Addr, Coin, Decimal, Uint128}; -use cw20_base::msg::InstantiateMsg as Cw20BaseInstantiateMsg; -use cw_multi_test::{next_block, App, AppResponse, BankSudo, ContractWrapper, Executor, SudoMsg}; -use stake_cw20::msg::{ClaimsResponse, InstantiateMsg as StakeCw20IntantiateMsg}; -use wasmswap::msg::{ - ExecuteMsg as WasmswapExecuteMsg, InfoResponse, InstantiateMsg as WasmswapInstantiateMsg, - QueryMsg as WasmswapQueryMsg, -}; -use wasmswap_cw20::{Cw20ExecuteMsg, Denom}; -use wasmswap_cw_utils::Duration; - -pub const ONE_DAY: u64 = 86_400; - -pub fn store_stake_cw20(app: &mut App) -> u64 { - let contract = Box::new(ContractWrapper::new( - stake_cw20::contract::execute, - stake_cw20::contract::instantiate, - stake_cw20::contract::query, - )); - app.store_code(contract) -} - -pub fn store_junoswap_pool(app: &mut App) -> u64 { - let contract = Box::new( - ContractWrapper::new( - wasmswap::contract::execute, - wasmswap::contract::instantiate, - wasmswap::contract::query, - ) - .with_reply_empty(wasmswap::contract::reply), - ); - app.store_code(contract) -} - -pub fn store_cw20(app: &mut App) -> u64 { - let contract = Box::new(ContractWrapper::new( - wasmswap_cw20_base::contract::execute, - wasmswap_cw20_base::contract::instantiate, - wasmswap_cw20_base::contract::query, - )); - app.store_code(contract) -} - -pub fn store_palomadex_staking(app: &mut App) -> u64 { - let contract = Box::new(ContractWrapper::new( - palomadex_stake::contract::execute, - palomadex_stake::contract::instantiate, - palomadex_stake::contract::query, - )); - app.store_code(contract) -} - -fn store_palomadex_factory(app: &mut App) -> u64 { - let factory_contract = Box::new( - ContractWrapper::new_with_empty( - palomadex_factory::contract::execute, - palomadex_factory::contract::instantiate, - palomadex_factory::contract::query, - ) - .with_reply_empty(palomadex_factory::contract::reply), - ); - - app.store_code(factory_contract) -} - -fn store_palomadex_pair(app: &mut App) -> u64 { - let factory_contract = Box::new( - ContractWrapper::new_with_empty( - palomadex_pair::contract::execute, - palomadex_pair::contract::instantiate, - palomadex_pair::contract::query, - ) - .with_reply_empty(palomadex_pair::contract::reply), - ); - - app.store_code(factory_contract) -} - -pub fn store_migrator(app: &mut App) -> u64 { - let contract = Box::new( - ContractWrapper::new( - crate::contract::execute, - crate::contract::instantiate, - crate::contract::query, - ) - .with_reply(crate::contract::reply), - ); - app.store_code(contract) -} - -/// Helper to be able to specify a non-existing cw20 token -#[derive(Debug, Clone)] -pub enum PoolDenom { - Native(String), - /// The string is not the contract address, but the symbol / name of the token. - /// A new token will be instantiated using this name. - Cw20(String), -} - -impl PoolDenom { - pub fn into_denom( - self, - app: &mut App, - owner: impl Into + Clone, - cw20_code_id: u64, - ) -> Denom { - match self { - PoolDenom::Native(denom) => Denom::Native(denom), - PoolDenom::Cw20(symbol) => { - // create cw20 token - let cw20_token = app - .instantiate_contract( - cw20_code_id, - Addr::unchecked(owner.clone()), - &Cw20BaseInstantiateMsg { - name: symbol.clone(), - symbol: symbol.clone(), - decimals: 6, - initial_balances: vec![], - mint: Some(MinterResponse { - minter: owner.into(), - cap: None, - }), - marketing: None, - }, - &[], - symbol, - None, - ) - .unwrap(); - Denom::Cw20(cw20_token) - } - } - } -} - -#[derive(Debug)] -pub struct SuiteBuilder { - funds: Vec<(Addr, Vec)>, - unbonding_periods: Vec, - pool_denom1: PoolDenom, - pool_denom2: PoolDenom, -} - -impl SuiteBuilder { - pub fn new() -> SuiteBuilder { - SuiteBuilder { - unbonding_periods: vec![100, 200, 300], - pool_denom1: PoolDenom::Native("ujuno".to_string()), - pool_denom2: PoolDenom::Native("uluna".to_string()), - funds: vec![], - } - } - - /// Specify the pool denoms. For cw20 denoms, the - pub fn with_denoms(mut self, denom1: PoolDenom, denom2: PoolDenom) -> Self { - self.pool_denom1 = denom1; - self.pool_denom2 = denom2; - self - } - - #[track_caller] - pub fn build(self) -> Suite { - let mut app = App::default(); - let owner = Addr::unchecked("owner"); - - let cw20_code_id = store_cw20(&mut app); - - let pool_denom1 = self - .pool_denom1 - .into_denom(&mut app, owner.clone(), cw20_code_id); - let pool_denom2 = self - .pool_denom2 - .into_denom(&mut app, owner.clone(), cw20_code_id); - - // Instantiate junoswap pool - let junoswap_pool_code_id = store_junoswap_pool(&mut app); - let junoswap_pool_contract = app - .instantiate_contract( - junoswap_pool_code_id, - owner.clone(), - &WasmswapInstantiateMsg { - token1_denom: pool_denom1.clone(), - token2_denom: pool_denom2.clone(), - lp_token_code_id: cw20_code_id, - owner: Some(owner.to_string()), - lp_fee_percent: Decimal::zero(), - protocol_fee_percent: Decimal::zero(), - protocol_fee_recipient: owner.to_string(), - }, - &[], - "wasmswap-pool", - Some(owner.to_string()), - ) - .unwrap(); - app.update_block(next_block); - - // Check address of created token contract - let junoswap_token_contract = Addr::unchecked( - app.wrap() - .query_wasm_smart::( - &junoswap_pool_contract, - &WasmswapQueryMsg::Info {}, - ) - .unwrap() - .lp_token_address, - ); - - // Instantiate junoswap staking contract - let junoswap_staking_code_id = store_stake_cw20(&mut app); - let junoswap_staking_contract = app - .instantiate_contract( - junoswap_staking_code_id, - owner.clone(), - &StakeCw20IntantiateMsg { - owner: Some(owner.to_string()), - manager: Some("manager".to_string()), - token_address: junoswap_token_contract.to_string(), - unstaking_duration: Some(Duration::Time(ONE_DAY * 14)), - }, - &[], - "staking", - Some(owner.to_string()), - ) - .unwrap(); - app.update_block(next_block); - - // Instantiate palomadex factory - let palomadex_stake_code_id = store_palomadex_staking(&mut app); - let palomadex_pair_code_id = store_palomadex_pair(&mut app); - let palomadex_factory_code_id = store_palomadex_factory(&mut app); - let factory_contract = app - .instantiate_contract( - palomadex_factory_code_id, - owner.clone(), - &FactoryInstantiateMsg { - pair_configs: vec![PairConfig { - pair_type: PairType::Xyk {}, - code_id: palomadex_pair_code_id, - fee_config: FeeConfig { - total_fee_bps: 0, - protocol_fee_bps: 0, - }, - is_disabled: false, - }], - token_code_id: cw20_code_id, - fee_address: Some(owner.to_string()), - owner: owner.to_string(), - max_referral_commission: Decimal::one(), - default_stake_config: DefaultStakeConfig { - staking_code_id: palomadex_stake_code_id, - tokens_per_power: Uint128::new(1000), - min_bond: Uint128::new(1000), - unbonding_periods: self.unbonding_periods.clone(), - max_distributions: 6, - converter: None, - }, - trading_starts: None, - }, - &[], - "palomadex-factory", - Some(owner.to_string()), - ) - .unwrap(); - - let wynd_cw20_token = app - .instantiate_contract( - cw20_code_id, - Addr::unchecked(owner.clone()), - &Cw20BaseInstantiateMsg { - name: "PALOMA".to_owned(), - symbol: "PALOMA".to_owned(), - decimals: 6, - initial_balances: vec![], - mint: Some(MinterResponse { - minter: owner.to_string(), - cap: None, - }), - marketing: None, - }, - &[], - "PALOMA".to_owned(), - None, - ) - .unwrap(); - - // Wasmswap is using older version of cw20, so specific From impl - // would have to be created - IMO not worth it - let asset_infos = vec![ - match pool_denom1.clone() { - Denom::Native(s) => AssetInfo::Native(s), - Denom::Cw20(s) => AssetInfo::Token(s.to_string()), - }, - AssetInfo::Token(wynd_cw20_token.to_string()), - ]; - - // Instantiate palomadex pair contract through factory - app.execute_contract( - owner.clone(), - factory_contract.clone(), - &FactoryExecuteMsg::CreatePair { - pair_type: PairType::Xyk {}, - asset_infos: asset_infos.clone(), - init_params: None, - total_fee_bps: None, - // accept defaults, but ensure there is a staking contract - staking_config: PartialStakeConfig { - staking_code_id: None, - tokens_per_power: None, - min_bond: None, - unbonding_periods: None, - max_distributions: None, - converter: None, - }, - }, - &[], - ) - .unwrap(); - let pair_info = app - .wrap() - .query_wasm_smart::( - Addr::unchecked(&factory_contract), - &FactoryQueryMsg::Pair { asset_infos }, - ) - .unwrap(); - - let palomadex_pair_contract = pair_info.contract_addr; - let palomadex_staking_contract = pair_info.staking_addr; - let palomadex_token_contract = pair_info.liquidity_token; - - // add funds to the contract - let funds = self.funds; - app.init_modules(|router, _, storage| -> AnyResult<()> { - for (addr, coin) in funds { - router.bank.init_balance(storage, &addr, coin)?; - } - Ok(()) - }) - .unwrap(); - - let migrator_code_id = store_migrator(&mut app); - - Suite { - owner, - app, - junoswap_token_contract, - junoswap_pool_contract, - junoswap_staking_contract, - factory_contract, - palomadex_pair_contract, - palomadex_staking_contract, - palomadex_token_contract, - grain_cw20_token: wynd_cw20_token, - migrator_code_id, - cw20_code_id, - pool_denom1, - pool_denom2, - unbonding_periods: self.unbonding_periods, - } - } -} - -pub struct Suite { - pub owner: Addr, - pub app: App, - pub migrator_code_id: u64, - pub cw20_code_id: u64, - pub unbonding_periods: Vec, - - pub junoswap_token_contract: Addr, - pub junoswap_pool_contract: Addr, - pub junoswap_staking_contract: Addr, - pub grain_cw20_token: Addr, - pub palomadex_token_contract: Addr, - pub palomadex_staking_contract: Addr, - pub palomadex_pair_contract: Addr, - pub pool_denom1: Denom, - pub pool_denom2: Denom, - - pub factory_contract: Addr, -} - -#[derive(Debug)] -#[allow(dead_code)] -struct SuiteInfo<'a> { - pub junoswap_token_contract: &'a Addr, - pub junoswap_pool_contract: &'a Addr, - pub junoswap_staking_contract: &'a Addr, - pub factory_contract: &'a Addr, - pub palomadex_token_contract: &'a Addr, - pub palomadex_staking_contract: &'a Addr, - pub palomadex_pair_contract: &'a Addr, -} - -impl Suite { - // for debugging tests - #[allow(dead_code)] - pub fn info(&self) { - let info = SuiteInfo { - junoswap_token_contract: &self.junoswap_token_contract, - junoswap_pool_contract: &self.junoswap_pool_contract, - junoswap_staking_contract: &self.junoswap_staking_contract, - factory_contract: &self.factory_contract, - palomadex_token_contract: &self.palomadex_token_contract, - palomadex_staking_contract: &self.palomadex_staking_contract, - palomadex_pair_contract: &self.palomadex_pair_contract, - }; - println!("{:?}", info); - } - - pub fn migration_unbonding_period(&self) -> u64 { - self.unbonding_periods[1] - } - - /// Returns true if migration is finished - /// Only makes sense to call after the junoswap staking contract has been migrated - pub fn migration_finished(&self) -> AnyResult { - self.app - .wrap() - .query_wasm_smart( - self.junoswap_staking_contract.clone(), - &QueryMsg::MigrationFinished {}, - ) - .map_err(Into::into) - } - - /// Migrates the junoswap staking contract to our migration contract and migrates the tokens - pub fn migrate_tokens( - &mut self, - migrator: Option, - palomadex_pair_migrate: Option, - palomadex_pair: Option, - raw_to_wynd_exchange_rate: Decimal, - raw_address: Addr, - ) -> AnyResult { - // // take RAW token's address by force. We know it is the one. - // let raw_address = match self.pool_denom2.clone() { - // Denom::Cw20(address) => address, - // _ => todo!(), - // }; - // first set up the migration - self.app.migrate_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &MigrateMsg { - init: Some(OrigMigrateMsg { - migrator: migrator.unwrap_or_else(|| self.owner.clone()).to_string(), - unbonding_period: self.migration_unbonding_period(), - junoswap_pool: self.junoswap_pool_contract.to_string(), - factory: self.factory_contract.to_string(), - palomadex_pool: palomadex_pair_migrate.map(|p| p.to_string()), - raw_to_grain_exchange_rate: raw_to_wynd_exchange_rate, - raw_address: raw_address.to_string(), - grain_address: self.grain_cw20_token.to_string(), - }), - }, - self.migrator_code_id, - )?; - - // then migrate again (self-migrate) to ensure it works - self.app.migrate_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &MigrateMsg { init: None }, - self.migrator_code_id, - )?; - - // then trigger the actual migration - self.app.execute_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &crate::msg::ExecuteMsg::MigrateTokens { - palomadex_pool: palomadex_pair - .unwrap_or_else(|| self.palomadex_pair_contract.clone()) - .to_string(), - }, - &[], - ) - } - - /// Migrates the next `limit` staker's LP tokens. - /// Only makes sense to call after the junoswap staking contract has been migrated. - pub fn migrate_stakers(&mut self, limit: u32) -> AnyResult { - self.app.execute_contract( - self.owner.clone(), - self.junoswap_staking_contract.clone(), - &crate::msg::ExecuteMsg::MigrateStakers { limit }, - &[], - ) - } - - pub fn migrate_to_palomadex( - &mut self, - migrator: Option, - palomadex_pair_migrate: Option, - palomadex_pair: Option, - raw_to_wynd_exchange_rate: Decimal, - raw_address: Addr, - ) -> AnyResult<()> { - self.migrate_tokens( - migrator, - palomadex_pair_migrate, - palomadex_pair, - raw_to_wynd_exchange_rate, - raw_address, - )?; - - // now migrate all the stakers - while !self.migration_finished()? { - self.migrate_stakers(10)?; - } - - Ok(()) - } - - fn increase_allowance( - &mut self, - owner: &str, - contract: &Addr, - spender: &str, - amount: u128, - ) -> AnyResult { - self.app.execute_contract( - Addr::unchecked(owner), - contract.clone(), - &Cw20ExecuteMsg::IncreaseAllowance { - spender: spender.to_owned(), - amount: amount.into(), - expires: None, - }, - &[], - ) - } - - pub fn mint_cw20( - &mut self, - owner: &str, - token: &Addr, - amount: u128, - recipient: &str, - ) -> AnyResult { - self.app.execute_contract( - Addr::unchecked(owner), - token.clone(), - &Cw20ExecuteMsg::Mint { - recipient: recipient.to_owned(), - amount: amount.into(), - }, - &[], - ) - } - - pub fn junoswap_lp(&mut self, user: &str, lp_contract: Option<&Addr>) -> AnyResult { - let query = cw20::Cw20QueryMsg::Balance { - address: user.to_string(), - }; - let cw20::BalanceResponse { balance } = self - .app - .wrap() - .query_wasm_smart(lp_contract.unwrap_or(&self.junoswap_token_contract), &query)?; - Ok(balance) - } - - /// Requirement: if using native token provide coins to sent as last argument - #[allow(clippy::too_many_arguments)] - pub fn provide_liquidity_to_junoswap_pool( - &mut self, - user: &str, - first_asset: u128, - second_asset: u128, - first_denom: Option, - second_denom: Option, - native_tokens: Vec, - ) -> AnyResult { - let owner = self.owner.to_string(); - - let assets = vec![ - ( - first_denom.unwrap_or_else(|| self.pool_denom1.clone()), - first_asset, - ), - ( - second_denom.unwrap_or_else(|| self.pool_denom2.clone()), - second_asset, - ), - ]; - for (denom, amount) in assets { - match denom { - Denom::Cw20(addr) => { - // Mint some initial balances for whale user - self.mint_cw20(&owner, &addr, amount, user).unwrap(); - // Increases allowances for given LP contracts in order to provide liquidity to pool - let spender = self.junoswap_pool_contract.to_string(); - self.increase_allowance(user, &addr, &spender, amount) - .unwrap(); - } - Denom::Native(denom) => { - self.app - .sudo(SudoMsg::Bank(BankSudo::Mint { - to_address: user.to_owned(), - amount: vec![coin(amount, denom)], - })) - .unwrap(); - } - } - } - - self.app.execute_contract( - Addr::unchecked(user), - self.junoswap_pool_contract.clone(), - &WasmswapExecuteMsg::AddLiquidity { - token1_amount: first_asset.into(), - min_liquidity: Uint128::new(100), - max_token2: second_asset.into(), - expiration: None, - }, - &native_tokens, - ) - } - - pub fn stake_junoswap_lp( - &mut self, - user: &str, - amount: Uint128, - lp_contract: Option<&Addr>, - staking_contract: Option<&Addr>, - ) -> AnyResult { - let msg = to_binary(&stake_cw20::msg::ReceiveMsg::Stake {})?; - self.app.execute_contract( - Addr::unchecked(user), - lp_contract - .unwrap_or(&self.junoswap_token_contract.clone()) - .to_owned(), - &cw20::Cw20ExecuteMsg::Send { - contract: staking_contract - .unwrap_or(&self.junoswap_staking_contract.clone()) - .to_string(), - amount, - msg, - }, - &[], - ) - } - - pub fn unstake_junoswap_lp( - &mut self, - user: &str, - amount: Uint128, - staking_contract: Option<&Addr>, - ) -> AnyResult { - self.app.execute_contract( - Addr::unchecked(user), - staking_contract - .unwrap_or(&self.junoswap_staking_contract) - .clone(), - &stake_cw20::msg::ExecuteMsg::Unstake { amount }, - &[], - ) - } - - #[allow(dead_code)] - pub fn query_stake_claims_for_pair(&mut self, address: String) -> ClaimsResponse { - let resp: ClaimsResponse = self - .app - .wrap() - .query_wasm_smart( - &self.junoswap_staking_contract, - &stake_cw20::msg::QueryMsg::Claims { address }, - ) - .unwrap(); - resp - } - - pub fn query_palomadex_pool(&mut self) -> PoolResponse { - self.app - .wrap() - .query_wasm_smart::(&self.palomadex_pair_contract, &PairQueryMsg::Pool {}) - .unwrap() - } - - pub fn total_palomadex_lp(&mut self) -> u128 { - let cw20::TokenInfoResponse { total_supply, .. } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_token_contract, - &cw20::Cw20QueryMsg::TokenInfo {}, - ) - .unwrap(); - - total_supply.u128() - } - - pub fn palomadex_lp(&mut self, user: &str) -> u128 { - let cw20::BalanceResponse { balance } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_token_contract, - &cw20::Cw20QueryMsg::Balance { - address: user.to_string(), - }, - ) - .unwrap(); - - balance.u128() - } - - // for debugging tests - #[allow(dead_code)] - pub fn palomadex_lp_holders(&mut self) -> Vec<(String, u128)> { - let cw20::AllAccountsResponse { accounts } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_token_contract, - &cw20::Cw20QueryMsg::AllAccounts { - start_after: None, - limit: None, - }, - ) - .unwrap(); - accounts - .into_iter() - .map(|addr| (addr.clone(), self.palomadex_lp(&addr))) - .collect() - } - - pub fn total_palomadex_staked(&mut self) -> u128 { - let addr = self.palomadex_staking_contract.clone(); - self.palomadex_lp(addr.as_str()) - } - - pub fn palomadex_staked(&mut self, user: &str, unbonding_period: u64) -> u128 { - let palomadex_stake::msg::StakedResponse { stake, .. } = self - .app - .wrap() - .query_wasm_smart( - &self.palomadex_staking_contract, - &palomadex_stake::msg::QueryMsg::Staked { - address: user.to_string(), - unbonding_period, - }, - ) - .unwrap(); - - stake.u128() - } -} diff --git a/contracts/raw-migration/src/state.rs b/contracts/raw-migration/src/state.rs deleted file mode 100644 index 3e69e32..0000000 --- a/contracts/raw-migration/src/state.rs +++ /dev/null @@ -1,51 +0,0 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Decimal, Uint128}; -use cw_storage_plus::Item; - -#[cw_serde] -pub struct MigrateConfig { - /// This is the address that can run ExecuteMsg::MigrateTokens - pub migrator: Addr, - /// This is how long it will be staked on PALOMA DEX - pub unbonding_period: u64, - - /// This is the junoswap pool where the LP will be withdrawn from - pub junoswap_pool: Addr, - - /// Can be deposited in any pool created by this factory - pub factory: Addr, - /// If set, only can be deposited in this pool (which must also be created by the factory) - pub palomadex_pool: Option, - - /// This is set when token migration is finished. - /// It is used to calculate the amount of LP tokens to give to each staker. - pub migrate_stakers_config: Option, -} - -/// The necessary information to migrate stakers. -#[cw_serde] -pub struct MigrateStakersConfig { - /// The palomadex LP token contract - pub lp_token: Addr, - /// The palomadex LP staking contract - pub staking_addr: Addr, - /// The total amount of palomadex LP tokens this contract received after token migration. - pub total_lp_tokens: Uint128, - /// The total amount of staked junoswap LP tokens. - pub total_staked: Uint128, -} - -/// Stores the contract configuration at the given key -pub const MIGRATION: Item = Item::new("migration"); - -/// This is set once MigrateTokens is called -pub const DESTINATION: Item = Item::new("destination"); - -#[cw_serde] -pub struct ExchangeConfig { - pub raw_to_grain_exchange_rate: Decimal, - pub raw_token: Addr, - pub grain_token: Addr, -} - -pub const EXCHANGE_CONFIG: Item = Item::new("exchange_config"); diff --git a/contracts/splitter/src/contract.rs b/contracts/splitter/src/contract.rs index e3b94fb..449fc66 100644 --- a/contracts/splitter/src/contract.rs +++ b/contracts/splitter/src/contract.rs @@ -6,9 +6,8 @@ use cosmwasm_std::{ }; use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg}; -use cw_utils::ensure_from_older_version; -use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use crate::state::{Config, CONFIG}; use crate::ContractError; @@ -358,7 +357,7 @@ mod tests { .init_balance( storage, &Addr::unchecked("owner"), - vec![coin(1_000_000, "ujuno"), coin(200_000, "grain")], + vec![coin(1_000_000, "ujuno"), coin(200_000, "ugrain")], ) .unwrap() }); @@ -395,7 +394,7 @@ mod tests { Addr::unchecked("owner"), BankMsg::Send { to_address: splitter_contract.to_string(), - amount: vec![coin(200_000, "grain")], + amount: vec![coin(200_000, "ugrain")], } .into(), ) @@ -406,7 +405,7 @@ mod tests { Addr::unchecked("owner"), splitter_contract, &ExecuteMsg::SendTokens { - native_denoms: vec!["ujuno".to_owned(), "grain".to_owned()], + native_denoms: vec!["ujuno".to_owned(), "ugrain".to_owned()], cw20_addresses: None, }, &[], @@ -417,13 +416,13 @@ mod tests { app.wrap() .query_all_balances("address1".to_owned()) .unwrap(), - vec![coin(330_000u128, "ujuno"), coin(66_000u128, "grain")] + vec![coin(66_000u128, "ugrain"), coin(330_000u128, "ujuno")] ); assert_eq!( app.wrap() .query_all_balances("address2".to_owned()) .unwrap(), - vec![coin(670_000u128, "ujuno"), coin(134_000u128, "grain")] + vec![coin(134_000u128, "ugrain"), coin(670_000u128, "ujuno")] ); } @@ -435,7 +434,7 @@ mod tests { .init_balance( storage, &Addr::unchecked("owner"), - vec![coin(1_000_000, "ujuno"), coin(200_000, "grain")], + vec![coin(1_000_000, "ujuno"), coin(200_000, "ugrain")], ) .unwrap() }); @@ -472,7 +471,7 @@ mod tests { Addr::unchecked("owner"), BankMsg::Send { to_address: splitter_contract.to_string(), - amount: vec![coin(200_000, "grain")], + amount: vec![coin(200_000, "ugrain")], } .into(), ) @@ -482,7 +481,7 @@ mod tests { Addr::unchecked("owner"), splitter_contract.clone(), &ExecuteMsg::SendTokens { - native_denoms: vec!["grain".to_owned()], + native_denoms: vec!["ugrain".to_owned()], cw20_addresses: None, }, &[], @@ -493,13 +492,13 @@ mod tests { app.wrap() .query_all_balances("address1".to_owned()) .unwrap(), - vec![coin(66_000u128, "grain")] + vec![coin(66_000u128, "ugrain")] ); assert_eq!( app.wrap() .query_all_balances("address2".to_owned()) .unwrap(), - vec![coin(134_000u128, "grain")] + vec![coin(134_000u128, "ugrain")] ); // make sure other tokens are still on splitter contract's balance assert_eq!( diff --git a/contracts/stake/src/contract.rs b/contracts/stake/src/contract.rs index 9df6ce1..b25deec 100644 --- a/contracts/stake/src/contract.rs +++ b/contracts/stake/src/contract.rs @@ -20,13 +20,12 @@ use crate::distribution::{ query_undistributed_rewards, query_withdraw_adjustment_data, query_withdrawable_rewards, }; use crate::utils::{create_undelegate_msg, CurveExt}; -use cw2::set_contract_version; -use cw_utils::{ensure_from_older_version, maybe_addr, Expiration}; +use cw_utils::{maybe_addr, Expiration}; use crate::error::ContractError; use crate::msg::{ AllStakedResponse, AnnualizedReward, AnnualizedRewardsResponse, BondingInfoResponse, - BondingPeriodInfo, ExecuteMsg, MigrateMsg, QueryMsg, RewardsPowerResponse, StakedResponse, + BondingPeriodInfo, ExecuteMsg, QueryMsg, RewardsPowerResponse, StakedResponse, TotalStakedResponse, TotalUnbondingResponse, UnbondAllResponse, }; use crate::state::{ diff --git a/contracts/stake/src/state.rs b/contracts/stake/src/state.rs index 161a009..907677a 100644 --- a/contracts/stake/src/state.rs +++ b/contracts/stake/src/state.rs @@ -251,7 +251,7 @@ impl Distribution { let totals = TOTAL_PER_PERIOD.load(storage).unwrap_or_default(); self.reward_multipliers .iter() - .zip(totals.into_iter()) + .zip(totals) .map( |(&(unbonding_period, multiplier), (unbonding_period2, total_stake))| { // sanity check diff --git a/packages/palomadex/src/asset.rs b/packages/palomadex/src/asset.rs index 37fd854..e67387a 100644 --- a/packages/palomadex/src/asset.rs +++ b/packages/palomadex/src/asset.rs @@ -242,9 +242,9 @@ impl fmt::Display for AssetInfo { /// ## Examples /// ``` /// # use cosmwasm_std::Addr; -/// # use wyndex::asset::AssetInfo::{Native, Token}; +/// # use palomadex::asset::AssetInfo::{Native, Token}; /// Token("terra...".to_string()); -/// Native(String::from("uluna")); +/// Native(String::from("ugrain")); /// ``` #[cw_serde] #[derive(Hash, Eq)]