Skip to content

Commit

Permalink
wip: astro rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
emidev98 committed Jan 23, 2024
1 parent b7366cf commit 2b50554
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 177 deletions.
331 changes: 206 additions & 125 deletions contracts/alliance-lp-hub/src/contract.rs

Large diffs are not rendered by default.

45 changes: 34 additions & 11 deletions contracts/alliance-lp-hub/src/models.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
use alliance_protocol::alliance_protocol::{
use alliance_protocol::{
alliance_protocol::{
AllianceDelegateMsg, AllianceRedelegateMsg, AllianceUndelegateMsg, AssetDistribution,
},
error::ContractError,
};
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Uint128};
use cosmwasm_std::{Addr, Coins, Uint128};
use cw20::Cw20ReceiveMsg;
use cw_asset::{Asset, AssetInfo};
use std::collections::{HashMap, HashSet};
use cw_asset::{Asset, AssetInfo, AssetInfoKey};
use std::{
collections::{HashMap, HashSet},
};

pub type AssetDenom = String;

#[cw_serde]
pub struct Config {
pub governance: Addr,
pub controller: Addr,
pub fee_collector: Addr,
pub astro_incentives: Addr,
pub fee_collector_addr: Addr,
pub astro_incentives_addr: Addr,
pub alliance_token_denom: String,
pub alliance_token_supply: Uint128,
pub reward_denom: String,
pub alliance_reward_denom: String,
}

#[cw_serde]
Expand All @@ -31,7 +36,7 @@ pub struct InstantiateMsg {

#[cw_serde]
pub enum ExecuteMsg {
// Privileged function used to whitelist,
// Privileged function used to whitelist,
// modify or delete assets from the allowed list
ModifyAssetPairs(Vec<ModifyAssetPair>),

Expand All @@ -44,15 +49,14 @@ pub enum ExecuteMsg {
Unstake(Asset),
ClaimRewards(AssetInfo),

// Alliance interactions used to delegate, undelegate and redelegate
// Alliance interactions used to delegate, undelegate and redelegate
AllianceDelegate(AllianceDelegateMsg),
AllianceUndelegate(AllianceUndelegateMsg),
AllianceRedelegate(AllianceRedelegateMsg),

// Rewards related messages
UpdateRewards {},
UpdateAllianceRewardsCallback {},
UpdateAstroRewardsCallback {},
}

#[cw_serde]
Expand Down Expand Up @@ -132,4 +136,23 @@ pub struct AssetQuery {
pub struct StakedBalanceRes {
pub deposit_asset: AssetInfo,
pub balance: Uint128,
}
}

#[derive(Clone, Default)]
pub struct AstroClaimRewardsPosition {
pub deposited_asset: String,
pub rewards: Coins,
}

pub fn from_string_to_asset_info(denom: String) -> Result<AssetInfoKey, ContractError> {
if denom.starts_with("ibc/") || denom.starts_with("factory/") {
let asset_info = AssetInfoKey::from(AssetInfo::Native(denom));
return Ok(asset_info);
} else if denom.starts_with("terra") {
let from = Addr::unchecked(denom);
let asset_info = AssetInfoKey::from(AssetInfo::Cw20(from));
return Ok(asset_info);
}

Err(ContractError::InvalidDenom(denom))
}
22 changes: 11 additions & 11 deletions contracts/alliance-lp-hub/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::models::{
AllPendingRewardsQuery, AllStakedBalancesQuery, AssetQuery,
PendingRewardsRes, QueryMsg, StakedBalanceRes, WhitelistedAssetsResponse,
AllPendingRewardsQuery, AllStakedBalancesQuery, AssetQuery, PendingRewardsRes, QueryMsg,
StakedBalanceRes, WhitelistedAssetsResponse,
};
use alliance_protocol::alliance_oracle_types::EmissionsDistribution;
use alliance_protocol::signed_decimal::{Sign, SignedDecimal};
Expand Down Expand Up @@ -84,26 +84,26 @@ fn get_staked_balance(deps: Deps, asset_query: AssetQuery) -> StdResult<Binary>
}

fn get_pending_rewards(deps: Deps, asset_query: AssetQuery) -> StdResult<Binary> {
let config = CONFIG.load(deps.storage)?;
let addr = deps.api.addr_validate(&asset_query.address)?;
let reward_asset = AssetInfoKey::from(asset_query.reward_asset.clone());
let deposit_asset = AssetInfoKey::from(asset_query.deposit_asset.clone());

let key = (addr, deposit_asset, reward_asset);
let key = (addr.clone(), deposit_asset.clone(), reward_asset.clone());
let user_reward_rate = USER_ASSET_REWARD_RATE.load(deps.storage, key)?;

let asset_reward_rate = ASSET_REWARD_RATE.load(deps.storage, (deposit_asset, reward_asset))?;
let user_balance = BALANCES.load(deps.storage, (addr, 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, reward_asset))
.unwrap_or_default();

let alliance_pending_rewards = (asset_reward_rate - user_reward_rate) * user_balance;
let pending_rewards = (asset_reward_rate - user_reward_rate) * user_balance;

to_json_binary(&PendingRewardsRes {
deposit_asset: asset_query.deposit_asset,
reward_asset: asset_query.reward_asset,
rewards: alliance_pending_rewards + unclaimed_rewards,
rewards: pending_rewards + unclaimed_rewards,
})
}

Expand Down Expand Up @@ -145,8 +145,8 @@ fn get_all_pending_rewards(deps: Deps, query: AllPendingRewardsQuery) -> StdResu
let reward_asset = AssetInfoKey::from(assets.1.check(deps.api, None)?);

let asset_reward_rate =
ASSET_REWARD_RATE.load(deps.storage, (deposit_asset, reward_asset))?;
let user_balance = BALANCES.load(deps.storage, (addr.clone(), deposit_asset))?;
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();
Expand All @@ -155,7 +155,7 @@ fn get_all_pending_rewards(deps: Deps, query: AllPendingRewardsQuery) -> StdResu
Ok(PendingRewardsRes {
rewards: alliance_pending_rewards + unclaimed_rewards,
deposit_asset: assets.0.check(deps.api, None)?,
reward_asset: AssetInfo::Native(config.reward_denom.to_string()),
reward_asset: AssetInfo::Native(config.alliance_reward_denom.to_string()),
})
})
.collect::<StdResult<Vec<PendingRewardsRes>>>();
Expand Down
5 changes: 5 additions & 0 deletions contracts/alliance-lp-hub/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ pub const USER_ASSET_REWARD_RATE: Map<(Addr, AssetInfoKey, AssetInfoKey), Decima
pub const UNCLAIMED_REWARDS: Map<(Addr, AssetInfoKey), Uint128> = Map::new("unclaimed_rewards");

