Skip to content

Commit

Permalink
wip(lp-hub): cw20 staking for both native and cw20
Browse files Browse the repository at this point in the history
  • Loading branch information
emidev98 committed Jan 9, 2024
1 parent 4e9a0be commit 2599ecc
Show file tree
Hide file tree
Showing 4 changed files with 443 additions and 13 deletions.
21 changes: 11 additions & 10 deletions contracts/alliance-lp-hub/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ pub fn execute(
ExecuteMsg::ModifyAssets(assets) => modify_assets(deps, info, assets),

ExecuteMsg::Receive(cw20_msg) => {
let sender = deps.api.addr_validate(&cw20_msg.sender)?;
let received_asset = Asset::cw20(info.sender.clone(), cw20_msg.amount);

stake(deps, info, received_asset)
stake(deps, sender, received_asset)
}
ExecuteMsg::Stake {} => {
if info.funds.len() != 1 {
Expand All @@ -96,8 +97,9 @@ pub fn execute(
if coin.amount.is_zero() {
return Err(ContractError::AmountCannotBeZero {});
}
stake(deps, info, coin.into())
stake(deps, info.sender, coin.into())
}

ExecuteMsg::Unstake(asset) => unstake(deps, info, asset),
ExecuteMsg::ClaimRewards(asset) => claim_rewards(deps, info, asset),

Expand Down Expand Up @@ -160,14 +162,13 @@ fn modify_assets(
// update the user balance and the total balance for the asset.
fn stake(
deps: DepsMut,
info: MessageInfo,
sender: Addr,
received_asset: Asset,
) -> Result<Response, ContractError> {
let asset_key = AssetInfoKey::from(&received_asset.info);
WHITELIST
.load(deps.storage, asset_key.clone())
.map_err(|_| ContractError::AssetNotWhitelisted {})?;
let sender = info.sender.clone();

let rewards = _claim_reward(deps.storage, sender.clone(), received_asset.info.clone())?;
if !rewards.is_zero() {
Expand All @@ -185,29 +186,29 @@ fn stake(
(sender.clone(), asset_key.clone()),
|balance| -> Result<_, ContractError> {
match balance {
Some(balance) => Ok(balance + info.funds[0].amount),
None => Ok(info.funds[0].amount),
Some(balance) => Ok(balance + received_asset.amount),
None => Ok(received_asset.amount),
}
},
)?;
TOTAL_BALANCES.update(
deps.storage,
asset_key.clone(),
|balance| -> Result<_, ContractError> {
Ok(balance.unwrap_or(Uint128::zero()) + info.funds[0].amount)
Ok(balance.unwrap_or(Uint128::zero()) + received_asset.amount)
},
)?;

let asset_reward_rate = ASSET_REWARD_RATE
.load(deps.storage, asset_key.clone())
.unwrap_or(Decimal::zero());
USER_ASSET_REWARD_RATE.save(deps.storage, (sender, asset_key), &asset_reward_rate)?;
USER_ASSET_REWARD_RATE.save(deps.storage, (sender.clone(), asset_key), &asset_reward_rate)?;

Ok(Response::new().add_attributes(vec![
("action", "stake"),
("user", info.sender.as_ref()),
("user", sender.as_ref()),
("asset", &received_asset.info.to_string()),
("amount", &info.funds[0].amount.to_string()),
("amount", &received_asset.amount.to_string()),
]))
}

Expand Down
152 changes: 149 additions & 3 deletions contracts/alliance-lp-hub/src/tests/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
use crate::contract::instantiate;
use crate::models::InstantiateMsg;
use crate::contract::{execute, instantiate};
use crate::models::{
AllPendingRewardsQuery, AssetQuery, Config, ExecuteMsg, InstantiateMsg, PendingRewardsRes,
QueryMsg, StakedBalanceRes, ModifyAsset,
};
use crate::query::query;
use crate::state::CONFIG;
use alliance_protocol::alliance_protocol::{
AllianceDelegateMsg, AllianceDelegation, AllianceRedelegateMsg, AllianceRedelegation,
AllianceUndelegateMsg,
};
use alliance_protocol::token_factory::CustomExecuteMsg;
use cosmwasm_std::testing::{mock_env, mock_info};
use cosmwasm_std::{DepsMut, Response};
use cosmwasm_std::{coin, from_json, Deps, DepsMut, Response, StdResult, Uint128, Binary, Addr};
use cw20::Cw20ReceiveMsg;
use cw_asset::{Asset, AssetInfo};

pub const DENOM: &str = "token_factory/token";

pub fn setup_contract(deps: DepsMut) -> Response<CustomExecuteMsg> {
let info = mock_info("admin", &[]);
Expand All @@ -15,3 +28,136 @@ pub fn setup_contract(deps: DepsMut) -> Response<CustomExecuteMsg> {
};
instantiate(deps, env, info, init_msg).unwrap()
}

pub fn set_alliance_asset(deps: DepsMut) {
CONFIG
.update(deps.storage, |c| -> StdResult<_> {
Ok(Config {
alliance_token_denom: DENOM.to_string(),
alliance_token_supply: Uint128::new(1000000000000),
..c
})
})
.unwrap();
}

pub fn modify_asset(deps: DepsMut, assets: Vec<ModifyAsset>) -> Response {
let info = mock_info("gov", &[]);
let env = mock_env();

let msg = ExecuteMsg::ModifyAssets(assets);
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();
let msg = ExecuteMsg::Stake {};
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{
sender: String::from(user),
amount: Uint128::new(amount),
msg: Binary::default(),
});
info.sender = Addr::unchecked(denom.to_owned());
execute(deps, env, info, msg).unwrap()
}

pub fn unstake(deps: DepsMut, user: &str, amount: u128, denom: &str) -> Response {
let info = mock_info(user, &[]);
let env = mock_env();
let msg = ExecuteMsg::Unstake(Asset::native(denom, amount));
execute(deps, env, info, msg).unwrap()
}

pub fn alliance_delegate(deps: DepsMut, delegations: Vec<(&str, u128)>) -> Response {
let info = mock_info("controller", &[]);
let env = mock_env();
let delegations: Vec<AllianceDelegation> = delegations
.iter()
.map(|(addr, amount)| AllianceDelegation {
validator: addr.to_string(),
amount: Uint128::new(*amount),
})
.collect();
let msg = ExecuteMsg::AllianceDelegate(AllianceDelegateMsg { delegations });
execute(deps, env, info, msg).unwrap()
}

pub fn alliance_undelegate(deps: DepsMut, delegations: Vec<(&str, u128)>) -> Response {
let info = mock_info("controller", &[]);
let env = mock_env();
let delegations: Vec<AllianceDelegation> = delegations
.iter()
.map(|(addr, amount)| AllianceDelegation {
validator: addr.to_string(),
amount: Uint128::new(*amount),
})
.collect();
let msg = ExecuteMsg::AllianceUndelegate(AllianceUndelegateMsg {
undelegations: delegations,
});
execute(deps, env, info, msg).unwrap()
}

pub fn alliance_redelegate(deps: DepsMut, redelegations: Vec<(&str, &str, u128)>) -> Response {
let info = mock_info("controller", &[]);
let env = mock_env();
let redelegations: Vec<AllianceRedelegation> = redelegations
.iter()
.map(|(src, dst, amount)| AllianceRedelegation {
src_validator: src.to_string(),
dst_validator: dst.to_string(),
amount: Uint128::new(*amount),
})
.collect();
let msg = ExecuteMsg::AllianceRedelegate(AllianceRedelegateMsg { redelegations });
execute(deps, env, info, msg).unwrap()
}

pub fn claim_rewards(deps: DepsMut, user: &str, denom: &str) -> Response {
let info = mock_info(user, &[]);
let env = mock_env();
let msg = ExecuteMsg::ClaimRewards(AssetInfo::Native(denom.to_string()));
execute(deps, env, info, msg).unwrap()
}

pub fn query_rewards(deps: Deps, user: &str, denom: &str) -> PendingRewardsRes {
from_json(
query(
deps,
mock_env(),
QueryMsg::PendingRewards(AssetQuery {
address: user.to_string(),
asset: AssetInfo::Native(denom.to_string()),
}),
)
.unwrap(),
)
.unwrap()
}

pub fn query_all_rewards(deps: Deps, user: &str) -> Vec<PendingRewardsRes> {
from_json(
query(
deps,
mock_env(),
QueryMsg::AllPendingRewards(AllPendingRewardsQuery {
address: user.to_string(),
}),
)
.unwrap(),
)
.unwrap()
}

pub fn query_all_staked_balances(deps: Deps) -> Vec<StakedBalanceRes> {
from_json(query(deps, mock_env(), QueryMsg::TotalStakedBalances {}).unwrap()).unwrap()
}
2 changes: 2 additions & 0 deletions contracts/alliance-lp-hub/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
mod helpers;
mod instantiate;
mod stake_unstake;

Loading

0 comments on commit 2599ecc

Please sign in to comment.