diff --git a/contracts/alliance-hub/src/tests/stake_unstake.rs b/contracts/alliance-hub/src/tests/stake_unstake.rs index 244a899..445b141 100644 --- a/contracts/alliance-hub/src/tests/stake_unstake.rs +++ b/contracts/alliance-hub/src/tests/stake_unstake.rs @@ -99,7 +99,10 @@ fn test_stake_invalid() { let msg = ExecuteMsg::Stake {}; let info = mock_info("user1", &[coin(100, "asset2")]); let err = execute(deps.as_mut(), mock_env(), info, msg).unwrap_err(); - assert_eq!(err, ContractError::AssetNotWhitelisted("native:asset2".to_string())); + assert_eq!( + err, + ContractError::AssetNotWhitelisted("native:asset2".to_string()) + ); // Stake multiple assets in a single call let msg = ExecuteMsg::Stake {}; diff --git a/contracts/alliance-lp-hub/src/astro_models.rs b/contracts/alliance-lp-hub/src/astro_models.rs index b8be30a..03b4a9b 100644 --- a/contracts/alliance-lp-hub/src/astro_models.rs +++ b/contracts/alliance-lp-hub/src/astro_models.rs @@ -1,10 +1,8 @@ -use cosmwasm_schema::{QueryResponses, cw_serde}; -use cosmwasm_std::{Decimal, Addr, Uint128}; +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{Addr, Decimal, Uint128}; use cw20::Cw20ReceiveMsg; use cw_asset::AssetInfo; - - #[cw_serde] pub enum ExecuteAstroMsg { /// Receives a message of type [`Cw20ReceiveMsg`]. Handles cw20 LP token deposits. @@ -29,7 +27,6 @@ pub enum Cw20Msg { DepositFor(String), } - #[cw_serde] #[derive(QueryResponses)] pub enum QueryAstroMsg { @@ -85,4 +82,4 @@ pub enum AstroAssetInfo { Token { contract_addr: Addr }, /// Native token NativeToken { denom: String }, -} \ No newline at end of file +} diff --git a/contracts/alliance-lp-hub/src/contract.rs b/contracts/alliance-lp-hub/src/contract.rs index 13625e8..bc3dbf7 100644 --- a/contracts/alliance-lp-hub/src/contract.rs +++ b/contracts/alliance-lp-hub/src/contract.rs @@ -193,7 +193,7 @@ fn stake( deps.storage, sender.clone(), received_asset.info.clone(), - reward_token, + reward_token.clone(), )?; if !rewards.is_zero() { UNCLAIMED_REWARDS.update( @@ -285,6 +285,15 @@ fn stake( Ok(balance.unwrap_or(Uint128::zero()) + received_asset.amount) }, )?; + + let asset_reward_rate = ASSET_REWARD_RATE + .load(deps.storage, (asset_key.clone(), reward_token.clone())) + .unwrap_or(Decimal::zero()); + USER_ASSET_REWARD_RATE.save( + deps.storage, + (sender, asset_key, reward_token), + &asset_reward_rate, + )?; Ok(res) } @@ -360,7 +369,7 @@ fn claim_rewards( ) -> Result { let user = info.sender; let config = CONFIG.load(deps.storage)?; - let reward_token = AssetInfoKey::from(AssetInfo::Native(config.alliance_token_denom)); + let reward_token = AssetInfoKey::from(AssetInfo::Native(config.alliance_reward_denom.clone())); let rewards = _claim_alliance_rewards(deps.storage, user.clone(), asset.clone(), reward_token)?; let unclaimed_rewards = UNCLAIMED_REWARDS .load( @@ -411,14 +420,14 @@ fn _claim_alliance_rewards( let rewards = ((asset_reward_rate - user_reward_rate) * user_staked).to_uint_floor(); if rewards.is_zero() { - return Ok(Uint128::zero()); + Ok(Uint128::zero()) } else { USER_ASSET_REWARD_RATE.save(storage, state_key, &asset_reward_rate)?; - return Ok(rewards); + Ok(rewards) } } else { USER_ASSET_REWARD_RATE.save(storage, state_key, &asset_reward_rate)?; - return Ok(Uint128::zero()); + Ok(Uint128::zero()) } } @@ -711,7 +720,7 @@ fn update_alliance_reward_callback( (asset_key.clone(), reward_asset_info_key.clone()), |rate| -> StdResult<_> { let mut reward_rate = rate.unwrap_or_default(); - reward_rate = reward_rate + rate_to_update; + reward_rate += rate_to_update; Ok(reward_rate) }, )?; @@ -878,5 +887,6 @@ fn reply_claim_astro_rewards( )?; } } - return Ok(res.add_attribute("action", "claim_astro_rewards_success")); + + Ok(res.add_attribute("action", "claim_astro_rewards_success")) } diff --git a/contracts/alliance-lp-hub/src/helpers.rs b/contracts/alliance-lp-hub/src/helpers.rs index 238e8d1..b29422e 100644 --- a/contracts/alliance-lp-hub/src/helpers.rs +++ b/contracts/alliance-lp-hub/src/helpers.rs @@ -3,7 +3,6 @@ use cosmwasm_std::MessageInfo; use crate::models::Config; - // Controller is used to perform administrative operations that deals with delegating the virtual // tokens to the expected validators pub fn is_controller(info: &MessageInfo, config: &Config) -> Result<(), ContractError> { diff --git a/contracts/alliance-lp-hub/src/lib.rs b/contracts/alliance-lp-hub/src/lib.rs index 591cbd1..84d5385 100644 --- a/contracts/alliance-lp-hub/src/lib.rs +++ b/contracts/alliance-lp-hub/src/lib.rs @@ -1,9 +1,9 @@ +pub mod astro_models; pub mod contract; +pub mod helpers; pub mod models; pub mod query; pub mod state; -pub mod astro_models; -pub mod helpers; #[cfg(test)] mod tests; diff --git a/contracts/alliance-lp-hub/src/models.rs b/contracts/alliance-lp-hub/src/models.rs index 3c8f4de..8a3ceab 100644 --- a/contracts/alliance-lp-hub/src/models.rs +++ b/contracts/alliance-lp-hub/src/models.rs @@ -8,9 +8,7 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Addr, Coins, Uint128}; use cw20::Cw20ReceiveMsg; use cw_asset::{Asset, AssetInfo, AssetInfoKey}; -use std::{ - collections::{HashMap, HashSet}, -}; +use std::collections::{HashMap, HashSet}; pub type AssetDenom = String; diff --git a/contracts/alliance-lp-hub/src/query.rs b/contracts/alliance-lp-hub/src/query.rs index 451d64c..1a4eb05 100644 --- a/contracts/alliance-lp-hub/src/query.rs +++ b/contracts/alliance-lp-hub/src/query.rs @@ -144,9 +144,10 @@ fn get_all_pending_rewards(deps: Deps, query: AllPendingRewardsQuery) -> StdResu let deposit_asset = AssetInfoKey::from(assets.0.check(deps.api, None)?); let reward_asset = AssetInfoKey::from(assets.1.check(deps.api, None)?); - let asset_reward_rate = - ASSET_REWARD_RATE.load(deps.storage, (deposit_asset.clone(), reward_asset.clone()))?; - let user_balance = BALANCES.load(deps.storage, (addr.clone(), deposit_asset.clone()))?; + let asset_reward_rate = ASSET_REWARD_RATE + .load(deps.storage, (deposit_asset.clone(), reward_asset.clone()))?; + let user_balance = + BALANCES.load(deps.storage, (addr.clone(), deposit_asset.clone()))?; let unclaimed_rewards = UNCLAIMED_REWARDS .load(deps.storage, (addr.clone(), deposit_asset)) .unwrap_or_default(); diff --git a/contracts/alliance-lp-hub/src/state.rs b/contracts/alliance-lp-hub/src/state.rs index 5540a09..0915cdd 100644 --- a/contracts/alliance-lp-hub/src/state.rs +++ b/contracts/alliance-lp-hub/src/state.rs @@ -37,4 +37,4 @@ pub const TEMP_BALANCE: Map = Map::new("temp_balance"); // Temporary variable used to store the user address // so we can access it on reply_claim_astro_rewards // callback function and account for the rewards -pub const TEMP_USR_ADDR: Item = Item::new("temp_addr_stake"); \ No newline at end of file +pub const TEMP_USR_ADDR: Item = Item::new("temp_addr_stake"); diff --git a/contracts/alliance-lp-hub/src/tests/helpers.rs b/contracts/alliance-lp-hub/src/tests/helpers.rs index e4e2043..6589a1a 100644 --- a/contracts/alliance-lp-hub/src/tests/helpers.rs +++ b/contracts/alliance-lp-hub/src/tests/helpers.rs @@ -1,7 +1,7 @@ use crate::contract::{execute, instantiate}; use crate::models::{ - AllPendingRewardsQuery, AssetQuery, Config, ExecuteMsg, InstantiateMsg, PendingRewardsRes, - QueryMsg, StakedBalanceRes, ModifyAssetPair, + AllPendingRewardsQuery, AssetQuery, Config, ExecuteMsg, InstantiateMsg, ModifyAssetPair, + PendingRewardsRes, QueryMsg, StakedBalanceRes, }; use crate::query::query; use crate::state::CONFIG; @@ -11,7 +11,7 @@ use alliance_protocol::alliance_protocol::{ }; use alliance_protocol::token_factory::CustomExecuteMsg; use cosmwasm_std::testing::{mock_env, mock_info}; -use cosmwasm_std::{coin, from_json, Deps, DepsMut, Response, StdResult, Uint128, Binary, Addr}; +use cosmwasm_std::{coin, from_json, Addr, Binary, Deps, DepsMut, Response, StdResult, Uint128}; use cw20::Cw20ReceiveMsg; use cw_asset::{Asset, AssetInfo}; @@ -24,7 +24,7 @@ pub fn setup_contract(deps: DepsMut) -> Response { let init_msg = InstantiateMsg { governance: "gov".to_string(), fee_collector_address: "collector_address".to_string(), - astro_incentives_address : "astro_incentives".to_string(), + astro_incentives_address: "astro_incentives".to_string(), controller: "controller".to_string(), reward_denom: "uluna".to_string(), }; @@ -51,7 +51,6 @@ pub fn modify_asset(deps: DepsMut, assets: Vec) -> Response { execute(deps, env, info, msg).unwrap() } - pub fn stake(deps: DepsMut, user: &str, amount: u128, denom: &str) -> Response { let info = mock_info(user, &[coin(amount, denom)]); let env = mock_env(); @@ -59,11 +58,10 @@ pub fn stake(deps: DepsMut, user: &str, amount: u128, denom: &str) -> Response { execute(deps, env, info, msg).unwrap() } - pub fn stake_cw20(deps: DepsMut, user: &str, amount: u128, denom: &str) -> Response { let mut info = mock_info(user, &[]); let env = mock_env(); - let msg = ExecuteMsg::Receive(Cw20ReceiveMsg{ + let msg = ExecuteMsg::Receive(Cw20ReceiveMsg { sender: String::from(user), amount: Uint128::new(amount), msg: Binary::default(), @@ -133,7 +131,12 @@ pub fn claim_rewards(deps: DepsMut, user: &str, denom: &str) -> Response { execute(deps, env, info, msg).unwrap() } -pub fn query_rewards(deps: Deps, user: &str, deposit_asset: &str, reward_asset: &str ) -> PendingRewardsRes { +pub fn query_rewards( + deps: Deps, + user: &str, + deposit_asset: &str, + reward_asset: &str, +) -> PendingRewardsRes { from_json( query( deps, diff --git a/contracts/alliance-lp-hub/src/tests/mod.rs b/contracts/alliance-lp-hub/src/tests/mod.rs index ae5112b..e453f9f 100644 --- a/contracts/alliance-lp-hub/src/tests/mod.rs +++ b/contracts/alliance-lp-hub/src/tests/mod.rs @@ -1,6 +1,6 @@ +mod alliance; mod helpers; mod instantiate; -mod stake_unstake; +mod mock_querier; mod rewards; -mod alliance; -mod mock_querier; \ No newline at end of file +mod stake_unstake; diff --git a/contracts/alliance-lp-hub/src/tests/rewards.rs b/contracts/alliance-lp-hub/src/tests/rewards.rs index 9d08ef3..932ba95 100644 --- a/contracts/alliance-lp-hub/src/tests/rewards.rs +++ b/contracts/alliance-lp-hub/src/tests/rewards.rs @@ -636,26 +636,35 @@ fn claim_rewards_after_staking_and_unstaking() { stake(deps.as_mut(), "user1", 1000000, "aWHALE"); // User 1 should not have any rewards - let res = query_rewards(deps.as_ref(), "user1", "aWHALE","uluna"); - assert_eq!(res, PendingRewardsRes { - rewards: Uint128::zero(), - deposit_asset: AssetInfo::Native("aWHALE".to_string()), - reward_asset: AssetInfo::Native("uluna".to_string()), - }); + let res = query_rewards(deps.as_ref(), "user1", "aWHALE", "uluna"); + assert_eq!( + res, + PendingRewardsRes { + rewards: Uint128::zero(), + deposit_asset: AssetInfo::Native("aWHALE".to_string()), + reward_asset: AssetInfo::Native("uluna".to_string()), + } + ); // User 2 should receive all the rewards in the contract - let res = query_rewards(deps.as_ref(), "user2", "aWHALE","uluna"); - assert_eq!(res, PendingRewardsRes { - rewards: Uint128::new(900000), - deposit_asset: AssetInfo::Native("aWHALE".to_string()), - reward_asset: AssetInfo::Native("uluna".to_string()), - }); - let res = query_rewards(deps.as_ref(), "user2", "bWHALE","uluna"); - assert_eq!(res, PendingRewardsRes { - rewards: Uint128::new(1000000), - deposit_asset: AssetInfo::Native("aWHALE".to_string()), - reward_asset: AssetInfo::Native("uluna".to_string()), - }); + let res = query_rewards(deps.as_ref(), "user2", "aWHALE", "uluna"); + assert_eq!( + res, + PendingRewardsRes { + rewards: Uint128::new(900000), + deposit_asset: AssetInfo::Native("aWHALE".to_string()), + reward_asset: AssetInfo::Native("uluna".to_string()), + } + ); + let res = query_rewards(deps.as_ref(), "user2", "bWHALE", "uluna"); + assert_eq!( + res, + PendingRewardsRes { + rewards: Uint128::new(1000000), + deposit_asset: AssetInfo::Native("bWHALE".to_string()), + reward_asset: AssetInfo::Native("uluna".to_string()), + } + ); } #[test] @@ -741,9 +750,9 @@ fn claim_rewards_after_rebalancing_emissions() { ) .unwrap(); - let rewards = query_rewards(deps.as_ref(), "user1", "aWHALE","uluna"); + let rewards = query_rewards(deps.as_ref(), "user1", "aWHALE", "uluna"); assert_eq!(rewards.rewards, Uint128::new(1500000)); // User 2 should receive all the rewards in the contract - let rewards = query_rewards(deps.as_ref(), "user2", "bWHALE","uluna"); + let rewards = query_rewards(deps.as_ref(), "user2", "bWHALE", "uluna"); assert_eq!(rewards.rewards, Uint128::new(500000)); } diff --git a/contracts/alliance-lp-hub/src/tests/stake_unstake.rs b/contracts/alliance-lp-hub/src/tests/stake_unstake.rs index 28fc58c..6dbf1be 100644 --- a/contracts/alliance-lp-hub/src/tests/stake_unstake.rs +++ b/contracts/alliance-lp-hub/src/tests/stake_unstake.rs @@ -1,4 +1,4 @@ -use crate::astro_models::{ExecuteAstroMsg, Cw20Msg}; +use crate::astro_models::{Cw20Msg, ExecuteAstroMsg}; use crate::contract::execute; use crate::models::{ExecuteMsg, ModifyAssetPair, StakedBalanceRes}; use crate::state::{BALANCES, TOTAL_BALANCES}; @@ -11,7 +11,7 @@ use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; use cosmwasm_std::{ coin, to_json_binary, Addr, BankMsg, Coin, CosmosMsg, Response, Uint128, WasmMsg, }; -use cw20::{Cw20ReceiveMsg, Cw20ExecuteMsg}; +use cw20::{Cw20ExecuteMsg, Cw20ReceiveMsg}; use cw_asset::{Asset, AssetInfo, AssetInfoKey}; #[test] @@ -133,7 +133,6 @@ fn test_stake_astro_token() { ) .unwrap(); assert_eq!(balance, Uint128::new(100)); - } #[test] @@ -227,31 +226,31 @@ fn test_stake_astro_token_cw20() { let res = stake_cw20(deps.as_mut(), "user1", 100, "astro_existent_cw20"); assert_eq!( res, - Response::default().add_attributes(vec![ - ("action", "stake"), - ("user", "user1"), - ("asset", "cw20:astro_existent_cw20"), - ("amount", "100"), - ]) - .add_message(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: "astro_existent_cw20".to_string(), - msg: to_json_binary(&Cw20ExecuteMsg::Send { - contract: "astro_incentives".to_string(), - amount: Uint128::new(100), - msg: to_json_binary(&Cw20ReceiveMsg { - sender: "cosmos2contract".to_string(), + Response::default() + .add_attributes(vec![ + ("action", "stake"), + ("user", "user1"), + ("asset", "cw20:astro_existent_cw20"), + ("amount", "100"), + ]) + .add_message(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: "astro_existent_cw20".to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: "astro_incentives".to_string(), amount: Uint128::new(100), - msg: to_json_binary(&Cw20Msg::Deposit { - recipient: None, - }).unwrap(), - }).unwrap(), - }).unwrap(), - funds: vec![], - })) + msg: to_json_binary(&Cw20ReceiveMsg { + sender: "cosmos2contract".to_string(), + amount: Uint128::new(100), + msg: to_json_binary(&Cw20Msg::Deposit { recipient: None }).unwrap(), + }) + .unwrap(), + }) + .unwrap(), + funds: vec![], + })) ); } - #[test] fn test_unstake() { let mut deps = mock_dependencies(); @@ -266,9 +265,9 @@ fn test_unstake() { }], ); stake(deps.as_mut(), "user1", 100, "native_asset"); - + let asset_info = Asset::native(Addr::unchecked("native_asset"), 50u128); - let res = unstake(deps.as_mut(), "user1",asset_info); + let res = unstake(deps.as_mut(), "user1", asset_info); assert_eq!( res, Response::default() diff --git a/packages/alliance-protocol/src/error.rs b/packages/alliance-protocol/src/error.rs index 08dd908..61f2130 100644 --- a/packages/alliance-protocol/src/error.rs +++ b/packages/alliance-protocol/src/error.rs @@ -50,7 +50,7 @@ pub enum ContractError { #[error("Invalid contract callback with key: {0} and type: {1}")] InvalidContractCallback(String, String), - + #[error("Invalid denom: {0}")] InvalidDenom(String),