From ca3db75ffcc47a6abf6d5163b0c7b1b36a980e81 Mon Sep 17 00:00:00 2001 From: Kerber0x Date: Fri, 17 May 2024 17:07:12 +0100 Subject: [PATCH] refactor: cleanup state --- .../bonding-manager/src/bonding/commands.rs | 124 ++++++++++++------ .../bonding-manager/src/contract.rs | 3 +- .../bonding-manager/src/helpers.rs | 17 +-- .../bonding-manager/src/queries.rs | 87 +++++------- .../bonding-manager/src/state.rs | 88 +++++++++++-- .../bonding-manager/src/tests/queries.rs | 19 ++- .../src/tests/unbond_withdraw.rs | 8 +- .../incentive-manager/src/state.rs | 4 +- .../white-whale-std/src/bonding_manager.rs | 11 +- 9 files changed, 239 insertions(+), 122 deletions(-) diff --git a/contracts/liquidity_hub/bonding-manager/src/bonding/commands.rs b/contracts/liquidity_hub/bonding-manager/src/bonding/commands.rs index 7f022c52..62bed1e3 100644 --- a/contracts/liquidity_hub/bonding-manager/src/bonding/commands.rs +++ b/contracts/liquidity_hub/bonding-manager/src/bonding/commands.rs @@ -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, @@ -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)?; @@ -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, @@ -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 @@ -143,8 +189,6 @@ pub(crate) fn unbond( ("address", info.sender.to_string()), ("asset", asset.to_string()), ])) - } else { - Err(ContractError::NothingToUnbond) } } @@ -154,11 +198,14 @@ pub(crate) fn withdraw( address: Addr, denom: String, ) -> Result { - let unbondings: Vec<(u64, Bond)> = UNBOND - .prefix((&address, &denom)) - .range(deps.storage, None, None, Order::Ascending) - .take(MAX_PAGE_LIMIT as usize) - .collect::>>()?; + 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); @@ -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)?; } } diff --git a/contracts/liquidity_hub/bonding-manager/src/contract.rs b/contracts/liquidity_hub/bonding-manager/src/contract.rs index 335ea793..f2b9a379 100644 --- a/contracts/liquidity_hub/bonding-manager/src/contract.rs +++ b/contracts/liquidity_hub/bonding-manager/src/contract.rs @@ -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}; @@ -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()), diff --git a/contracts/liquidity_hub/bonding-manager/src/helpers.rs b/contracts/liquidity_hub/bonding-manager/src/helpers.rs index d0789534..2b4d444b 100644 --- a/contracts/liquidity_hub/bonding-manager/src/helpers.rs +++ b/contracts/liquidity_hub/bonding-manager/src/helpers.rs @@ -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> { @@ -377,19 +379,14 @@ pub(crate) fn get_user_share( address: String, mut global_index: GlobalIndex, ) -> StdResult { - let address = deps.api.addr_validate(&address)?; - - let bonds: StdResult> = 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, diff --git a/contracts/liquidity_hub/bonding-manager/src/queries.rs b/contracts/liquidity_hub/bonding-manager/src/queries.rs index 2aab70ee..5b490bf2 100644 --- a/contracts/liquidity_hub/bonding-manager/src/queries.rs +++ b/contracts/liquidity_hub/bonding-manager/src/queries.rs @@ -1,15 +1,13 @@ -use cosmwasm_std::{Deps, Order, StdResult, Uint128}; -use cw_storage_plus::Bound; +use cosmwasm_std::{Deps, StdResult, Uint128}; use crate::{helpers, ContractError}; use white_whale_std::bonding_manager::ClaimableRewardBucketsResponse; use white_whale_std::bonding_manager::{ - Bond, BondedResponse, Config, GlobalIndex, RewardsResponse, UnbondingResponse, - WithdrawableResponse, + BondedResponse, Config, GlobalIndex, RewardsResponse, UnbondingResponse, WithdrawableResponse, }; use crate::state::{ - BOND, BONDING_ASSETS_LIMIT, CONFIG, GLOBAL, LAST_CLAIMED_EPOCH, REWARD_BUCKETS, UNBOND, + get_bonds_by_receiver, CONFIG, GLOBAL, LAST_CLAIMED_EPOCH, MAX_LIMIT, REWARD_BUCKETS, }; /// Queries the current configuration of the contract. @@ -20,57 +18,46 @@ pub(crate) fn query_config(deps: Deps) -> StdResult { /// Queries the current bonded amount of the given address. If no address is provided, returns /// the global bonded amount. pub(crate) fn query_bonded(deps: Deps, address: Option) -> StdResult { - let (total_bonded, bonded_assets, first_bonded_epoch_id) = if let Some(address) = address { + let (total_bonded, bonded_assets) = if let Some(address) = address { let address = deps.api.addr_validate(&address)?; - let bonds: Vec = BOND - .prefix(&address) - .range(deps.storage, None, None, Order::Ascending) - .take(BONDING_ASSETS_LIMIT) - .map(|item| { - let (_, bond) = item?; - Ok(bond) - }) - .collect::>>()?; + let bonds = get_bonds_by_receiver( + deps.storage, + address.to_string(), + Some(true), + None, + None, + None, + )?; // if it doesn't have bonded, return empty response if bonds.is_empty() { return Ok(BondedResponse { total_bonded: Default::default(), bonded_assets: Default::default(), - first_bonded_epoch_id: Default::default(), }); } let mut total_bonded = Uint128::zero(); let mut bonded_assets = vec![]; - let mut first_bonded_epoch_id = u64::MAX; for bond in bonds { - if bond.created_at_epoch < first_bonded_epoch_id { - first_bonded_epoch_id = bond.created_at_epoch; - } - total_bonded = total_bonded.checked_add(bond.asset.amount)?; bonded_assets.push(bond.asset); } - (total_bonded, bonded_assets, Some(first_bonded_epoch_id)) + (total_bonded, bonded_assets) } else { let global_index = GLOBAL.may_load(deps.storage)?.unwrap_or_default(); - (global_index.bonded_amount, global_index.bonded_assets, None) + (global_index.bonded_amount, global_index.bonded_assets) }; Ok(BondedResponse { total_bonded, bonded_assets, - first_bonded_epoch_id, }) } -pub const MAX_PAGE_LIMIT: u8 = 30u8; -pub const DEFAULT_PAGE_LIMIT: u8 = 10u8; - /// Queries the current unbonding amount of the given address. pub(crate) fn query_unbonding( deps: Deps, @@ -80,18 +67,16 @@ pub(crate) fn query_unbonding( limit: Option, ) -> StdResult { let address = deps.api.addr_validate(&address)?; - let limit = limit.unwrap_or(DEFAULT_PAGE_LIMIT).min(MAX_PAGE_LIMIT) as usize; - let start = calc_range_start(start_after).map(Bound::ExclusiveRaw); - - let unbonding = UNBOND - .prefix((&deps.api.addr_validate(address.as_str())?, &denom)) - .range(deps.storage, start, None, Order::Ascending) - .take(limit) - .map(|item| { - let (_, bond) = item?; - Ok(bond) - }) - .collect::>>()?; + + let unbonding = get_bonds_by_receiver( + deps.storage, + address.to_string(), + Some(false), + Some(denom), + start_after, + limit, + )?; + // aggregate all the amounts in unbonding vec and return uint128 let unbonding_amount = unbonding.iter().try_fold(Uint128::zero(), |acc, bond| { acc.checked_add(bond.asset.amount) @@ -103,14 +88,6 @@ pub(crate) fn query_unbonding( }) } -fn calc_range_start(start_after: Option) -> Option> { - start_after.map(|block_height| { - let mut v: Vec = block_height.to_be_bytes().to_vec(); - v.push(0); - v - }) -} - /// Queries the amount of unbonding tokens of the specified address that have passed the /// unbonding period and can be withdrawn. pub(crate) fn query_withdrawable( @@ -118,11 +95,14 @@ pub(crate) fn query_withdrawable( address: String, denom: String, ) -> StdResult { - let unbonding: StdResult> = UNBOND - .prefix((&deps.api.addr_validate(address.as_str())?, &denom)) - .range(deps.storage, None, None, Order::Ascending) - .take(MAX_PAGE_LIMIT as usize) - .collect(); + let unbonding = get_bonds_by_receiver( + deps.storage, + address, + Some(false), + Some(denom), + None, + Some(MAX_LIMIT), + )?; let config = CONFIG.load(deps.storage)?; let current_epoch: white_whale_std::epoch_manager::epoch_manager::EpochResponse = @@ -132,7 +112,7 @@ pub(crate) fn query_withdrawable( )?; let mut withdrawable_amount = Uint128::zero(); - for (_, bond) in unbonding? { + for bond in unbonding { if current_epoch.epoch.id.saturating_sub(bond.created_at_epoch) >= config.unbonding_period { withdrawable_amount = withdrawable_amount.checked_add(bond.asset.amount)?; } @@ -186,6 +166,7 @@ pub fn query_claimable( claimable_reward_buckets.retain(|bucket| !bucket.available.is_empty()); } + println!("here: {:?}", claimable_reward_buckets); Ok(ClaimableRewardBucketsResponse { reward_buckets: claimable_reward_buckets, }) diff --git a/contracts/liquidity_hub/bonding-manager/src/state.rs b/contracts/liquidity_hub/bonding-manager/src/state.rs index d5102535..e9e16ee4 100644 --- a/contracts/liquidity_hub/bonding-manager/src/state.rs +++ b/contracts/liquidity_hub/bonding-manager/src/state.rs @@ -1,16 +1,41 @@ -use crate::ContractError; -use cosmwasm_std::{Addr, Decimal, DepsMut, StdError, StdResult, Uint128}; -use cw_storage_plus::{Item, Map}; +use cosmwasm_std::{Addr, Decimal, DepsMut, Order, StdError, StdResult, Storage, Uint128}; +use cw_storage_plus::{Bound, Index, IndexList, IndexedMap, Item, Map, MultiIndex}; + use white_whale_std::bonding_manager::{ Bond, Config, GlobalIndex, RewardBucket, UpcomingRewardBucket, }; -type Denom = str; +use crate::ContractError; pub const BONDING_ASSETS_LIMIT: usize = 2; pub const CONFIG: Item = Item::new("config"); -pub const BOND: Map<(&Addr, &Denom), Bond> = Map::new("bond"); -pub const UNBOND: Map<(&Addr, &Denom, u64), Bond> = Map::new("unbond"); + +/// A monotonically increasing counter to generate unique bond ids. +pub const BOND_COUNTER: Item = Item::new("bond_id_counter"); +pub const BONDS: IndexedMap = IndexedMap::new( + "bonds", + BondIndexes { + receiver: MultiIndex::new(|_pk, b| b.receiver.to_string(), "bonds", "bonds__receiver"), + asset_denom: MultiIndex::new( + |_pk, b| b.asset.denom.to_string(), + "bonds", + "bonds__asset_denom", + ), + }, +); + +pub struct BondIndexes<'a> { + pub receiver: MultiIndex<'a, String, Bond, String>, + pub asset_denom: MultiIndex<'a, String, Bond, String>, +} + +impl<'a> IndexList for BondIndexes<'a> { + fn get_indexes(&'_ self) -> Box> + '_> { + let v: Vec<&dyn Index> = vec![&self.receiver, &self.asset_denom]; + Box::new(v.into_iter()) + } +} + pub const GLOBAL: Item = Item::new("global"); pub const LAST_CLAIMED_EPOCH: Map<&Addr, u64> = Map::new("last_claimed_epoch"); pub const REWARD_BUCKETS: Map = Map::new("reward_buckets"); @@ -23,7 +48,6 @@ pub const UPCOMING_REWARD_BUCKET: Item = Item::new("upcomi /// Updates the local weight of the given address. pub fn update_bond_weight( deps: &mut DepsMut, - address: Addr, current_epoch_id: u64, mut bond: Bond, ) -> Result { @@ -38,7 +62,7 @@ pub fn update_bond_weight( )?; bond.last_updated = current_epoch_id; - BOND.save(deps.storage, (&address, &bond.asset.denom), &bond)?; + BONDS.save(deps.storage, bond.id, &bond)?; Ok(bond) } @@ -85,3 +109,51 @@ pub fn get_weight( Ok(weight.checked_add(amount.checked_mul(time_factor)? * growth_rate)?) } + +// settings for pagination +pub(crate) const MAX_LIMIT: u8 = 100; +pub const DEFAULT_LIMIT: u8 = 10; + +pub fn get_bonds_by_receiver( + storage: &dyn Storage, + receiver: String, + is_bonding: Option, + asset_denom: Option, + start_after: Option, + limit: Option, +) -> StdResult> { + let start = calc_range_start(start_after).map(Bound::ExclusiveRaw); + let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize; + + let mut bonds_by_receiver = BONDS + .idx + .receiver + .prefix(receiver) + .range(storage, start, None, Order::Ascending) + .take(limit) + .map(|item| { + let (_, bond) = item?; + Ok(bond) + }) + .collect::>>()?; + + println!("bonds_by_receiver: {:?}", bonds_by_receiver); + + if let Some(is_bonding) = is_bonding { + bonds_by_receiver.retain(|bond| bond.unbonded_at.is_none() == is_bonding); + } + + if let Some(asset_denom) = asset_denom { + bonds_by_receiver.retain(|bond| bond.asset.denom == asset_denom); + } + + Ok(bonds_by_receiver) +} + +fn calc_range_start(start_after: Option) -> Option> { + start_after.map(|block_height| { + let mut v: Vec = block_height.to_be_bytes().to_vec(); + v.push(0); + v + }) +} diff --git a/contracts/liquidity_hub/bonding-manager/src/tests/queries.rs b/contracts/liquidity_hub/bonding-manager/src/tests/queries.rs index b399961f..445d0864 100644 --- a/contracts/liquidity_hub/bonding-manager/src/tests/queries.rs +++ b/contracts/liquidity_hub/bonding-manager/src/tests/queries.rs @@ -205,7 +205,6 @@ fn test_queries() { denom: "ampWHALE".to_string(), amount: Uint128::from(1_000u128), }], - first_bonded_epoch_id: None, } ); }); @@ -245,32 +244,40 @@ fn test_queries() { total_amount: Uint128::new(1_000), unbonding_requests: vec![ Bond { + id: 2, asset: coin(100, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572056619), last_updated: 3, weight: Default::default(), + receiver: creator.clone() }, Bond { + id: 3, asset: coin(200, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572057619), last_updated: 3, weight: Default::default(), + receiver: creator.clone() }, Bond { + id: 4, asset: coin(300, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572058619), last_updated: 3, weight: Default::default(), + receiver: creator.clone() }, Bond { + id: 5, asset: coin(400, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572059619), last_updated: 3, weight: Default::default(), + receiver: creator.clone() }, ], } @@ -290,18 +297,22 @@ fn test_queries() { total_amount: Uint128::new(300), unbonding_requests: vec![ Bond { + id: 2, asset: coin(100, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572056619), last_updated: 3, weight: Default::default(), + receiver: creator.clone(), }, Bond { + id: 3, asset: coin(200, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572057619), last_updated: 3, weight: Default::default(), + receiver: creator.clone(), }, ], } @@ -312,7 +323,7 @@ fn test_queries() { suite.query_unbonding( creator.clone().to_string(), "ampWHALE".to_string(), - Some(1572057619), + Some(3), Some(2), |res| { let unbonding_response = res.unwrap().1; @@ -322,18 +333,22 @@ fn test_queries() { total_amount: Uint128::new(700), unbonding_requests: vec![ Bond { + id: 4, asset: coin(300, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572058619), last_updated: 3, weight: Default::default(), + receiver: creator.clone() }, Bond { + id: 5, asset: coin(400, "ampWHALE"), created_at_epoch: 3, unbonded_at: Some(1572059619), last_updated: 3, weight: Default::default(), + receiver: creator.clone() }, ], } diff --git a/contracts/liquidity_hub/bonding-manager/src/tests/unbond_withdraw.rs b/contracts/liquidity_hub/bonding-manager/src/tests/unbond_withdraw.rs index 47ede32b..4bf30267 100644 --- a/contracts/liquidity_hub/bonding-manager/src/tests/unbond_withdraw.rs +++ b/contracts/liquidity_hub/bonding-manager/src/tests/unbond_withdraw.rs @@ -502,11 +502,13 @@ fn test_unbonding_withdraw() { assert_eq!( unbonding_response.unbonding_requests[0], Bond { + id: 4, asset: coin(1_000u128, "ampWHALE"), created_at_epoch: 6, unbonded_at: Some(1572335819), last_updated: 6, weight: Uint128::zero(), + receiver: creator.clone(), } ); }, @@ -724,7 +726,6 @@ fn test_unbonding_withdraw() { BondedResponse { total_bonded: Uint128::new(200), bonded_assets: coins(200u128, "bWHALE"), - first_bonded_epoch_id: Some(4u64), } ); }) @@ -741,18 +742,22 @@ fn test_unbonding_withdraw() { total_amount: Uint128::new(500), unbonding_requests: vec![ Bond { + id: 5, asset: coin(300u128, "bWHALE"), created_at_epoch: 8, unbonded_at: Some(1572508619), last_updated: 8, weight: Uint128::zero(), + receiver: another_sender.clone(), }, Bond { + id: 6, asset: coin(200u128, "bWHALE"), created_at_epoch: 8, unbonded_at: Some(1572508620), last_updated: 8, weight: Uint128::zero(), + receiver: another_sender.clone(), } ], } @@ -964,7 +969,6 @@ fn test_unbonding_withdraw() { BondedResponse { total_bonded: Uint128::new(200), bonded_assets: coins(200u128, "bWHALE"), - first_bonded_epoch_id: Some(4u64), } ); }) diff --git a/contracts/liquidity_hub/incentive-manager/src/state.rs b/contracts/liquidity_hub/incentive-manager/src/state.rs index d6430e94..245d539f 100644 --- a/contracts/liquidity_hub/incentive-manager/src/state.rs +++ b/contracts/liquidity_hub/incentive-manager/src/state.rs @@ -11,7 +11,7 @@ use crate::ContractError; /// Contract's config pub const CONFIG: Item = Item::new("config"); -/// An monotonically increasing counter to generate unique position identifiers. +/// A monotonically increasing counter to generate unique position identifiers. pub const POSITION_ID_COUNTER: Item = Item::new("position_id_counter"); /// The positions that a user has. Positions can be open or closed. @@ -47,7 +47,7 @@ pub const LAST_CLAIMED_EPOCH: Map<&Addr, EpochId> = Map::new("last_claimed_epoch pub const LP_WEIGHT_HISTORY: Map<(&Addr, &str, EpochId), Uint128> = Map::new("address_lp_weight_history"); -/// An monotonically increasing counter to generate unique incentive identifiers. +/// A monotonically increasing counter to generate unique incentive identifiers. pub const INCENTIVE_COUNTER: Item = Item::new("incentive_counter"); /// Incentives map diff --git a/packages/white-whale-std/src/bonding_manager.rs b/packages/white-whale-std/src/bonding_manager.rs index 1724734a..0259919a 100644 --- a/packages/white-whale-std/src/bonding_manager.rs +++ b/packages/white-whale-std/src/bonding_manager.rs @@ -54,6 +54,8 @@ pub struct UpcomingRewardBucket { #[cw_serde] pub struct Bond { + /// The id of the bond. + pub id: u64, /// The epoch id at which the Bond was created. pub created_at_epoch: u64, /// The epoch id at which the bond was last time updated. @@ -64,11 +66,14 @@ pub struct Bond { pub weight: Uint128, /// The time at which the Bond was unbonded. pub unbonded_at: Option, + /// The owner of the bond. + pub receiver: Addr, } impl Default for Bond { fn default() -> Self { Self { + id: 0, asset: Coin { denom: String::new(), amount: Uint128::zero(), @@ -77,6 +82,7 @@ impl Default for Bond { unbonded_at: None, last_updated: Default::default(), weight: Uint128::zero(), + receiver: Addr::unchecked(""), } } } @@ -229,11 +235,8 @@ pub struct BondedResponse { /// The total amount of bonded tokens by the address. Bear in mind the bonded assets are /// considered to be equal for this purpose. pub total_bonded: Uint128, - /// The total amount of bonded assets by the address. + /// The assets that are bonded by the address. pub bonded_assets: Vec, - /// If Some, the epoch id at which the user/address bonded first time. None is used when this - /// Response is used to check the bonded assets in the contract. - pub first_bonded_epoch_id: Option, } /// Response for the Unbonding query