Skip to content

Commit

Permalink
refactor: cleanup state
Browse files Browse the repository at this point in the history
  • Loading branch information
kerber0x committed May 17, 2024
1 parent 1dfa428 commit ca3db75
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 122 deletions.
124 changes: 84 additions & 40 deletions contracts/liquidity_hub/bonding-manager/src/bonding/commands.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use crate::queries::MAX_PAGE_LIMIT;
use crate::state::{
update_bond_weight, update_global_weight, BOND, CONFIG, GLOBAL, LAST_CLAIMED_EPOCH, UNBOND,
};
use crate::{helpers, ContractError};
use cosmwasm_std::{
ensure, Addr, BankMsg, Coin, CosmosMsg, Decimal, DepsMut, Env, MessageInfo, Order, Response,
StdResult, Uint128,
ensure, Addr, BankMsg, Coin, CosmosMsg, Decimal, DepsMut, Env, MessageInfo, Response, StdError,
Uint128,
};

use white_whale_std::bonding_manager::Bond;
use white_whale_std::pool_network::asset;

use crate::state::{
get_bonds_by_receiver, update_bond_weight, update_global_weight, BONDS, BOND_COUNTER, CONFIG,
GLOBAL, LAST_CLAIMED_EPOCH, MAX_LIMIT,
};
use crate::{helpers, ContractError};

