diff --git a/Cargo.toml b/Cargo.toml index 22544533..7ca96479 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = [ # Packages "packages/shade_protocol", - "packages/shadeswap_shared", + #"packages/shadeswap_shared", # "packages/secretcli", "packages/multi_test", "packages/multi_derive", diff --git a/contracts/liquidity_book/lb_pair/Cargo.toml b/contracts/liquidity_book/lb_pair/Cargo.toml index a7bbe78e..bad68727 100644 --- a/contracts/liquidity_book/lb_pair/Cargo.toml +++ b/contracts/liquidity_book/lb_pair/Cargo.toml @@ -30,7 +30,7 @@ serde-json-wasm = { version = "0.5"} thiserror = { version = "1" } secret-storage-plus = { git = "https://github.com/securesecrets/secret-plus-utils", version = "0.13.4", optional = true } ethnum = { version = "1" } -shadeswap-shared = { version = "0.1.0", path = "../../../packages/shadeswap_shared", features = [] } +#shadeswap-shared = { version = "0.1.0", path = "../../../packages/shadeswap_shared", features = [] } [dev-dependencies] anyhow = "1" diff --git a/contracts/liquidity_book/router/Cargo.toml b/contracts/liquidity_book/router/Cargo.toml index 92d1b600..068f04ed 100644 --- a/contracts/liquidity_book/router/Cargo.toml +++ b/contracts/liquidity_book/router/Cargo.toml @@ -31,8 +31,8 @@ serde = { version = "1.0.114", default-features = false, features = [ schemars = "0.8.1" cosmwasm-std = { package = "secret-cosmwasm-std", version = "=1.1.11", features = ["iterator"] } cosmwasm-storage = { package = "secret-cosmwasm-storage", version = "=1.1.11", features = ["iterator"] } -shadeswap-shared = { version = "0.1.0", path = "../../../packages/shadeswap_shared", features = [] } -shade-protocol = { version = "0.1.0", path = "../../../packages/shade_protocol", features = [] } +# shadeswap-shared = { version = "0.1.0", path = "../../../packages/shadeswap_shared", features = [] } +shade-protocol = { version = "0.1.0", path = "../../../packages/shade_protocol", features = ["swap"] } [dev-dependencies] cosmwasm-schema = { git = "https://github.com/CosmWasm/cosmwasm"} secret-multi-test = { git = "https://github.com/securesecrets/secret-plus-utils", version = "0.13.4", features=["iterator"] } diff --git a/contracts/liquidity_book/router/src/contract.rs b/contracts/liquidity_book/router/src/contract.rs index 9fae0dab..6036806f 100644 --- a/contracts/liquidity_book/router/src/contract.rs +++ b/contracts/liquidity_book/router/src/contract.rs @@ -4,33 +4,20 @@ use crate::{ state::{config_r, config_w, registered_tokens_list_r, registered_tokens_list_w, Config}, }; use cosmwasm_std::{ - entry_point, - from_binary, - to_binary, - Addr, - BankMsg, - Binary, - Coin, - CosmosMsg, - Deps, - DepsMut, - Env, - MessageInfo, - Reply, - Response, - StdError, - StdResult, - Uint128, + entry_point, from_binary, to_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Deps, DepsMut, + Env, MessageInfo, Reply, Response, StdError, StdResult, Uint128, }; -use shade_protocol::{utils::liquidity_book::tokens::TokenType, Contract}; -use shadeswap_shared::{ - admin::helpers::{validate_admin, AdminPermissions}, +use shade_protocol::contract_interfaces::swap::{ amm_pair::QueryMsgResponse as AMMPairQueryReponse, - core::TokenAmount, + core::{ + admin::helpers::{validate_admin, AdminPermissions}, + TokenAmount, + }, router::{ExecuteMsg, InitMsg, InvokeMsg, QueryMsg, QueryMsgResponse}, snip20::helpers::send_msg, utils::{pad_handle_result, pad_query_result}, }; +use shade_protocol::{utils::liquidity_book::tokens::TokenType, Contract}; /// Pad handle responses and log attributes to blocks /// of 256 bytes to prevent leaking info based on response size @@ -177,11 +164,13 @@ fn receiver_callback( path, recipient, } => { - let pair_contract_config = - query::pair_contract_config(&deps.querier, Contract { + let pair_contract_config = query::pair_contract_config( + &deps.querier, + Contract { address: deps.api.addr_validate(&path[0].addr.to_string())?, code_hash: path[0].code_hash.clone(), - })?; + }, + )?; match pair_contract_config { AMMPairQueryReponse::GetPairInfo { diff --git a/contracts/liquidity_book/tests/Cargo.toml b/contracts/liquidity_book/tests/Cargo.toml index f67d0ec7..ad33fd5f 100644 --- a/contracts/liquidity_book/tests/Cargo.toml +++ b/contracts/liquidity_book/tests/Cargo.toml @@ -44,4 +44,4 @@ shade-multi-test = { path = "../../../packages/multi_test", features = [ "lb_factory" ] } -shadeswap-shared = { version = "0.1.0", path = "../../../packages/shadeswap_shared", features = [] } +# shadeswap-shared = { version = "0.1.0", path = "../../../packages/shadeswap_shared", features = [] } diff --git a/packages/multi_test/Cargo.toml b/packages/multi_test/Cargo.toml index 5f7200ee..75df0387 100644 --- a/packages/multi_test/Cargo.toml +++ b/packages/multi_test/Cargo.toml @@ -66,7 +66,7 @@ mock_stkd = { version = "0.1.0", package = "mock_stkd_derivative", path = "../.. mock_sienna = { version = "0.1.0", package = "mock_sienna_pair", path = "../../contracts/mock/mock_sienna_pair", optional = true } snip20_migration = { version = "0.1.0", path = "../../contracts/snip20_migration", optional = true } shade-protocol = { path = "../shade_protocol", features = ["multi-test"] } -shadeswap-shared = { version = "0.1.0", path = "../../packages/shadeswap_shared", features = [] } +# shadeswap-shared = { version = "0.1.0", path = "../../packages/shadeswap_shared", features = [] } anyhow = "1" [target.'cfg(not(target_arch="wasm32"))'.dependencies] diff --git a/packages/shade_protocol/Cargo.toml b/packages/shade_protocol/Cargo.toml index c42e80c9..f40975de 100644 --- a/packages/shade_protocol/Cargo.toml +++ b/packages/shade_protocol/Cargo.toml @@ -88,6 +88,7 @@ admin = ["interface"] peg_stability = ["sky-utils", "adapter"] snip20_migration = [] liquidity_book = ["interface"] +swap = ["snip20"] chrono = ["dep:chrono"] diff --git a/packages/shade_protocol/src/contract_interfaces/mod.rs b/packages/shade_protocol/src/contract_interfaces/mod.rs index c64d285f..fe995ee7 100644 --- a/packages/shade_protocol/src/contract_interfaces/mod.rs +++ b/packages/shade_protocol/src/contract_interfaces/mod.rs @@ -47,3 +47,6 @@ pub mod basic_staking; #[cfg(feature = "snip20_migration")] pub mod snip20_migration; + +#[cfg(feature = "swap")] +pub mod swap; diff --git a/packages/shade_protocol/src/contract_interfaces/swap/amm_pair.rs b/packages/shade_protocol/src/contract_interfaces/swap/amm_pair.rs index b9dd0cd8..43dd3eaa 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/amm_pair.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/amm_pair.rs @@ -1,26 +1,22 @@ use crate::{ - c_std::{ - utils::{ExecuteCallback, InstantiateCallback, Query}, - Addr, Binary, Uint128, BLOCK_SIZE, - }, + c_std::{Addr, Binary, Decimal256, Uint128, Uint256}, cosmwasm_schema::cw_serde, - liquidity_book::lb_pair::SwapResult, + lb_pair::SwapResult, snip20::Snip20ReceiveMsg, - utils::asset::RawContract, - utils::liquidity_book::tokens::TokenType, - Contract, + swap::core::{ + ContractInstantiationInfo, CustomFee, Fee, StableTokenData, TokenAmount, TokenPair, + TokenPairAmount, + }, + utils::{ + asset::RawContract, liquidity_book::tokens::TokenType, ExecuteCallback, + InstantiateCallback, Query, + }, + Contract, BLOCK_SIZE, }; use std::fmt::{Debug, Display}; -use super::*; -use core::{ - ContractInstantiationInfo, ContractInstantiationInfo, CustomFee, Fee, StableTokenData, - TokenAmount, TokenPair, TokenPairAmount, -}; -use staking::StakingContractInstantiateInfo; - -use cosmwasm_std::{Addr, Decimal256, Uint256}; +use crate::swap::staking::StakingContractInstantiateInfo; /// Represents the address of an exchange and the pair that it manages #[cw_serde] diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/admin.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/admin.rs deleted file mode 100644 index a26ae8e5..00000000 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/admin.rs +++ /dev/null @@ -1,37 +0,0 @@ -// use cosmwasm_std::{ -// StdError, -// StdResult, -// Storage, Response, MessageInfo, Addr -// }; -// use cosmwasm_storage::{singleton, Singleton, singleton_read, ReadonlySingleton}; - -// pub static ADMIN: &[u8] =b"contract_pair_admin"; - -// pub fn admin_w(storage: &mut dyn Storage) -> Singleton { -// singleton(storage, ADMIN) -// } - -// pub fn admin_r(storage: & dyn Storage) -> ReadonlySingleton { -// singleton_read(storage, ADMIN) -// } - -// // pub fn apply_admin_guard( -// // caller: &Addr, -// // storage: &mut dyn Storage, -// // ) -> StdResult { -// // let admin_address = admin_r(storage).load()?; -// // if caller != &admin_address { -// // return Err(StdError::generic_err("Caller is not admin")) -// // } -// // return Ok(true) -// // } - -// pub fn set_admin_guard( -// storage: &mut dyn Storage, -// info: MessageInfo, -// admin: Addr -// ) -> StdResult{ -// apply_admin_guard(&info.sender, storage)?; -// admin_w(storage).save(&admin)?; -// Ok(Response::default()) -// } diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/callback.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/callback.rs index 57c74952..c1f6074d 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/callback.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/callback.rs @@ -2,7 +2,7 @@ use cosmwasm_std::{Binary, CosmosMsg, WasmMsg}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use shade_protocol::Contract; +use crate::Contract; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] /// Info needed to have the other contract respond. diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/events.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/events.rs index 124d326f..cd95d3f4 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/events.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/events.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Event, StdError, StdResult}; +use crate::c_std::{Event, StdError, StdResult}; pub struct EventsParser; diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/mod.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/mod.rs index bfd3b455..eee0cd51 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/mod.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/mod.rs @@ -1,4 +1,4 @@ -mod admin; +// mod admin; mod callback; mod custom_fee; mod display; @@ -8,7 +8,7 @@ mod token_pair; mod token_pair_amount; mod token_type; mod viewing_keys; -pub use admin::*; +// pub use admin::*; pub use callback::*; pub use custom_fee::*; pub use display::*; diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/token_amount.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/token_amount.rs index 15a5f96d..2602376e 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/token_amount.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/token_amount.rs @@ -1,8 +1,8 @@ +use crate::swap::core::TokenType; use cosmwasm_std::StdResult; use cosmwasm_std::{MessageInfo, Uint128}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use shade_protocol::utils::liquidity_book::tokens::TokenType; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct TokenAmount { diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair.rs index 85719588..6888dbb2 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair.rs @@ -1,9 +1,10 @@ -use cosmwasm_std::{Deps, StdResult, Uint128}; +use crate::{ + c_std::{Deps, StdResult, Uint128}, + swap::core::{TokenPairAmount, TokenType}, + Contract, +}; use schemars::JsonSchema; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use shade_protocol::{utils::liquidity_book::tokens::TokenType, Contract}; - -use super::TokenPairAmount; #[derive(Clone, Debug, JsonSchema)] pub struct TokenPair(pub TokenType, pub TokenType, pub bool); diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair_amount.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair_amount.rs index db2da614..f892b468 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair_amount.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/token_pair_amount.rs @@ -1,10 +1,11 @@ #[warn(unused_imports)] -use cosmwasm_std::{MessageInfo, StdError, StdResult, Uint128}; +use crate::c_std::{MessageInfo, StdError, StdResult, Uint128}; +use crate::utils::liquidity_book::tokens::TokenType; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use shade_protocol::utils::liquidity_book::tokens::TokenType; -use super::TokenPair; +use crate::swap::core::TokenPair; + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct TokenPairAmount { pub pair: TokenPair, @@ -84,10 +85,10 @@ impl<'a> Iterator for TokenPairAmountIterator<'a> { } pub mod tests { - use cosmwasm_std::{Addr, Uint128}; - use shade_protocol::utils::liquidity_book::tokens::TokenType; + use crate::c_std::{Addr, Uint128}; + use crate::utils::liquidity_book::tokens::TokenType; - use crate::core::TokenPair; + use crate::swap::core::TokenPair; use super::TokenPairAmount; @@ -148,10 +149,8 @@ pub mod tests { }, false, ); - assert!( - reverse_amount - .create_new_pair_amount_to_match_order_of(&broken_pair) - .is_err() - ); + assert!(reverse_amount + .create_new_pair_amount_to_match_order_of(&broken_pair) + .is_err()); } } diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/token_type.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/token_type.rs index 03bd16ad..e0a9c12f 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/token_type.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/token_type.rs @@ -1,6 +1,6 @@ +use crate::utils::liquidity_book::tokens::TokenType; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use shade_protocol::utils::liquidity_book::tokens::TokenType; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct StableTokenData { diff --git a/packages/shade_protocol/src/contract_interfaces/swap/core/viewing_keys.rs b/packages/shade_protocol/src/contract_interfaces/swap/core/viewing_keys.rs index ac408fce..e6e9c1a5 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/core/viewing_keys.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/core/viewing_keys.rs @@ -1,10 +1,10 @@ -use cosmwasm_std::{Binary, Env, MessageInfo}; +use crate::c_std::{Binary, Env, MessageInfo}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt; use subtle::ConstantTimeEq; -use shade_protocol::utils::crypto::{sha_256, Prng}; +use crate::utils::crypto::{sha_256, Prng}; pub const VIEWING_KEY_SIZE: usize = 32; const VIEWING_KEY_PREFIX: &str = "api_key_"; diff --git a/packages/shade_protocol/src/contract_interfaces/swap/mod.rs b/packages/shade_protocol/src/contract_interfaces/swap/mod.rs index f49d55de..d809fc4b 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/mod.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/mod.rs @@ -1,4 +1,4 @@ -use core; +pub mod core; -use amm_pair; -use staking; +pub mod amm_pair; +pub mod staking; diff --git a/packages/shade_protocol/src/contract_interfaces/swap/staking.rs b/packages/shade_protocol/src/contract_interfaces/swap/staking.rs index f132b470..b000181d 100644 --- a/packages/shade_protocol/src/contract_interfaces/swap/staking.rs +++ b/packages/shade_protocol/src/contract_interfaces/swap/staking.rs @@ -1,12 +1,13 @@ +use crate::swap::core::{time, ContractInstantiationInfo, BLOCK_SIZE}; use crate::{ c_std::{ - Addr, Addr, Binary, CosmosMsg, Decimal256, OverflowError, QuerierWrapper, StdError, - StdResult, Storage, Uint128, Uint128, Uint256, Uint256, + Addr, Binary, CosmosMsg, Decimal256, OverflowError, QuerierWrapper, StdError, StdResult, + Storage, Uint128, Uint256, }, - contract_interfaces::snip20::ExecuteMsg as Snip20ExecuteMsg, cosmwasm_schema::{cw_serde, QueryResponses}, query_auth::QueryPermit, secret_storage_plus::{Bincode2, Item, ItemStorage, Map}, + snip20::ExecuteMsg as Snip20ExecuteMsg, snip20::Snip20ReceiveMsg, utils::{ asset::RawContract, liquidity_book::tokens::TokenType, ExecuteCallback, @@ -14,13 +15,14 @@ use crate::{ }, Contract, }; -use core::{time, ContractInstantiationInfo, BLOCK_SIZE}; use std::{cmp::min, collections::HashMap}; -use super::{ +/* +use crate::swap::core::{ ClaimRewardResponse, ClaimableRewardsResponse, ConfigResponse, PermitQueryResponse, RewardTokenInfo, }; +*/ impl InstantiateCallback for InstantiateMsg { const BLOCK_SIZE: usize = BLOCK_SIZE; diff --git a/packages/shade_protocol/src/utils/asset.rs b/packages/shade_protocol/src/utils/asset.rs index 013b8f25..08ecdd4b 100644 --- a/packages/shade_protocol/src/utils/asset.rs +++ b/packages/shade_protocol/src/utils/asset.rs @@ -1,11 +1,11 @@ -use std::vec; - use crate::{ - c_std::{Addr, Api, BalanceResponse, BankQuery, ContractInfo, Deps, StdResult, Uint128}, + c_std::{ + Addr, Api, BalanceResponse, BankQuery, ContractInfo, CosmosMsg, Deps, DepsMut, Env, + StdResult, Uint128, + }, + cosmwasm_schema::cw_serde, BLOCK_SIZE, }; -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{CosmosMsg, DepsMut, Env}; /// Validates an optional address. pub fn optional_addr_validate(api: &dyn Api, addr: Option) -> StdResult> { diff --git a/packages/shadeswap_shared/Cargo.toml b/packages/shadeswap_shared/Cargo.toml deleted file mode 100644 index 7fa3c2f9..00000000 --- a/packages/shadeswap_shared/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "shadeswap-shared" -version = "0.1.0" -authors = ["Tony "] -edition = "2021" - -exclude = [ - # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. - "contract.wasm", - "hash.txt", -] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -default = [] -utils = [] -staking = [] - -[dependencies] -schemars = "0.8.11" -serde = { version = "1.0.114", default-features = false, features = ["derive"] } -cosmwasm-std = { package = "secret-cosmwasm-std", version = "=1.1.11", features = ["iterator"] } -cosmwasm-storage = { package = "secret-cosmwasm-storage", version = "=1.1.11", features = ["iterator"] } -cosmwasm-schema = { version = "1.1.8" } -subtle = { version = "2.2.3", default-features = false } -query-authentication = { git = "https://github.com/securesecrets/query-authentication", branch = "cosmwasm_v1_upgrade" } -shade-protocol = { version = "0.1.0", path = "../shade_protocol", features = ["snip20", "admin", "query_auth", "airdrop","liquidity_book"] } - -better-secret-math = { git = "https://github.com/securesecrets/better-secret-math" } -secret-storage-plus = { git = "https://github.com/securesecrets/secret-plus-utils" } diff --git a/packages/shadeswap_shared/src/amm_pair.rs b/packages/shadeswap_shared/src/amm_pair.rs deleted file mode 100644 index 31600c9a..00000000 --- a/packages/shadeswap_shared/src/amm_pair.rs +++ /dev/null @@ -1,53 +0,0 @@ -use cosmwasm_std::{ - Addr, Decimal256, Uint256 -}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use crate::core::{ContractLink, TokenPair, Fee, TokenType}; -use shade_protocol::Contract; - -/// Represents the address of an exchange and the pair that it manages -#[derive(Serialize, Deserialize, JsonSchema, Clone, PartialEq, Debug)] -pub struct AMMPair { - /// The pair that the contract manages. - pub pair: TokenPair, - /// Address of the contract that manages the exchange. - pub address: Addr, - /// Used to enable or disable the AMMPair - pub enabled: bool -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct StableParams { - pub a: Decimal256, - pub gamma1: Uint256, - pub gamma2: Uint256, - pub oracle: Contract, -} - -#[derive(Serialize, Deserialize, JsonSchema, PartialEq, Debug,Clone)] -pub struct AMMSettings { - pub lp_fee: Fee, - pub shade_dao_fee: Fee, - pub stable_lp_fee: Fee, - pub stable_shade_dao_fee: Fee, - pub shade_dao_address: ContractLink -} - -pub fn generate_pair_key(pair: &TokenPair) -> Vec { - let mut bytes: Vec<&[u8]> = Vec::new(); - - match &pair.0 { - TokenType::NativeToken { denom, ..} => bytes.push(denom.as_bytes()), - TokenType::CustomToken { contract_addr, .. } => bytes.push(contract_addr.as_bytes()) - } - - match &pair.1 { - TokenType::NativeToken { denom, .. } => bytes.push(denom.as_bytes()), - TokenType::CustomToken { contract_addr, .. } => bytes.push(contract_addr.as_bytes()) - } - - bytes.sort(); - - bytes.concat() -} \ No newline at end of file diff --git a/packages/shadeswap_shared/src/helpers.rs b/packages/shadeswap_shared/src/helpers.rs deleted file mode 100644 index eb50b215..00000000 --- a/packages/shadeswap_shared/src/helpers.rs +++ /dev/null @@ -1,47 +0,0 @@ -use cosmwasm_std::{from_binary, Addr, Deps, QuerierWrapper, StdError, StdResult}; -use serde::de::DeserializeOwned; -use shade_protocol::{ - query_auth::{self, helpers::PermitAuthentication, QueryPermit}, - utils::Query, - Contract, -}; - -pub fn authenticate_permit( - deps: Deps, - permit: QueryPermit, - querier: &QuerierWrapper, - authenticator: Option, -) -> StdResult> { - let sender: Addr; - let revoked: bool; - match authenticator { - Some(a) => { - let res: query_auth::QueryAnswer = query_auth::QueryMsg::ValidatePermit { - permit: permit.clone(), - } - .query(querier, &a)?; - - match res { - query_auth::QueryAnswer::ValidatePermit { user, is_revoked } => { - sender = user; - revoked = is_revoked; - } - _ => return Err(StdError::generic_err("Wrong query response")), - } - - Ok(PermitAuthentication { - sender, - revoked, - data: from_binary(&permit.params.data)?, - }) - } - None => { - sender = permit.validate(deps.api, None)?.as_addr(None)?; - Ok(PermitAuthentication { - sender, - revoked: false, - data: from_binary(&permit.params.data)?, - }) - } - } -} diff --git a/packages/shadeswap_shared/src/lib.rs b/packages/shadeswap_shared/src/lib.rs deleted file mode 100644 index 0dde33a7..00000000 --- a/packages/shadeswap_shared/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -mod helpers; -pub mod msg; -pub use msg::*; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -pub mod core; -// Forward important libs to avoid constantly importing them in the cargo crates, could help reduce compile times -pub mod c_std { - pub use cosmwasm_std::*; -} -pub use shade_protocol::{admin, airdrop, query_auth, snip20, utils}; -pub const BLOCK_SIZE: usize = 256; -pub use helpers::*; -pub use serde; - -#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)] -pub struct Pagination { - pub start: u64, - pub limit: u8, -} diff --git a/packages/shadeswap_shared/src/msg/mod.rs b/packages/shadeswap_shared/src/msg/mod.rs deleted file mode 100644 index 53a3851f..00000000 --- a/packages/shadeswap_shared/src/msg/mod.rs +++ /dev/null @@ -1,585 +0,0 @@ -use crate::core::ContractInstantiationInfo; -use cosmwasm_std::Addr; -use cosmwasm_std::Binary; -use cosmwasm_std::Uint128; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use shade_protocol::{ - utils::{ExecuteCallback, InstantiateCallback, Query}, - BLOCK_SIZE, -}; - -pub mod staking; - -pub mod router { - - use super::*; - use crate::core::TokenAmount; - use shade_protocol::{ - liquidity_book::lb_pair::SwapResult, snip20::Snip20ReceiveMsg, - utils::liquidity_book::tokens::TokenType, Contract, - }; - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum ExecuteMsgResponse { - SwapResult { - amount_in: Uint128, - amount_out: Uint128, - }, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum InvokeMsg { - SwapTokensForExact { - path: Vec, - expected_return: Option, - recipient: Option, - }, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - pub struct InitMsg { - pub prng_seed: Binary, - pub entropy: Binary, - pub admin_auth: Contract, - pub airdrop_address: Option, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - pub struct Hop { - pub addr: String, - pub code_hash: String, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum ExecuteMsg { - // SNIP20 receiver interface - Receive(Snip20ReceiveMsg), - SwapTokensForExact { - /// The token type to swap from. - offer: TokenAmount, - expected_return: Option, - path: Vec, - recipient: Option, - padding: Option, - }, - RegisterSNIP20Token { - token_addr: String, - token_code_hash: String, - oracle_key: Option, - padding: Option, - }, - RecoverFunds { - token: TokenType, - amount: Uint128, - to: String, - msg: Option, - padding: Option, - }, - SetConfig { - admin_auth: Option, - padding: Option, - }, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum QueryMsg { - SwapSimulation { - offer: TokenAmount, - path: Vec, - exclude_fee: Option, - }, - GetConfig {}, - RegisteredTokens {}, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum QueryMsgResponse { - SwapSimulation { - total_fee_amount: Uint128, - lp_fee_amount: Uint128, - shade_dao_fee_amount: Uint128, - result: SwapResult, - price: String, - }, - GetConfig { - admin_auth: Contract, - airdrop_address: Option, - }, - RegisteredTokens { - tokens: Vec, - }, - } - - impl InstantiateCallback for InitMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } - - impl ExecuteCallback for ExecuteMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } - - impl Query for QueryMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } -} - -pub mod amm_pair { - use std::fmt::{Debug, Display}; - - use super::*; - use crate::{ - core::{ - ContractInstantiationInfo, CustomFee, Fee, StableTokenData, TokenAmount, TokenPair, - TokenPairAmount, - }, - staking::StakingContractInstantiateInfo, - }; - use cosmwasm_std::{Addr, Decimal256, Uint256}; - use schemars::JsonSchema; - use serde::{Deserialize, Serialize}; - use shade_protocol::{ - liquidity_book::lb_pair::SwapResult, snip20::Snip20ReceiveMsg, utils::asset::RawContract, - utils::liquidity_book::tokens::TokenType, Contract, - }; - - /// Represents the address of an exchange and the pair that it manages - #[derive(Serialize, Deserialize, JsonSchema, Clone, PartialEq, Debug)] - pub struct AMMPair { - /// The pair that the contract manages. - pub pair: TokenPair, - /// Address of the contract that manages the exchange. - pub address: Addr, - // Code hash of the AMM Pair - pub code_hash: String, - /// Used to enable or disable the AMMPair - pub enabled: bool, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug, Clone, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum ContractStatus { - Active, // allows all operations - FreezeAll, // blocks everything except admin-protected config changes - LpWithdrawOnly, // blocks everything except LP withdraws and admin-protected config changes - } - - impl Display for ContractStatus { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Debug::fmt(self, f) - } - } - - #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, JsonSchema)] - pub struct CustomIterationControls { - pub epsilon: Uint256, // assumed to have same decimals as SignedDecimal - pub max_iter_newton: u16, - pub max_iter_bisect: u16, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - pub struct StableParams { - pub a: Decimal256, - pub gamma1: Uint256, - pub gamma2: Uint256, - pub oracle: Contract, - pub min_trade_size_x_for_y: Decimal256, - pub min_trade_size_y_for_x: Decimal256, - pub max_price_impact_allowed: Decimal256, - pub custom_iteration_controls: Option, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - pub struct StablePairInfoResponse { - pub stable_params: StableParams, - pub stable_token0_data: StableTokenData, - pub stable_token1_data: StableTokenData, - //p is optional so that the PairInfo query can still return even when the calculation of p fails - pub p: Option, - } - - #[derive(Serialize, Deserialize, JsonSchema, PartialEq, Debug, Clone)] - pub struct AMMSettings { - pub lp_fee: Fee, - pub shade_dao_fee: Fee, - pub stable_lp_fee: Fee, - pub stable_shade_dao_fee: Fee, - pub shade_dao_address: Contract, - } - - pub fn generate_pair_key(pair: &TokenPair) -> Vec { - let mut bytes: Vec<&[u8]> = Vec::new(); - let mut values: Vec = Vec::new(); - - values.push(pair.0.unique_key()); - values.push(pair.1.unique_key()); - values.push(pair.2.to_string()); - values.sort(); - bytes.push(values[0].as_bytes()); - bytes.push(values[1].as_bytes()); - bytes.push(values[2].as_bytes()); - bytes.concat() - } - - #[derive(Serialize, Deserialize, PartialEq, Debug, JsonSchema, Clone)] - pub struct SwapInfo { - pub total_fee_amount: Uint128, - pub lp_fee_amount: Uint128, - pub shade_dao_fee_amount: Uint128, - pub result: SwapResult, - pub price: String, - pub new_input_pool: Uint128, - pub new_output_pool: Uint128, - pub index_of_input_token: u8, - pub index_of_output_token: u8, - } - - pub struct VirtualSwapResponse { - pub output: TokenPairAmount, - pub swap_info: Option, - } - - #[derive(Serialize, Deserialize, PartialEq, Clone, Debug, JsonSchema)] - pub struct FeeInfo { - pub shade_dao_address: Addr, - pub lp_fee: Fee, - pub shade_dao_fee: Fee, - pub stable_lp_fee: Fee, - pub stable_shade_dao_fee: Fee, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - pub struct InitMsg { - pub pair: TokenPair, - pub token0_oracle_key: Option, - pub token1_oracle_key: Option, - pub lp_token_contract: ContractInstantiationInfo, - // Leave none if initializing without factory - pub factory_info: Option, - pub prng_seed: Binary, - pub entropy: Binary, - pub admin_auth: Contract, - pub staking_contract: Option, - pub custom_fee: Option, - pub stable_params: Option, - pub lp_token_decimals: u8, - pub lp_token_custom_label: Option, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum ExecuteMsg { - AddLiquidityToAMMContract { - deposit: TokenPairAmount, - expected_return: Option, - staking: Option, - execute_sslp_virtual_swap: Option, - padding: Option, - }, - SwapTokens { - /// The token type to swap from. - offer: TokenAmount, - expected_return: Option, - to: Option, - padding: Option, - }, - // SNIP20 receiver interface - Receive(Snip20ReceiveMsg), - AddWhiteListAddress { - address: String, - padding: Option, - }, - RemoveWhitelistAddresses { - addresses: Vec, - padding: Option, - }, - SetConfig { - admin_auth: Option, - padding: Option, - }, - SetStableParams { - stable_params: Option, - padding: Option, - }, - SetCustomPairFee { - custom_fee: Option, - padding: Option, - }, - SetViewingKey { - viewing_key: String, - padding: Option, - }, - SetOracleKeyAndDecimals { - token: TokenType, - oracle_key: String, - padding: Option, - }, - SetStakingContract { - staking: RawContract, - padding: Option, - }, - SetContractStatus { - contract_status: ContractStatus, - padding: Option, - }, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum ExecuteMsgResponse { - SwapResult { - price: String, - amount_in: Uint128, - amount_out: Uint128, - total_fee_amount: Uint128, - lp_fee_amount: Uint128, - shade_dao_fee_amount: Uint128, - }, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum InvokeMsg { - SwapTokens { - expected_return: Option, - to: Option, - padding: Option, - }, - RemoveLiquidity { - /// If sender is removing LP for someone else, from should contain who that someone is - from: Option, - single_sided_withdraw_type: Option, //None means 50/50 balanced withdraw, and a value here tells which token to send the withdraw in - single_sided_expected_return: Option, //this field will be ignored on balanced withdraws - padding: Option, - }, - } - #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)] - #[serde(rename_all = "snake_case")] - pub enum QueryMsg { - GetConfig {}, - GetPairInfo {}, - GetWhiteListAddress {}, - GetTradeCount {}, - SwapSimulation { - offer: TokenAmount, - exclude_fee: Option, - }, - GetShadeDaoInfo {}, - GetEstimatedLiquidity { - deposit: TokenPairAmount, - sender: Addr, - execute_sslp_virtual_swap: Option, - }, - GetContractStatus {}, - } - - #[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq)] - #[serde(rename_all = "snake_case")] - pub enum QueryMsgResponse { - GetPairInfo { - liquidity_token: Contract, - factory: Option, - pair: TokenPair, - amount_0: Uint128, - amount_1: Uint128, - total_liquidity: Uint128, - contract_version: u32, - fee_info: FeeInfo, - stable_info: Option, - }, - GetWhiteListAddress { - addresses: Vec, - }, - GetTradeCount { - count: u64, - }, - GetClaimReward { - amount: Uint128, - }, - GetEstimatedPrice { - estimated_price: String, - }, - SwapSimulation { - total_fee_amount: Uint128, - lp_fee_amount: Uint128, - shade_dao_fee_amount: Uint128, - result: SwapResult, - price: String, - }, - GetShadeDaoInfo { - shade_dao_address: String, - shade_dao_fee: Fee, - lp_fee: Fee, - admin_auth: Contract, - }, - GetEstimatedLiquidity { - lp_token: Uint128, - tokens_returned: Option, - total_lp_token: Uint128, - }, - GetConfig { - factory_contract: Option, - lp_token: Contract, - staking_contract: Option, - pair: TokenPair, - custom_fee: Option, - }, - GetContractStatus { - contract_status: ContractStatus, - }, - } - - impl InstantiateCallback for InitMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } - - impl ExecuteCallback for ExecuteMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } - - impl Query for QueryMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } -} - -pub mod factory { - use super::*; - use crate::amm_pair::{AMMPair, StableParams}; - use crate::core::TokenPair; - use crate::staking::StakingContractInstantiateInfo; - use crate::{amm_pair::AMMSettings, Pagination}; - use schemars::JsonSchema; - use serde::{Deserialize, Serialize}; - use shade_protocol::Contract; - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - pub struct InitMsg { - pub pair_contract: ContractInstantiationInfo, - pub amm_settings: AMMSettings, - pub lp_token_contract: ContractInstantiationInfo, - pub prng_seed: Binary, - pub api_key: String, - //Set the default authenticator for all permits on the contracts - pub authenticator: Option, - pub admin_auth: Contract, - } - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] - #[serde(rename_all = "snake_case")] - pub enum ExecuteMsg { - SetConfig { - pair_contract: Option, - lp_token_contract: Option, - amm_settings: Option, - api_key: Option, - admin_auth: Option, - padding: Option, - }, - CreateAMMPair { - pair: TokenPair, - entropy: Binary, - staking_contract: Option, - stable_params: Option, - token0_oracle_key: Option, - token1_oracle_key: Option, - lp_token_decimals: u8, - amm_pair_custom_label: Option, - lp_token_custom_label: Option, - padding: Option, - }, - AddAMMPairs { - amm_pairs: Vec, - padding: Option, - }, - } - - #[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq)] - #[serde(rename_all = "snake_case")] - pub enum QueryResponse { - ListAMMPairs { - amm_pairs: Vec, - }, - GetConfig { - pair_contract: ContractInstantiationInfo, - amm_settings: AMMSettings, - lp_token_contract: ContractInstantiationInfo, - authenticator: Option, - admin_auth: Contract, - }, - GetAMMPairAddress { - address: String, - }, - AuthorizeApiKey { - authorized: bool, - }, - } - - #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)] - #[serde(rename_all = "snake_case")] - pub enum QueryMsg { - // GetCount returns the current count as a json-encoded number - ListAMMPairs { pagination: Pagination }, - GetAMMPairAddress { pair: TokenPair }, - GetConfig {}, - AuthorizeApiKey { api_key: String }, - } - - impl InstantiateCallback for InitMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } - - impl ExecuteCallback for ExecuteMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } - - impl Query for QueryMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } -} - -pub mod lp_token { - - use shade_protocol::contract_interfaces::snip20::InitialBalance; - - use super::*; - - #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] - pub struct InitConfig { - /// Indicates whether the total supply is public or should be kept secret. - /// default: False - pub public_total_supply: Option, - /// Indicates whether deposit functionality should be enabled - /// default: False - pub enable_deposit: Option, - /// Indicates whether redeem functionality should be enabled - /// default: False - pub enable_redeem: Option, - /// Indicates whether mint functionality should be enabled - /// default: False - pub enable_mint: Option, - /// Indicates whether burn functionality should be enabled - /// default: False - pub enable_burn: Option, - } - - #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] - pub struct InstantiateMsg { - pub name: String, - pub admin: Option, - pub symbol: String, - pub decimals: u8, - pub initial_balances: Option>, - pub prng_seed: Binary, - pub config: Option, - pub supported_denoms: Option>, - } - - impl InstantiateCallback for InstantiateMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; - } -} diff --git a/packages/shadeswap_shared/src/msg/staking.rs b/packages/shadeswap_shared/src/msg/staking.rs deleted file mode 100644 index 9536d9e2..00000000 --- a/packages/shadeswap_shared/src/msg/staking.rs +++ /dev/null @@ -1,668 +0,0 @@ -use crate::{core::ContractInstantiationInfo, BLOCK_SIZE}; -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, Binary, Uint128, Uint256}; -use shade_protocol::{ - query_auth::QueryPermit, - snip20::Snip20ReceiveMsg, - utils::liquidity_book::tokens::TokenType, - utils::{asset::RawContract, ExecuteCallback, InstantiateCallback, Query}, - Contract, -}; -#[cfg(feature = "staking")] -pub use state::*; - -impl InstantiateCallback for InstantiateMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; -} - -impl ExecuteCallback for ExecuteMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; -} - -impl Query for QueryMsg { - const BLOCK_SIZE: usize = BLOCK_SIZE; -} - -#[cw_serde] -pub struct StakingContractInstantiateInfo { - pub staking_contract_info: ContractInstantiationInfo, - pub custom_label: Option, - pub first_reward_token: Option, - pub query_auth: Option, -} - -#[cw_serde] -pub struct InstantiateMsg { - pub amm_pair: String, - pub lp_token: RawContract, - pub admin_auth: RawContract, - pub query_auth: Option, - pub first_reward_token: Option, -} - -#[cw_serde] -pub enum ExecuteMsg { - ClaimRewards { - padding: Option, - }, - Unstake { - amount: Uint128, - remove_liquidity: Option, - padding: Option, - }, - Receive(Snip20ReceiveMsg), - UpdateRewardTokens(Vec), - CreateRewardTokens(Vec), - UpdateConfig { - admin_auth: Option, - query_auth: Option, - padding: Option, - }, - RecoverFunds { - token: TokenType, - amount: Uint128, - to: String, - msg: Option, - padding: Option, - }, -} - -#[cw_serde] -pub enum InvokeMsg { - /// From is used to determine the staker since this can be called by the AMMPair when auto staking. - Stake { - from: Option, - padding: Option, - }, -} - -#[cw_serde] -pub struct RewardTokenUpdate { - pub reward_token: RawContract, - pub index: u64, - pub valid_to: u64, -} - -#[cw_serde] -pub struct RewardTokenCreate { - pub reward_token: RawContract, - pub daily_reward_amount: Uint128, - pub valid_to: u64, -} - -#[allow(clippy::large_enum_variant)] -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - #[returns(ConfigResponse)] - GetConfig {}, - #[returns(PermitQueryResponse)] - WithPermit { - permit: QueryPermit, - query: AuthQuery, - }, -} - -#[cw_serde] -pub struct QueryPermitData {} - -#[cw_serde] -pub enum AuthQuery { - GetStakerInfo {}, -} - -#[derive(PartialEq, Debug, Clone)] -pub struct ClaimRewardResponse { - pub token: Contract, - pub amount: Uint128, -} - -// RESPONSE TYPES - -#[cw_serde] -pub struct ConfigResponse { - pub lp_token: Contract, - pub amm_pair: Addr, - pub admin_auth: Contract, - pub query_auth: Option, - pub total_amount_staked: Uint128, - pub reward_tokens: Vec, -} - -#[cw_serde] -pub enum PermitQueryResponse { - StakerInfo { - /// Amount normally staked. - staked: Uint128, - /// Staked - total_staked: Uint128, - claimable_rewards: Vec, - }, -} - -#[cw_serde] -pub struct ClaimableRewardsResponse { - pub token: Contract, - pub amount: Uint128, -} - -#[cw_serde] -pub struct RewardTokenInfo { - pub token: Contract, - pub decimals: u8, - pub reward_per_second: Uint256, - pub reward_per_staked_token: Uint256, - pub valid_to: u64, - pub last_updated: u64, -} - -impl RewardTokenUpdate { - pub fn new(reward_token: impl Into, index: u64, valid_to: u64) -> Self { - Self { - reward_token: reward_token.into(), - index, - valid_to, - } - } -} - -impl RewardTokenCreate { - pub fn new( - reward_token: impl Into, - daily_reward_amount: Uint128, - valid_to: u64, - ) -> Self { - Self { - reward_token: reward_token.into(), - daily_reward_amount, - valid_to, - } - } -} - -#[cfg(feature = "staking")] -pub mod state { - use better_secret_math::{ - common::{bankers_round, exp10, muldiv}, - ud60x18::mul, - U256, - }; - use core::time; - use cosmwasm_schema::cw_serde; - use cosmwasm_std::{ - Addr, CosmosMsg, Decimal256, OverflowError, QuerierWrapper, StdError, StdResult, Storage, - Uint128, Uint256, - }; - use secret_storage_plus::{Bincode2, Item, ItemStorage, Map}; - use shade_protocol::{ - contract_interfaces::snip20::ExecuteMsg as Snip20ExecuteMsg, utils::ExecuteCallback, - Contract, - }; - use std::{cmp::min, collections::HashMap}; - - use super::{ - ClaimRewardResponse, ClaimableRewardsResponse, ConfigResponse, PermitQueryResponse, - RewardTokenInfo, - }; - - /// Manages the global state of the staking contract. - #[cw_serde] - pub struct Custodian { - pub lp_token: Contract, - pub amm_pair: Addr, - pub admin_auth: Contract, - pub query_auth: Option, - pub total_amount_staked: Uint128, - } - - impl ItemStorage for Custodian { - const ITEM: Item<'static, Self> = Item::new("custodian"); - } - - #[cw_serde] - pub struct RewardTokenSet(Vec); - - impl RewardTokenSet { - pub fn insert(&mut self, addr: &Addr) { - if !self.0.contains(addr) { - self.0.push(addr.clone()); - } - } - pub fn get(&self) -> &[Addr] { - self.0.as_slice() - } - } - - impl<'a> Custodian { - pub const STAKERS: Map<'static, &'a Addr, u128, Bincode2> = Map::new("stakers"); - pub const REWARD_TOKEN_INFO: Map<'static, &'a Addr, Vec> = - Map::new("reward_token_info"); - pub const REWARD_TOKENS: Item<'static, RewardTokenSet> = Item::new("reward_tokens"); - } - - impl Custodian { - pub fn require_lp_token(&self, addr: &Addr) -> StdResult<()> { - if self.lp_token.address.eq(addr) { - return Ok(()); - } - Err(StdError::generic_err(format!( - "Must stake the LP token {}. Attempted to stake {addr}.", - self.lp_token.address - ))) - } - pub fn save_staker(storage: &mut dyn Storage, staker: &Staker) -> StdResult<()> { - staker.save_rewards(storage)?; - Self::STAKERS.save(storage, &staker.addr, &staker.staked.u128()) - } - } - - impl Custodian { - pub fn store_empty_reward_set(&self, storage: &mut dyn Storage) -> StdResult<()> { - match Self::REWARD_TOKENS.may_load(storage)? { - Some(_) => Err(StdError::generic_err("Reward token storage already exists")), - None => Self::REWARD_TOKENS.save(storage, &RewardTokenSet(vec![])), - } - } - - pub fn update_reward_token( - &self, - now: u64, - storage: &mut dyn Storage, - token: &Contract, - index: u64, - valid_to: u64, - ) -> StdResult> { - if valid_to < now { - return Err(StdError::generic_err("valid_to cannot be in the past")); - } - let mut reward_configs = Self::REWARD_TOKEN_INFO.load(storage, &token.address)?; - match reward_configs.get_mut(index as usize) { - Some(info) => { - info.valid_to = valid_to; - } - None => return Err(StdError::generic_err("Invalid index")), - }; - Self::REWARD_TOKEN_INFO.save(storage, &token.address, &reward_configs)?; - Ok(reward_configs) - } - - pub fn create_reward_token( - &self, - storage: &mut dyn Storage, - now: u64, - token: &Contract, - daily_emission_amount: Uint128, - valid_to: u64, - decimals: u8, - ) -> StdResult> { - let mut reward_configs = - match Self::REWARD_TOKEN_INFO.may_load(storage, &token.address)? { - Some(rewards) => rewards, - None => vec![], - }; - let info = RewardTokenInfo::init_from_daily_rewards( - now, - token, - decimals, - daily_emission_amount, - valid_to, - )?; - match Self::REWARD_TOKENS.may_load(storage)? { - Some(mut tokens) => { - tokens.insert(&info.token.address); - Self::REWARD_TOKENS.save(storage, &tokens)?; - } - None => Self::REWARD_TOKENS - .save(storage, &RewardTokenSet(vec![info.token.address.clone()]))?, - }; - reward_configs.push(info); - Self::REWARD_TOKEN_INFO.save(storage, &token.address, &reward_configs)?; - Ok(reward_configs) - } - - pub fn to_config_response(self, storage: &dyn Storage) -> StdResult { - let tokens = Self::REWARD_TOKENS.load(storage)?; - let mut infos = Vec::with_capacity(tokens.0.len()); - for token in tokens.0 { - if let Some(reward_configs) = Self::REWARD_TOKEN_INFO.may_load(storage, &token)? { - for info in reward_configs { - let info = info.to_response()?; - infos.push(info); - } - } - } - Ok(ConfigResponse { - lp_token: self.lp_token, - amm_pair: self.amm_pair, - admin_auth: self.admin_auth, - query_auth: self.query_auth, - reward_tokens: infos, - total_amount_staked: self.total_amount_staked, - }) - } - - pub fn update_reward_per_token( - &self, - now: u64, - info: &mut RewardTokenInfo, - ) -> StdResult { - info.update_reward_per_token(now, self.total_amount_staked) - } - - pub fn may_load_staker(storage: &dyn Storage, user: &Addr) -> StdResult> { - if let Some(staked) = Self::STAKERS.may_load(storage, user)? { - Ok(Some(Staker { - addr: user.clone(), - staked: Uint128::new(staked), - claimable_rewards: HashMap::default(), - })) - } else { - Ok(None) - } - } - } - - impl RewardTokenInfo { - pub const SECONDS_IN_DAY: U256 = U256::new(24u128 * 3600u128); - pub const MAX_DECIMALS: U256 = exp10(18); - - pub fn normalize_amount(amount: impl Into) -> StdResult { - let amount: U256 = amount.into(); - amount - .checked_mul(Self::MAX_DECIMALS) - .ok_or_else(|| StdError::generic_err("Overflow")) - } - - pub fn denormalize_amount(amount: impl Into) -> StdResult { - let amount: U256 = amount.into(); - amount - .checked_div(Self::MAX_DECIMALS) - .ok_or_else(|| StdError::generic_err("Overflow")) - } - - pub fn init_from_daily_rewards( - now: u64, - token: &Contract, - decimals: u8, - daily_emission_amount: Uint128, - valid_to: u64, - ) -> StdResult { - let daily_emission_amount = Self::normalize_amount(daily_emission_amount)?; - Ok(Self { - token: token.clone(), - decimals, - reward_per_second: (daily_emission_amount / Self::SECONDS_IN_DAY).into(), - valid_to, - reward_per_staked_token: Uint256::zero(), - last_updated: now, - }) - } - - pub fn update_reward_per_second( - &mut self, - daily_emission_amount: Uint128, - ) -> StdResult<()> { - let daily_emission_amount = Self::normalize_amount(daily_emission_amount)?; - self.reward_per_second = (daily_emission_amount / Self::SECONDS_IN_DAY).into(); - Ok(()) - } - - /// Denormalizes the reward per second and reward per token stored. - pub fn to_response(&self) -> StdResult { - Ok(RewardTokenInfo { - token: self.token.clone(), - decimals: self.decimals, - reward_per_second: Self::denormalize_amount(self.reward_per_second)?.into(), - valid_to: self.valid_to, - reward_per_staked_token: Self::denormalize_amount(self.reward_per_staked_token)? - .into(), - last_updated: self.last_updated, - }) - } - - /// recalculates reward per staked token - pub fn update_reward_per_token( - &mut self, - now: u64, - total_staked: Uint128, - ) -> StdResult { - let min_time_rewards_applicable = min(now, self.valid_to); - if !total_staked.is_zero() && min_time_rewards_applicable > self.last_updated { - let time_since_updated = - U256::new((min_time_rewards_applicable - self.last_updated).into()); - let total_staked = U256::new(total_staked.u128()); - let rewards_since_updated = muldiv( - time_since_updated, - self.reward_per_second.into(), - total_staked, - )?; - self.reward_per_staked_token = self - .reward_per_staked_token - .checked_add(rewards_since_updated.into())?; - } - self.last_updated = min_time_rewards_applicable; - Ok(self.reward_per_staked_token) - } - } - - #[cw_serde] - pub struct Staker { - pub addr: Addr, - pub staked: Uint128, - pub claimable_rewards: HashMap>, - } - - impl Staker { - pub fn new(addr: &Addr) -> Self { - Self { - addr: addr.clone(), - staked: Uint128::zero(), - claimable_rewards: HashMap::default(), - } - } - } - - #[cw_serde] - pub struct ClaimableRewardsInfo { - pub info: RewardTokenInfo, - pub amount: Uint128, - pub last_reward_per_staked_token_paid: Uint256, - } - - impl ClaimableRewardsInfo { - pub fn new(info: &RewardTokenInfo) -> Self { - Self { - info: info.clone(), - amount: Uint128::zero(), - last_reward_per_staked_token_paid: Uint256::zero(), - } - } - } - - impl<'a> Staker { - pub const REWARDS: Map<'static, (&'a Addr, &'a Addr), Vec> = - Map::new("staker_rewards"); - } - - impl Staker { - pub fn get_rewards_key<'a>(&'a self, reward_token: &'a Addr) -> (&'a Addr, &'a Addr) { - (reward_token, &self.addr) - } - - pub fn total_staked(&self) -> Uint128 { - self.staked - } - - pub fn stake( - &mut self, - storage: &mut dyn Storage, - amount: impl Into + Copy, - ) -> StdResult { - let amount = amount.into(); - self.staked = self.staked.checked_add(amount)?; - Ok(amount) - } - - pub fn unstake( - &mut self, - storage: &mut dyn Storage, - amount: impl Into + Copy, - ) -> StdResult { - let amount = amount.into(); - self.staked = self.staked.checked_sub(amount)?; - Ok(amount) - } - - //called once per reward token type, loads data from storage into staker object, updating claimable amounts - pub fn update_claimable_rewards( - &mut self, - storage: &dyn Storage, - reward_infos: &Vec, - reward_token_address: Addr, - ) -> StdResult<()> { - let rewards_key = self.get_rewards_key(&reward_token_address); - let mut claimable_rewards = match Self::REWARDS.may_load(storage, rewards_key)? { - Some(data) => data, - None => vec![], - }; - - for i in claimable_rewards.len()..reward_infos.len() { - claimable_rewards.push(ClaimableRewardsInfo::new(&reward_infos[i])) - } - if claimable_rewards.len() != reward_infos.len() { - return Err(StdError::generic_err( - "Off by one error in reward list padding", - )); - } - for (reward_info, mut claimable_reward) in - reward_infos.into_iter().zip(claimable_rewards.into_iter()) - { - if reward_info.token.address != reward_token_address { - return Err(StdError::generic_err( - "Update claimable rewards bad reward token address", - )); - } - if reward_info.reward_per_staked_token - > claimable_reward.last_reward_per_staked_token_paid - { - let reward_per_staked_token_earned = reward_info.reward_per_staked_token - - claimable_reward.last_reward_per_staked_token_paid; - let normalized_amount_earned = - reward_per_staked_token_earned.checked_mul(self.total_staked().into())?; - let reward_amount_earned = - RewardTokenInfo::denormalize_amount(normalized_amount_earned)?; - claimable_reward.amount = claimable_reward - .amount - .checked_add(reward_amount_earned.into())?; - claimable_reward.last_reward_per_staked_token_paid = - reward_info.reward_per_staked_token; - } - - //load update claimable reward into object - match self.claimable_rewards.get_mut(&reward_info.token.address) { - Some(list) => list.push(claimable_reward.clone()), - None => { - let list = vec![claimable_reward.clone()]; - self.claimable_rewards - .insert(reward_info.token.address.clone(), list); - } - } - } - Ok(()) - } - - /// write data from staker object to contract storage - pub fn save_rewards(&self, storage: &mut dyn Storage) -> StdResult<()> { - for reward in &self.claimable_rewards { - let rewards_key = self.get_rewards_key(&reward.0); - Self::REWARDS.save(storage, rewards_key, &reward.1)?; - } - Ok(()) - } - - /// send all claimable rewards to staker and save 0 into claimable rewards storage - pub fn claim_and_save_rewards( - &self, - storage: &mut dyn Storage, - ) -> StdResult<(Vec, Vec)> { - let mut response_data = vec![]; - let mut msgs = vec![]; - for rewards in self.claimable_rewards.iter() { - let mut claimable_rewards = vec![]; - for reward in rewards.1 { - if !reward.amount.is_zero() { - response_data.push(ClaimRewardResponse { - token: reward.info.token.clone(), - amount: reward.amount, - }); - msgs.push( - Snip20ExecuteMsg::Send { - recipient: self.addr.to_string(), - recipient_code_hash: None, - amount: reward.amount, - msg: None, - memo: None, - padding: None, - } - .to_cosmos_msg(&reward.info.token, vec![])?, - ); - } - claimable_rewards.push(ClaimableRewardsInfo { - info: reward.info.clone(), - amount: Uint128::zero(), - last_reward_per_staked_token_paid: reward.last_reward_per_staked_token_paid, - }); - } - - let rewards_key = self.get_rewards_key(rewards.0); - Self::REWARDS.save(storage, rewards_key, &claimable_rewards)?; - } - Ok((msgs, response_data)) - } - - pub fn to_staker_info_response(self) -> StdResult { - let mut all_rewards = vec![]; - for (_, rewards) in &self.claimable_rewards { - all_rewards.append( - &mut rewards - .into_iter() - .map(|r| ClaimableRewardsResponse { - token: r.info.token.clone(), - amount: r.amount, - }) - .collect(), - ); - } - Ok(PermitQueryResponse::StakerInfo { - staked: self.staked, - total_staked: self.total_staked(), - claimable_rewards: all_rewards, - }) - } - } - - #[cfg(test)] - mod test { - use super::*; - - #[cfg(feature = "staking")] - #[test] - fn test_max_emission_rate_no_panic() { - let high_emissions = Uint128::new(exp10(77).as_u128()); - let info = RewardTokenInfo::init_from_daily_rewards( - 1u64, - &Contract::default(), - 18u8, - high_emissions, - 1u64, - ) - .unwrap(); - let info = info.to_response().unwrap(); - let rps: Uint128 = info.reward_per_second.try_into().unwrap(); - assert_eq!( - rps, - high_emissions / Uint128::new(RewardTokenInfo::SECONDS_IN_DAY.as_u128()) - ); - } - } -}