Skip to content

Commit

Permalink
basic staking completed
Browse files Browse the repository at this point in the history
  • Loading branch information
itsHaseebSaeed committed Dec 14, 2023
1 parent f7ea22b commit b4bc488
Show file tree
Hide file tree
Showing 6 changed files with 947 additions and 64 deletions.
15 changes: 11 additions & 4 deletions contracts/liquidity_book/lb_pair/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@ use shade_protocol::{
WasmMsg,
},
contract_interfaces::{
liquidity_book::{lb_pair::*, lb_token},
liquidity_book::{lb_pair::*, lb_token, staking},
swap::{
amm_pair::{
FeeInfo,
QueryMsgResponse::{GetPairInfo, SwapSimulation},
},
core::{Fee, TokenPair, TokenType},
router::ExecuteMsgResponse,
staking,
},
},
lb_libraries::{
Expand Down Expand Up @@ -1569,8 +1568,16 @@ fn try_calculate_rewards(deps: DepsMut, env: Env, info: MessageInfo) -> Result<R
}

//distribution algorithm
let res = staking::ExecuteMsg::EndEpoch {
rewards_distribution: distribution,
}
.to_cosmos_msg(
state.staking_contract.code_hash,
state.staking_contract.address.to_string(),
None,
)?;

Ok(Response::default())
Ok(Response::default().add_message(res))
}