pub const TEMP_BALANCE: Map<AssetInfoKey, Uint128> = 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<Addr> = Item::new("temp_addr_stake");
12 changes: 6 additions & 6 deletions contracts/alliance-lp-hub/src/tests/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ fn test_setup_contract() {
Config {
governance: Addr::unchecked("gov"),
controller: Addr::unchecked("controller"),
fee_collector: Addr::unchecked("collector_address"),
astro_incentives: Addr::unchecked("astro_incentives"),
reward_denom: "uluna".to_string(),
fee_collector_addr: Addr::unchecked("collector_address"),
astro_incentives_addr: Addr::unchecked("astro_incentives"),
alliance_reward_denom: "uluna".to_string(),
alliance_token_denom: "".to_string(),
alliance_token_supply: Uint128::new(0),
}
Expand Down Expand Up @@ -109,9 +109,9 @@ fn test_reply_create_token() {
Config {
governance: Addr::unchecked("gov"),
controller: Addr::unchecked("controller"),
fee_collector: Addr::unchecked("collector_address"),
astro_incentives: Addr::unchecked("astro_incentives"),
reward_denom: "uluna".to_string(),
fee_collector_addr: Addr::unchecked("collector_address"),
astro_incentives_addr: Addr::unchecked("astro_incentives"),
alliance_reward_denom: "uluna".to_string(),
alliance_token_denom: "factory/cosmos2contract/ualliancelp".to_string(),
alliance_token_supply: Uint128::new(1000000000000),
}
Expand Down
44 changes: 28 additions & 16 deletions contracts/alliance-lp-hub/src/tests/rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn test_update_rewards_with_funds_sent() {
}

#[test]
fn update_reward_callback() {
fn update_alliance_reward_callback() {
let mut deps = mock_dependencies_with_balance(&[coin(2000000, "uluna")]);
setup_contract(deps.as_mut());
set_alliance_asset(deps.as_mut());
Expand Down Expand Up @@ -198,12 +198,12 @@ fn update_reward_callback() {

assert_eq!(
res,
Response::new().add_attributes(vec![("action", "update_rewards_callback"),])
Response::new().add_attributes(vec![("action", "update_alliance_rewards_callback"),])
);
}

#[test]
fn update_reward_callback_with_unallocated() {
fn update_alliance_rewards_callback_with_unallocated() {
let mut deps = mock_dependencies_with_balance(&[coin(2000000, "uluna")]);
setup_contract(deps.as_mut());
set_alliance_asset(deps.as_mut());
Expand Down Expand Up @@ -283,7 +283,7 @@ fn update_reward_callback_with_unallocated() {
assert_eq!(
res,
Response::new()
.add_attributes(vec![("action", "update_rewards_callback")])
.add_attributes(vec![("action", "update_alliance_rewards_callback")])
.add_message(BankMsg::Send {
to_address: "collector_address".to_string(),
amount: vec![coin(300000, "uluna")]
Expand All @@ -300,7 +300,7 @@ fn claim_user_rewards() {
deps.as_mut(),
Vec::from([ModifyAssetPair {
asset_info: AssetInfo::Native("aWHALE".to_string()),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}]),
);
Expand Down Expand Up @@ -468,7 +468,7 @@ fn claim_user_rewards_after_staking() {
deps.as_mut(),
Vec::from([ModifyAssetPair {
asset_info: AssetInfo::Native("aWHALE".to_string()),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}]),
);
Expand Down Expand Up @@ -546,12 +546,12 @@ fn claim_rewards_after_staking_and_unstaking() {
Vec::from([
ModifyAssetPair {
asset_info: AssetInfo::Native("aWHALE".to_string()),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
},
ModifyAssetPair {
asset_info: AssetInfo::Native("bWHALE".to_string()),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
},
]),
Expand Down Expand Up @@ -636,14 +636,26 @@ fn claim_rewards_after_staking_and_unstaking() {
stake(deps.as_mut(), "user1", 1000000, "aWHALE");

// User 1 should not have any rewards
let rewards = query_rewards(deps.as_ref(), "user1", "aWHALE","uluna");
assert_eq!(rewards.rewards, Uint128::zero());
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 rewards = query_rewards(deps.as_ref(), "user2", "aWHALE","uluna");
assert_eq!(rewards.rewards, Uint128::new(900000));
let rewards = query_rewards(deps.as_ref(), "user2", "bWHALE","uluna");
assert_eq!(rewards.rewards, Uint128::new(1000000));
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()),
});
}

#[test]
Expand All @@ -656,12 +668,12 @@ fn claim_rewards_after_rebalancing_emissions() {
Vec::from([
ModifyAssetPair {
asset_info: AssetInfo::Native("aWHALE".to_string()),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
},
ModifyAssetPair {
asset_info: AssetInfo::Native("bWHALE".to_string()),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
},
]),
Expand Down
14 changes: 7 additions & 7 deletions contracts/alliance-lp-hub/src/tests/stake_unstake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn test_stake() {
deps.as_mut(),
vec![ModifyAssetPair {
asset_info: AssetInfo::native(Addr::unchecked("native_asset")),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}],
);
Expand Down Expand Up @@ -97,7 +97,7 @@ fn test_stake_astro_token() {
deps.as_mut(),
vec![ModifyAssetPair {
asset_info: AssetInfo::native(Addr::unchecked("astro_existent_native_coin")),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}],
);
Expand Down Expand Up @@ -144,7 +144,7 @@ fn test_stake_cw20() {
deps.as_mut(),
vec![ModifyAssetPair {
asset_info: AssetInfo::Cw20(Addr::unchecked("cw20_asset")),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}],
);
Expand Down Expand Up @@ -219,7 +219,7 @@ fn test_stake_astro_token_cw20() {
deps.as_mut(),
vec![ModifyAssetPair {
asset_info: AssetInfo::Cw20(Addr::unchecked("astro_existent_cw20")),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}],
);
Expand Down Expand Up @@ -261,7 +261,7 @@ fn test_unstake() {
deps.as_mut(),
vec![ModifyAssetPair {
asset_info: AssetInfo::native("native_asset"),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}],
);
Expand Down Expand Up @@ -341,7 +341,7 @@ fn test_unstake_cw20_invalid() {
deps.as_mut(),
vec![ModifyAssetPair {
asset_info: AssetInfo::Cw20(Addr::unchecked("cw20_asset")),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}],
);
Expand Down Expand Up @@ -375,7 +375,7 @@ fn test_unstake_native_invalid() {
deps.as_mut(),
vec![ModifyAssetPair {
asset_info: AssetInfo::native(Addr::unchecked("native_asset")),
reward_asset_info: None,
reward_asset_info: Some(AssetInfo::Native("uluna".to_string())),
delete: false,
}],
);
Expand Down
8 changes: 7 additions & 1 deletion packages/alliance-protocol/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::string::FromUtf8Error;

use cosmwasm_std::{Decimal, DecimalRangeExceeded, StdError};
use cosmwasm_std::{CoinFromStrError, Decimal, DecimalRangeExceeded, StdError};
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
Expand All @@ -14,6 +14,9 @@ pub enum ContractError {
#[error("{0}")]
DecimalRangeExceeded(#[from] DecimalRangeExceeded),

#[error("{0}")]
CoinFromStrError(#[from] CoinFromStrError),

#[error("Unauthorized")]
Unauthorized {},

Expand Down Expand Up @@ -48,6 +51,9 @@ pub enum ContractError {
#[error("Invalid contract callback with key: {0} and type: {1}")]
InvalidContractCallback(String, String),

#[error("Invalid denom: {0}")]
InvalidDenom(String),

#[error("Missing reward asset info for asset {0}")]
MissingRewardAsset(String),
}

0 comments on commit 2b50554

Please sign in to comment.