/// Bonds the provided asset.
pub(crate) fn bond(
mut deps: DepsMut,
Expand All @@ -28,25 +30,50 @@ pub(crate) fn bond(
&white_whale_std::epoch_manager::epoch_manager::QueryMsg::CurrentEpoch {},
)?;

let mut bond = BOND
.key((&info.sender, &asset.denom))
.may_load(deps.storage)?
.unwrap_or(Bond {
let mut bonds_by_receiver = get_bonds_by_receiver(
deps.storage,
info.sender.to_string(),
Some(true),
Some(asset.denom.clone()),
None,
None,
)?;

let mut bond = if bonds_by_receiver.is_empty() {
// create bond id
let bond_id =
BOND_COUNTER.update::<_, StdError>(deps.storage, |current_id| Ok(current_id + 1u64))?;

Bond {
id: bond_id,
asset: Coin {
amount: Uint128::zero(),
..asset.clone()
},
created_at_epoch: current_epoch.epoch.id,
last_updated: current_epoch.epoch.id,
receiver: info.sender.clone(),
..Bond::default()
});
}
} else {
ensure!(
bonds_by_receiver.len() == 1usize,
//todo change this error
ContractError::NothingToUnbond
);

//todo change this error
bonds_by_receiver
.pop()
.ok_or(ContractError::NothingToUnbond)?
};

// update bond values
bond = update_bond_weight(&mut deps, info.sender.clone(), current_epoch.epoch.id, bond)?;
bond = update_bond_weight(&mut deps, current_epoch.epoch.id, bond)?;
bond.asset.amount = bond.asset.amount.checked_add(asset.amount)?;
bond.weight = bond.weight.checked_add(asset.amount)?;

BOND.save(deps.storage, (&info.sender, &bond.asset.denom), &bond)?;
BONDS.save(deps.storage, bond.id, &bond)?;

// update global values
let mut global_index = GLOBAL.load(deps.storage)?;
Expand Down Expand Up @@ -82,10 +109,30 @@ pub(crate) fn unbond(

helpers::validate_claimed(&deps, &info)?;
helpers::validate_bonding_for_current_epoch(&deps)?;
if let Some(mut unbond) = BOND
.key((&info.sender, &asset.denom))
.may_load(deps.storage)?
{

let mut bonds_by_receiver = get_bonds_by_receiver(
deps.storage,
info.sender.to_string(),
Some(true),
Some(asset.denom.clone()),
None,
None,
)?;

ensure!(
bonds_by_receiver.len() <= 1usize,
//todo change this error
ContractError::NothingToUnbond
);

if bonds_by_receiver.is_empty() {
Err(ContractError::NothingToUnbond)
} else {
//todo change this error
let mut unbond: Bond = bonds_by_receiver
.pop()
.ok_or(ContractError::NothingToUnbond)?;

// check if the address has enough bond
ensure!(
unbond.asset.amount >= asset.amount,
Expand All @@ -100,32 +147,31 @@ pub(crate) fn unbond(
)?;

// update bond values, decrease the bond
unbond = update_bond_weight(
&mut deps,
info.sender.clone(),
current_epoch.epoch.id,
unbond.clone(),
)?;
unbond = update_bond_weight(&mut deps, current_epoch.epoch.id, unbond.clone())?;
let weight_slash = unbond.weight * Decimal::from_ratio(asset.amount, unbond.asset.amount);
unbond.weight = unbond.weight.saturating_sub(weight_slash);
unbond.asset.amount = unbond.asset.amount.saturating_sub(asset.amount);

if unbond.asset.amount.is_zero() {
BOND.remove(deps.storage, (&info.sender, &asset.denom));
BONDS.remove(deps.storage, unbond.id)?;
} else {
BOND.save(deps.storage, (&info.sender, &asset.denom), &unbond)?;
BONDS.save(deps.storage, unbond.id, &unbond)?;
}

let bond_id =
BOND_COUNTER.update::<_, StdError>(deps.storage, |current_id| Ok(current_id + 1u64))?;
// record the unbonding
UNBOND.save(
BONDS.save(
deps.storage,
(&info.sender, &asset.denom, env.block.time.seconds()),
bond_id,
&Bond {
id: bond_id,
asset: asset.clone(),
weight: Uint128::zero(),
last_updated: current_epoch.epoch.id,
created_at_epoch: current_epoch.epoch.id,
unbonded_at: Some(env.block.time.seconds()),
receiver: info.sender.clone(),
},
)?;
// update global values
Expand All @@ -143,8 +189,6 @@ pub(crate) fn unbond(
("address", info.sender.to_string()),
("asset", asset.to_string()),
]))
} else {
Err(ContractError::NothingToUnbond)
}
}

Expand All @@ -154,11 +198,14 @@ pub(crate) fn withdraw(
address: Addr,
denom: String,
) -> Result<Response, ContractError> {
let unbondings: Vec<(u64, Bond)> = UNBOND
.prefix((&address, &denom))
.range(deps.storage, None, None, Order::Ascending)
.take(MAX_PAGE_LIMIT as usize)
.collect::<StdResult<Vec<(u64, Bond)>>>()?;
let unbondings = get_bonds_by_receiver(
deps.storage,
address.to_string(),
Some(false),
Some(denom.clone()),
None,
Some(MAX_LIMIT),
)?;

ensure!(!unbondings.is_empty(), ContractError::NothingToWithdraw);

Expand All @@ -170,13 +217,10 @@ pub(crate) fn withdraw(
)?;

let mut refund_amount = Uint128::zero();
for unbonding in unbondings {
let (ts, bond) = unbonding;
for bond in unbondings {
if current_epoch.epoch.id.saturating_sub(bond.created_at_epoch) >= config.unbonding_period {
let denom = bond.asset.denom;

refund_amount = refund_amount.checked_add(bond.asset.amount)?;
UNBOND.remove(deps.storage, (&address, &denom, ts));
BONDS.remove(deps.storage, bond.id)?;
}
}

Expand Down
3 changes: 2 additions & 1 deletion contracts/liquidity_hub/bonding-manager/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::error::ContractError;
use crate::helpers::{self, validate_growth_rate};
use crate::state::{BONDING_ASSETS_LIMIT, CONFIG, UPCOMING_REWARD_BUCKET};
use crate::state::{BONDING_ASSETS_LIMIT, BOND_COUNTER, CONFIG, UPCOMING_REWARD_BUCKET};
use crate::{bonding, commands, queries, rewards};
use cosmwasm_std::{ensure, entry_point, Addr, Reply};
use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response};
Expand Down Expand Up @@ -45,6 +45,7 @@ pub fn instantiate(

// Initialize the upcoming reward bucket
UPCOMING_REWARD_BUCKET.save(deps.storage, &UpcomingRewardBucket::default())?;
BOND_COUNTER.save(deps.storage, &0)?;

Ok(Response::default().add_attributes(vec![
("action", "instantiate".to_string()),
Expand Down
17 changes: 7 additions & 10 deletions contracts/liquidity_hub/bonding-manager/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ use white_whale_std::pool_network::asset::aggregate_coins;

use crate::contract::LP_WITHDRAWAL_REPLY_ID;
use crate::error::ContractError;
use crate::queries::{query_claimable, MAX_PAGE_LIMIT};
use crate::state::{get_weight, BOND, CONFIG, REWARD_BUCKETS, UPCOMING_REWARD_BUCKET};
use crate::queries::query_claimable;
use crate::state::{
get_bonds_by_receiver, get_weight, CONFIG, REWARD_BUCKETS, UPCOMING_REWARD_BUCKET,
};

/// Validates that the growth rate is between 0 and 1.
pub fn validate_growth_rate(growth_rate: Decimal) -> Result<(), ContractError> {
Expand Down Expand Up @@ -377,19 +379,14 @@ pub(crate) fn get_user_share(
address: String,
mut global_index: GlobalIndex,
) -> StdResult<Decimal> {
let address = deps.api.addr_validate(&address)?;

let bonds: StdResult<Vec<_>> = BOND
.prefix(&address)
.range(deps.storage, None, None, Order::Ascending)
.take(MAX_PAGE_LIMIT as usize)
.collect();
let mut bonds_by_receiver =
get_bonds_by_receiver(deps.storage, address, Some(true), None, None, None)?;

let config = CONFIG.load(deps.storage)?;

let mut total_bond_weight = Uint128::zero();

for (_, mut bond) in bonds? {
for bond in bonds_by_receiver.iter_mut() {
bond.weight = get_weight(
epoch_id,
bond.weight,
Expand Down
Loading

0 comments on commit ca3db75

Please sign in to comment.