fn calculate_time_based_rewards_distribution(
Expand Down Expand Up @@ -2546,7 +2553,7 @@ pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> StdResult<Response> {
admin_auth: state.admin_auth.into(),
query_auth: None,
first_reward_token: None,
epoch_index: 0, //TODO: Set this
epoch_index: 1, //TODO: Set this
epoch_duration: 100, //TODO: Set this
expiry_duration: None,
};
Expand Down
124 changes: 92 additions & 32 deletions contracts/liquidity_book/staking_contract/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
collections::HashMap,
ops::{Add, AddAssign, Sub},
str::FromStr,
};
Expand Down Expand Up @@ -590,20 +591,16 @@ pub fn try_end_epoch(
let mut state = STATE.load(deps.storage)?;
//check that only be called by lp-pair
assert_lb_pair(&state, info)?;
//saves the distribution
let mut epoch_obj = EPOCH_STORE.load(deps.storage, state.epoch_index)?;
epoch_obj.rewards_distribution = Some(rewards_distribution);

if let Some(expiry_duration) = epoch_obj.expired_at {
epoch_obj.expired_at = Some(state.epoch_index + expiry_duration)
}

EPOCH_STORE.save(deps.storage, state.epoch_index, &epoch_obj)?;

let mut reward_tokens = vec![];

for reward_token in REWARD_TOKENS.load(deps.storage)? {
let rewards_token_info = REWARD_TOKEN_INFO.load(deps.storage, &reward_token.address)?;
let rewards_token_info;
if let Ok(r_t_i) = REWARD_TOKEN_INFO.load(deps.storage, &reward_token.address) {
rewards_token_info = r_t_i;
} else {
continue;
};

// Create a filtered list of rewards to add to reward_tokens
let rewards_to_add: Vec<_> = rewards_token_info
Expand All @@ -621,13 +618,24 @@ pub fn try_end_epoch(
}
}

//saves the distribution
let mut epoch_obj = EPOCH_STORE.load(deps.storage, state.epoch_index)?;
epoch_obj.rewards_distribution = Some(rewards_distribution);
epoch_obj.reward_tokens = Some(reward_tokens);

if let Some(expiry_duration) = epoch_obj.expired_at {
epoch_obj.expired_at = Some(state.epoch_index + expiry_duration)
}

EPOCH_STORE.save(deps.storage, state.epoch_index, &epoch_obj)?;

let now = env.block.time.seconds();
EPOCH_STORE.save(deps.storage, state.epoch_index.add(1), &EpochInfo {
rewards_distribution: None,
start_time: now,
end_time: now + state.epoch_durations,
duration: state.epoch_durations,
reward_tokens: Some(reward_tokens),
reward_tokens: None,
expired_at: None,
})?;

Expand All @@ -643,6 +651,8 @@ pub fn try_claim_rewards(deps: DepsMut, _env: Env, info: MessageInfo) -> StdResu
let staker_result = STAKERS.load(deps.storage, &info.sender);
let mut messages = Vec::new();

let mut rewards_accumulator: HashMap<TokenKey, Uint128> = HashMap::new();

// Check if staker exists
let staker = match staker_result {
Ok(staker) => staker,
Expand Down Expand Up @@ -690,19 +700,26 @@ pub fn try_claim_rewards(deps: DepsMut, _env: Env, info: MessageInfo) -> StdResu
if let Some(rewards_distribution) = &epoch_info.rewards_distribution {
for (i, dis) in rewards_distribution.ids.iter().enumerate() {
let staker_liq_snap =
finding_user_liquidity(deps.storage, &info, &staker, state.epoch_index, *dis)?;
finding_user_liquidity(deps.storage, &info, &staker, round_epoch, *dis)?;
if staker_liq_snap.liquidity.is_zero() {
continue;
}
STAKERS_LIQUIDITY_SNAPSHOT.save(
deps.storage,
(&info.sender, state.epoch_index, *dis),
(&info.sender, round_epoch, *dis),
&staker_liq_snap,
)?;

let total_liquidity_snap =
finding_total_liquidity(deps.storage, state.epoch_index, *dis)?;
finding_total_liquidity(deps.storage, round_epoch, *dis)?;

if total_liquidity_snap.liquidity.is_zero() {
continue;
}

TOTAL_LIQUIDITY_SNAPSHOT.save(
deps.storage,
(state.epoch_index, *dis),
(round_epoch, *dis),
&total_liquidity_snap,
)?;

Expand All @@ -723,26 +740,67 @@ pub fn try_claim_rewards(deps: DepsMut, _env: Env, info: MessageInfo) -> StdResu
.to_string(),
)?;

messages.push(
Snip20ExecuteMsg::Send {
recipient: info.sender.to_string(),
recipient_code_hash: None,
amount: staker_rewards,
msg: None,
memo: None,
padding: None,
}
.to_cosmos_msg(&x.token, vec![])?,
);
let token_key = TokenKey {
address: x.token.address.clone(),
code_hash: x.token.code_hash.clone(),
};
let entry = rewards_accumulator
.entry(token_key)
.or_insert(Uint128::zero());
*entry += staker_rewards;
}
}
}
}
}

// Create messages for each token with the accumulated rewards
for (token_key, amount) in rewards_accumulator {
let contract_info = ContractInfo {
address: token_key.address,
code_hash: token_key.code_hash,
};
messages.push(
Snip20ExecuteMsg::Send {
recipient: info.sender.to_string(),
recipient_code_hash: None,
amount,
msg: None,
memo: None,
padding: None,
}
.to_cosmos_msg(&contract_info, vec![])?,
);
}

//TODO: add user rewards somewhere

Ok(Response::default().add_messages(messages))
}

use std::hash::{Hash, Hasher};

#[derive(Clone, Debug)]
struct TokenKey {
address: Addr,
code_hash: String,
}

impl PartialEq for TokenKey {
fn eq(&self, other: &Self) -> bool {
self.address == other.address && self.code_hash == other.code_hash
}
}

impl Eq for TokenKey {}

impl Hash for TokenKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.address.hash(state);
self.code_hash.hash(state);
}
}

pub fn try_register_reward_tokens(
deps: DepsMut,
env: Env,
Expand Down Expand Up @@ -825,12 +883,6 @@ pub fn try_add_rewards(
return Err(StdError::generic_err("Cannot start emitting in the past"));
}

validate_admin(
&deps.querier,
AdminPermissions::StakingAdmin,
info.sender.to_string(),
&state.admin_auth.into(),
)?;
let decimals = token_info(&deps.querier, &Contract {
address: token.address.clone(),
code_hash: token.code_hash.clone(),
Expand Down Expand Up @@ -918,6 +970,7 @@ fn try_revoke_permit(
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::ContractInfo {} => query_contract_info(deps),
QueryMsg::RegisteredTokens {} => query_registered_tokens(deps),
QueryMsg::IdTotalBalance { id } => query_token_id_balance(deps, id),
QueryMsg::Balance { .. }
| QueryMsg::AllBalances { .. }
Expand All @@ -943,6 +996,13 @@ fn query_contract_info(deps: Deps) -> StdResult<Binary> {
to_binary(&response)
}

fn query_registered_tokens(deps: Deps) -> StdResult<Binary> {
let reg_tokens = REWARD_TOKENS.load(deps.storage)?;

let response = QueryAnswer::RegisteredTokens(reg_tokens);
to_binary(&response)
}

fn query_token_id_balance(deps: Deps, token_id: String) -> StdResult<Binary> {
let id = u32::from_str(&token_id)
.map_err(|_| StdError::generic_err(format!("token_id {} cannot be parsed", token_id)))?;
Expand Down
17 changes: 12 additions & 5 deletions contracts/liquidity_book/staking_contract/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ pub fn register_reward_tokens(
tokens: Vec<ContractInfo>,
contract_code_hash: String,
) -> StdResult<Vec<CosmosMsg>> {
let mut binding = REWARD_TOKENS.load(storage)?;
let mut reg_tokens = REWARD_TOKENS.load(storage)?;
let mut messages = Vec::new();
for token in tokens.iter() {
if !binding.contains(token) {
binding.push(token.clone());
if !reg_tokens.contains(token) {
reg_tokens.push(token.clone());

let contract = &Contract {
address: token.address.to_owned(),
Expand All @@ -77,9 +77,11 @@ pub fn register_reward_tokens(
contract,
)?);
//set viewing_key
} else {
return Err(StdError::generic_err("Reward token already exists"));
}
}
REWARD_TOKENS.save(storage, &binding)?;
REWARD_TOKENS.save(storage, &reg_tokens)?;
Ok(messages)
}

Expand Down Expand Up @@ -168,6 +170,7 @@ pub fn finding_user_liquidity(
} else {
staker_info.starting_round.unwrap()
};

while finding_liq_round >= start {
let staker_liq_snap_prev_round = STAKERS_LIQUIDITY_SNAPSHOT
.load(storage, (&info.sender, finding_liq_round, bin_id))
Expand All @@ -179,6 +182,8 @@ pub fn finding_user_liquidity(
finding_liq_round = if let Some(f_liq_round) = finding_liq_round.checked_sub(1) {
f_liq_round
} else {
println!("finding_liq_round {:?}", finding_liq_round);
println!("start {:?}", start);
return Err(StdError::generic_err("Under-flow sub error 4"));
};
}
Expand All @@ -188,7 +193,7 @@ pub fn finding_user_liquidity(
staker_liq_snap.amount_delegated = legacy_bal;
// user_liquidity_snapshot_stats_helper_store(storage, round_index, sender, staker_liq_snap)?;

Ok((staker_liq_snap))
Ok(staker_liq_snap)
}
}

Expand Down Expand Up @@ -227,6 +232,8 @@ pub fn finding_total_liquidity(
finding_liq_round = if let Some(f_liq_round) = finding_liq_round.checked_sub(1) {
f_liq_round
} else {
print!("finding_liq_round {:?}", finding_liq_round);
print!("start {:?}", start);
return Err(StdError::generic_err("Under-flow sub error 4"));
};
}
Expand Down
Loading

0 comments on commit b4bc488

Please sign in to comment.