diff --git a/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json b/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json index ee01742b..ab97866b 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json +++ b/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json @@ -31,7 +31,7 @@ "type": "string" }, "grace_period": { - "description": "Grace period the maximum age of a epoch bucket before it's considered expired and fees are forwarded from it", + "description": "Grace period the maximum age of a reward bucket before it's considered expired and fees are forwarded from it", "type": "integer", "format": "uint64", "minimum": 0.0 @@ -185,7 +185,7 @@ ] }, { - "description": "Creates a new bucket for the rewards flowing from this time on, i.e. to be distributed in the upcoming epoch. Also, forwards the expiring epoch (only 21 epochs are live at a given moment)", + "description": "Epoch Changed hook implementation. Creates a new reward bucket for the rewards flowing from this time on, i.e. to be distributed in the upcoming epoch. Also, forwards the expiring reward bucket (only 21 of them are live at a given moment)", "type": "object", "required": [ "epoch_changed_hook" @@ -538,7 +538,7 @@ ] }, { - "description": "Returns the [Epoch]s that can be claimed by an address.", + "description": "Returns the [RewardBucket]s that can be claimed by an address.", "type": "object", "required": [ "claimable" @@ -548,7 +548,7 @@ "type": "object", "properties": { "address": { - "description": "The address to check for claimable epochs. If none is provided, all possible epochs stored in the contract that can potentially be claimed are returned.", + "description": "The address to check for claimable reward buckets. If none is provided, all possible reward buckets stored in the contract that can potentially be claimed are returned.", "type": [ "string", "null" @@ -706,17 +706,17 @@ }, "claimable": { "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ClaimableEpochsResponse", + "title": "ClaimableRewardBucketsResponse", "type": "object", "required": [ - "epochs" + "reward_buckets" ], "properties": { - "epochs": { - "description": "The epochs that can be claimed by the address.", + "reward_buckets": { + "description": "The reward buckets that can be claimed by the address.", "type": "array", "items": { - "$ref": "#/definitions/Epoch" + "$ref": "#/definitions/RewardBucket" } } }, @@ -737,49 +737,6 @@ } } }, - "Epoch": { - "type": "object", - "required": [ - "available", - "claimed", - "global_index", - "id", - "start_time", - "total" - ], - "properties": { - "available": { - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - } - }, - "claimed": { - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - } - }, - "global_index": { - "$ref": "#/definitions/GlobalIndex" - }, - "id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "total": { - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - } - } - }, - "additionalProperties": false - }, "GlobalIndex": { "type": "object", "required": [ @@ -821,6 +778,49 @@ }, "additionalProperties": false }, + "RewardBucket": { + "type": "object", + "required": [ + "available", + "claimed", + "epoch_id", + "epoch_start_time", + "global_index", + "total" + ], + "properties": { + "available": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "claimed": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "epoch_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "epoch_start_time": { + "$ref": "#/definitions/Timestamp" + }, + "global_index": { + "$ref": "#/definitions/GlobalIndex" + }, + "total": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + } + }, + "additionalProperties": false + }, "Timestamp": { "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", "allOf": [ @@ -873,7 +873,7 @@ ] }, "grace_period": { - "description": "Grace period the maximum age of a epoch bucket before it's considered expired and fees are forwarded from it", + "description": "Grace period the maximum age of a reward bucket before it's considered expired and fees are forwarded from it", "type": "integer", "format": "uint64", "minimum": 0.0 diff --git a/contracts/liquidity_hub/bonding-manager/schema/raw/execute.json b/contracts/liquidity_hub/bonding-manager/schema/raw/execute.json index c6a562de..4df3f63b 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/raw/execute.json +++ b/contracts/liquidity_hub/bonding-manager/schema/raw/execute.json @@ -124,7 +124,7 @@ ] }, { - "description": "Creates a new bucket for the rewards flowing from this time on, i.e. to be distributed in the upcoming epoch. Also, forwards the expiring epoch (only 21 epochs are live at a given moment)", + "description": "Epoch Changed hook implementation. Creates a new reward bucket for the rewards flowing from this time on, i.e. to be distributed in the upcoming epoch. Also, forwards the expiring reward bucket (only 21 of them are live at a given moment)", "type": "object", "required": [ "epoch_changed_hook" diff --git a/contracts/liquidity_hub/bonding-manager/schema/raw/instantiate.json b/contracts/liquidity_hub/bonding-manager/schema/raw/instantiate.json index f93d08e6..e331cda5 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/raw/instantiate.json +++ b/contracts/liquidity_hub/bonding-manager/schema/raw/instantiate.json @@ -27,7 +27,7 @@ "type": "string" }, "grace_period": { - "description": "Grace period the maximum age of a epoch bucket before it's considered expired and fees are forwarded from it", + "description": "Grace period the maximum age of a reward bucket before it's considered expired and fees are forwarded from it", "type": "integer", "format": "uint64", "minimum": 0.0 diff --git a/contracts/liquidity_hub/bonding-manager/schema/raw/query.json b/contracts/liquidity_hub/bonding-manager/schema/raw/query.json index 3c5ab6ae..7139a19f 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/raw/query.json +++ b/contracts/liquidity_hub/bonding-manager/schema/raw/query.json @@ -157,7 +157,7 @@ ] }, { - "description": "Returns the [Epoch]s that can be claimed by an address.", + "description": "Returns the [RewardBucket]s that can be claimed by an address.", "type": "object", "required": [ "claimable" @@ -167,7 +167,7 @@ "type": "object", "properties": { "address": { - "description": "The address to check for claimable epochs. If none is provided, all possible epochs stored in the contract that can potentially be claimed are returned.", + "description": "The address to check for claimable reward buckets. If none is provided, all possible reward buckets stored in the contract that can potentially be claimed are returned.", "type": [ "string", "null" diff --git a/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_claimable.json b/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_claimable.json index 41023177..01cc278f 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_claimable.json +++ b/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_claimable.json @@ -1,16 +1,16 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ClaimableEpochsResponse", + "title": "ClaimableRewardBucketsResponse", "type": "object", "required": [ - "epochs" + "reward_buckets" ], "properties": { - "epochs": { - "description": "The epochs that can be claimed by the address.", + "reward_buckets": { + "description": "The reward buckets that can be claimed by the address.", "type": "array", "items": { - "$ref": "#/definitions/Epoch" + "$ref": "#/definitions/RewardBucket" } } }, @@ -31,49 +31,6 @@ } } }, - "Epoch": { - "type": "object", - "required": [ - "available", - "claimed", - "global_index", - "id", - "start_time", - "total" - ], - "properties": { - "available": { - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - } - }, - "claimed": { - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - } - }, - "global_index": { - "$ref": "#/definitions/GlobalIndex" - }, - "id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "total": { - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - } - } - }, - "additionalProperties": false - }, "GlobalIndex": { "type": "object", "required": [ @@ -115,6 +72,49 @@ }, "additionalProperties": false }, + "RewardBucket": { + "type": "object", + "required": [ + "available", + "claimed", + "epoch_id", + "epoch_start_time", + "global_index", + "total" + ], + "properties": { + "available": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "claimed": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "epoch_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "epoch_start_time": { + "$ref": "#/definitions/Timestamp" + }, + "global_index": { + "$ref": "#/definitions/GlobalIndex" + }, + "total": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + } + }, + "additionalProperties": false + }, "Timestamp": { "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", "allOf": [ diff --git a/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json b/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json index 20a56f53..498ca242 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json +++ b/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json @@ -32,7 +32,7 @@ ] }, "grace_period": { - "description": "Grace period the maximum age of a epoch bucket before it's considered expired and fees are forwarded from it", + "description": "Grace period the maximum age of a reward bucket before it's considered expired and fees are forwarded from it", "type": "integer", "format": "uint64", "minimum": 0.0 diff --git a/contracts/liquidity_hub/bonding-manager/src/commands.rs b/contracts/liquidity_hub/bonding-manager/src/commands.rs index 63441446..4183c649 100644 --- a/contracts/liquidity_hub/bonding-manager/src/commands.rs +++ b/contracts/liquidity_hub/bonding-manager/src/commands.rs @@ -3,14 +3,14 @@ use cosmwasm_std::{ StdError, StdResult, SubMsg, Uint128, Uint64, }; -use white_whale_std::bonding_manager::{Bond, Epoch, GlobalIndex}; +use white_whale_std::bonding_manager::{Bond, GlobalIndex, RewardBucket}; use white_whale_std::pool_network::asset; use crate::helpers::validate_growth_rate; use crate::queries::{get_expiring_epoch, query_claimable, query_weight, MAX_PAGE_LIMIT}; use crate::state::{ - update_global_weight, update_local_weight, BOND, CONFIG, EPOCHS, GLOBAL, LAST_CLAIMED_EPOCH, - UNBOND, + update_global_weight, update_local_weight, BOND, CONFIG, GLOBAL, LAST_CLAIMED_EPOCH, + REWARD_BUCKETS, UNBOND, }; use crate::{helpers, ContractError}; @@ -244,7 +244,7 @@ pub(crate) fn update_config( /// Claims pending rewards for the sender. pub fn claim(deps: DepsMut, info: MessageInfo) -> Result { let claimable_epochs_for_user = - query_claimable(deps.as_ref(), Some(info.sender.to_string()))?.epochs; + query_claimable(deps.as_ref(), Some(info.sender.to_string()))?.reward_buckets; ensure!( !claimable_epochs_for_user.is_empty(), ContractError::NothingToClaim @@ -255,7 +255,7 @@ pub fn claim(deps: DepsMut, info: MessageInfo) -> Result Result Result { println!( "EPOCHS: {:?}", - EPOCHS + REWARD_BUCKETS .keys(deps.storage, None, None, Order::Descending) .collect::>() ); // Finding the most recent EpochID - let upcoming_epoch_id = match EPOCHS + let upcoming_epoch_id = match REWARD_BUCKETS .keys(deps.storage, None, None, Order::Descending) .next() { @@ -422,7 +426,7 @@ pub(crate) fn fill_rewards( // of all the LP token withdrawals and swaps // Because we are using minimum receive, it is possible the contract can accumulate micro amounts of whale if we get more than what the swap query returned // If this became an issue would could look at replys instead of the query - EPOCHS.update(deps.storage, &upcoming_epoch_id, |bucket| -> StdResult<_> { + REWARD_BUCKETS.update(deps.storage, upcoming_epoch_id, |bucket| -> StdResult<_> { let mut bucket = bucket.unwrap_or_default(); bucket.available = asset::aggregate_coins(bucket.available, vec![whale.clone()])?; bucket.total = asset::aggregate_coins(bucket.total, vec![whale.clone()])?; @@ -458,14 +462,14 @@ pub(crate) fn on_epoch_created( ..Default::default() }; GLOBAL.save(deps.storage, &initial_global_index)?; - EPOCHS.save( + REWARD_BUCKETS.save( deps.storage, - ¤t_epoch.id.to_be_bytes(), - &Epoch { - id: current_epoch.id, - start_time: current_epoch.start_time, + current_epoch.id, + &RewardBucket { + epoch_id: current_epoch.id, + epoch_start_time: current_epoch.start_time, global_index: initial_global_index, - ..Epoch::default() + ..RewardBucket::default() }, )?; } @@ -473,24 +477,20 @@ pub(crate) fn on_epoch_created( let global = GLOBAL.load(deps.storage)?; // update the global index for the current epoch, take the current snapshot of the global index - EPOCHS.update( - deps.storage, - ¤t_epoch.id.to_be_bytes(), - |epoch| -> StdResult<_> { - let mut epoch = epoch.unwrap_or_default(); - epoch.global_index = global; - Ok(epoch) - }, - )?; + REWARD_BUCKETS.update(deps.storage, current_epoch.id, |epoch| -> StdResult<_> { + let mut epoch = epoch.unwrap_or_default(); + epoch.global_index = global; + Ok(epoch) + })?; // todo to delete once the testing is done - let all_epochs: Vec = EPOCHS + let all_epochs: Vec = REWARD_BUCKETS .range(deps.storage, None, None, Order::Descending) .map(|item| { let (_, epoch) = item?; Ok(epoch) }) - .collect::>>()?; + .collect::>>()?; println!("EPOCHS: {:?}", all_epochs); @@ -498,26 +498,22 @@ pub(crate) fn on_epoch_created( let mut expiring_epoch = get_expiring_epoch(deps.as_ref())?; if let Some(expiring_epoch) = expiring_epoch.as_mut() { // Load all the available assets from the expiring epoch - let amount_to_be_forwarded = EPOCHS - .load(deps.storage, &expiring_epoch.id.to_be_bytes())? + let amount_to_be_forwarded = REWARD_BUCKETS + .load(deps.storage, expiring_epoch.epoch_id)? .available; - EPOCHS.update( - deps.storage, - ¤t_epoch.id.to_be_bytes(), - |epoch| -> StdResult<_> { - let mut epoch = epoch.unwrap_or_default(); - epoch.available = - asset::aggregate_coins(epoch.available, amount_to_be_forwarded.clone())?; - epoch.total = asset::aggregate_coins(epoch.total, amount_to_be_forwarded)?; + REWARD_BUCKETS.update(deps.storage, current_epoch.id, |epoch| -> StdResult<_> { + let mut epoch = epoch.unwrap_or_default(); + epoch.available = + asset::aggregate_coins(epoch.available, amount_to_be_forwarded.clone())?; + epoch.total = asset::aggregate_coins(epoch.total, amount_to_be_forwarded)?; - Ok(epoch) - }, - )?; + Ok(epoch) + })?; // Set the available assets for the expiring epoch to an empty vec now that they have been // forwarded - EPOCHS.update( + REWARD_BUCKETS.update( deps.storage, - &expiring_epoch.id.to_be_bytes(), + expiring_epoch.epoch_id, |epoch| -> StdResult<_> { let mut epoch = epoch.unwrap_or_default(); epoch.available = vec![]; @@ -531,16 +527,16 @@ pub(crate) fn on_epoch_created( let next_epoch_id = Uint64::new(current_epoch.id) .checked_add(Uint64::one())? .u64(); - EPOCHS.save( + REWARD_BUCKETS.save( deps.storage, - &next_epoch_id.to_be_bytes(), - &Epoch { - id: next_epoch_id, - start_time: current_epoch.start_time.plus_days(1), + next_epoch_id, + &RewardBucket { + epoch_id: next_epoch_id, + epoch_start_time: current_epoch.start_time.plus_days(1), // this global index is to be updated the next time this hook is called, as this future epoch // will become the current one global_index: Default::default(), - ..Epoch::default() + ..RewardBucket::default() }, )?; diff --git a/contracts/liquidity_hub/bonding-manager/src/contract.rs b/contracts/liquidity_hub/bonding-manager/src/contract.rs index 92dda2e8..a903f65c 100644 --- a/contracts/liquidity_hub/bonding-manager/src/contract.rs +++ b/contracts/liquidity_hub/bonding-manager/src/contract.rs @@ -8,7 +8,7 @@ use white_whale_std::pool_network::asset; use crate::error::ContractError; use crate::helpers::{self, validate_growth_rate}; -use crate::state::{BONDING_ASSETS_LIMIT, CONFIG, EPOCHS}; +use crate::state::{BONDING_ASSETS_LIMIT, CONFIG, REWARD_BUCKETS}; use crate::{commands, queries}; // version info for migration info @@ -197,7 +197,7 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result Result return Err(ContractError::Unauthorized), }; - EPOCHS.update(deps.storage, &upcoming_epoch_id, |epoch| -> StdResult<_> { - let mut upcoming_epoch = epoch.unwrap_or_default(); - upcoming_epoch.available = asset::aggregate_coins( - upcoming_epoch.available, - vec![to_be_distribution_asset.clone()], - )?; - upcoming_epoch.total = asset::aggregate_coins( - upcoming_epoch.total, - vec![to_be_distribution_asset.clone()], - )?; - Ok(upcoming_epoch) - })?; + REWARD_BUCKETS.update( + deps.storage, + upcoming_epoch_id, + |epoch| -> StdResult<_> { + let mut upcoming_epoch = epoch.unwrap_or_default(); + upcoming_epoch.available = asset::aggregate_coins( + upcoming_epoch.available, + vec![to_be_distribution_asset.clone()], + )?; + upcoming_epoch.total = asset::aggregate_coins( + upcoming_epoch.total, + vec![to_be_distribution_asset.clone()], + )?; + Ok(upcoming_epoch) + }, + )?; } Ok(Response::new() diff --git a/contracts/liquidity_hub/bonding-manager/src/helpers.rs b/contracts/liquidity_hub/bonding-manager/src/helpers.rs index 67cbe51c..e0523abc 100644 --- a/contracts/liquidity_hub/bonding-manager/src/helpers.rs +++ b/contracts/liquidity_hub/bonding-manager/src/helpers.rs @@ -3,7 +3,7 @@ use cosmwasm_std::{ StdResult, SubMsg, Timestamp, Uint64, WasmMsg, }; use cw_utils::PaymentError; -use white_whale_std::bonding_manager::{ClaimableEpochsResponse, Config}; +use white_whale_std::bonding_manager::{ClaimableRewardBucketsResponse, Config}; use white_whale_std::constants::{DAY_IN_SECONDS, LP_SYMBOL}; use white_whale_std::epoch_manager::epoch_manager::{EpochConfig, EpochResponse}; use white_whale_std::pool_manager::{ @@ -13,7 +13,7 @@ use white_whale_std::pool_manager::{ use crate::contract::LP_WITHDRAWAL_REPLY_ID; use crate::error::ContractError; use crate::queries::query_claimable; -use crate::state::{CONFIG, EPOCHS}; +use crate::state::{CONFIG, REWARD_BUCKETS}; /// Validates that the growth rate is between 0 and 1. pub fn validate_growth_rate(growth_rate: Decimal) -> Result<(), ContractError> { @@ -55,11 +55,11 @@ pub fn validate_funds(deps: &DepsMut, info: &MessageInfo) -> Result Result<(), ContractError> { // Do a smart query for Claimable - let claimable_rewards: ClaimableEpochsResponse = + let claimable_rewards: ClaimableRewardBucketsResponse = query_claimable(deps.as_ref(), Some(info.sender.to_string())).unwrap(); // ensure the user has nothing to claim ensure!( - claimable_rewards.epochs.is_empty(), + claimable_rewards.reward_buckets.is_empty(), ContractError::UnclaimedRewards ); @@ -288,7 +288,7 @@ pub fn swap_coins_to_main_token( /// Validates that there are epochs in the state. If there are none, it means the system has just /// been started and the epoch manager has still not created any epochs yet. pub(crate) fn validate_epochs(deps: &DepsMut) -> Result<(), ContractError> { - let epochs = EPOCHS + let epochs = REWARD_BUCKETS .keys(deps.storage, None, None, Order::Descending) .collect::>>()?; diff --git a/contracts/liquidity_hub/bonding-manager/src/queries.rs b/contracts/liquidity_hub/bonding-manager/src/queries.rs index 0e0d8975..e5a425f4 100644 --- a/contracts/liquidity_hub/bonding-manager/src/queries.rs +++ b/contracts/liquidity_hub/bonding-manager/src/queries.rs @@ -8,10 +8,11 @@ use white_whale_std::bonding_manager::{ Bond, BondedResponse, BondingWeightResponse, Config, GlobalIndex, UnbondingResponse, WithdrawableResponse, }; -use white_whale_std::bonding_manager::{ClaimableEpochsResponse, Epoch}; +use white_whale_std::bonding_manager::{ClaimableRewardBucketsResponse, RewardBucket}; use crate::state::{ - get_weight, BOND, BONDING_ASSETS_LIMIT, CONFIG, EPOCHS, GLOBAL, LAST_CLAIMED_EPOCH, UNBOND, + get_weight, BOND, BONDING_ASSETS_LIMIT, CONFIG, GLOBAL, LAST_CLAIMED_EPOCH, REWARD_BUCKETS, + UNBOND, }; /// Queries the current configuration of the contract. @@ -227,26 +228,26 @@ pub fn query_global_index(deps: Deps) -> StdResult { /// Returns the epoch that is falling out the grace period, which is the one expiring after creating /// a new epoch is created. -pub fn get_expiring_epoch(deps: Deps) -> Result, ContractError> { +pub fn get_expiring_epoch(deps: Deps) -> Result, ContractError> { let config = CONFIG.load(deps.storage)?; // Adding 1 because we store the future epoch in the map also, so grace_period + 1 let grace_period_plus_future_epoch = Uint64::new(config.grace_period) .checked_add(Uint64::one())? .u64(); // Take grace_period + 1 and then slice last one off - let epochs = EPOCHS + let epochs = REWARD_BUCKETS .range(deps.storage, None, None, Order::Descending) .take(grace_period_plus_future_epoch as usize) .map(|item| { let (_, epoch) = item?; Ok(epoch) }) - .collect::>>()?; + .collect::>>()?; // if the epochs vector's length is the same as the grace period it means there is one epoch that // is expiring once the new one is created i.e. the last epoch in the vector if epochs.len() == grace_period_plus_future_epoch as usize { - let expiring_epoch: Epoch = epochs.into_iter().last().unwrap_or_default(); + let expiring_epoch: RewardBucket = epochs.into_iter().last().unwrap_or_default(); Ok(Some(expiring_epoch)) } else { // nothing is expiring yet @@ -256,14 +257,14 @@ pub fn get_expiring_epoch(deps: Deps) -> Result, ContractError> { /// Returns the epochs that are within the grace period, i.e. the ones which fees can still be claimed. /// The result is ordered by epoch id, descending. Thus, the first element is the current epoch. -pub fn get_claimable_epochs(deps: Deps) -> StdResult { +pub fn get_claimable_epochs(deps: Deps) -> StdResult { let config = CONFIG.load(deps.storage)?; // Adding 1 because we store the future epoch in the map also, so grace_period + 1 let grace_period = Uint64::new(config.grace_period) .checked_add(Uint64::one())? .u64(); // Take grace_period + 1 and then slice last one off - let mut epochs = EPOCHS + let mut epochs = REWARD_BUCKETS .range(deps.storage, None, None, Order::Descending) .take(grace_period as usize) .map(|item| { @@ -271,7 +272,7 @@ pub fn get_claimable_epochs(deps: Deps) -> StdResult { Ok(epoch) }) - .collect::>>()?; + .collect::>>()?; println!("epochs: {:?}", epochs); @@ -281,15 +282,18 @@ pub fn get_claimable_epochs(deps: Deps) -> StdResult { println!("epochs: {:?}", epochs); - Ok(ClaimableEpochsResponse { - epochs: epochs.into(), + Ok(ClaimableRewardBucketsResponse { + reward_buckets: epochs.into(), }) } /// Returns the epochs that can be claimed by the given address. If no address is provided, /// returns all possible epochs stored in the contract that can potentially be claimed. -pub fn query_claimable(deps: Deps, address: Option) -> StdResult { - let mut claimable_epochs = get_claimable_epochs(deps)?.epochs; +pub fn query_claimable( + deps: Deps, + address: Option, +) -> StdResult { + let mut claimable_epochs = get_claimable_epochs(deps)?.reward_buckets; // if an address is provided, filter what's claimable for that address if let Some(address) = address { @@ -299,7 +303,7 @@ pub fn query_claimable(deps: Deps, address: Option) -> StdResult last_claimed_epoch); + claimable_epochs.retain(|epoch| epoch.epoch_id > last_claimed_epoch); } else { // if the user doesn't have any last_claimed_epoch two things might be happening: // 1- the user has never bonded before @@ -316,7 +320,7 @@ pub fn query_claimable(deps: Deps, address: Option) -> StdResult { // keep all epochs that are newer than the first bonded epoch - claimable_epochs.retain(|epoch| epoch.id > first_bonded_epoch_id); + claimable_epochs.retain(|epoch| epoch.epoch_id > first_bonded_epoch_id); } None => { // for sanity, it should never happen @@ -331,7 +335,7 @@ pub fn query_claimable(deps: Deps, address: Option) -> StdResult = Map::new("bond"); pub const UNBOND: Map<(&Addr, &Denom, u64), Bond> = Map::new("unbond"); pub const GLOBAL: Item = Item::new("global"); pub const LAST_CLAIMED_EPOCH: Map<&Addr, u64> = Map::new("last_claimed_epoch"); -pub const EPOCHS: Map<&[u8], Epoch> = Map::new("epochs"); +pub const REWARD_BUCKETS: Map = Map::new("epochs"); /// Updates the local weight of the given address. pub fn update_local_weight( @@ -87,18 +87,18 @@ pub fn get_weight( /// Returns the epoch that is falling out the grace period, which is the one expiring after creating /// a new epoch is created. -pub fn get_expiring_epoch(deps: Deps) -> StdResult> { +pub fn get_expiring_epoch(deps: Deps) -> StdResult> { let grace_period = CONFIG.load(deps.storage)?.grace_period; // last epochs within the grace period - let epochs = EPOCHS + let epochs = REWARD_BUCKETS .range(deps.storage, None, None, Order::Descending) .take(grace_period as usize) .map(|item| { let (_, epoch) = item?; Ok(epoch) }) - .collect::>>()?; + .collect::>>()?; // if the epochs vector's length is the same as the grace period it means there is one epoch that // is expiring once the new one is created i.e. the last epoch in the vector diff --git a/contracts/liquidity_hub/bonding-manager/src/tests/suite.rs b/contracts/liquidity_hub/bonding-manager/src/tests/suite.rs index 3eb472bd..d64af205 100644 --- a/contracts/liquidity_hub/bonding-manager/src/tests/suite.rs +++ b/contracts/liquidity_hub/bonding-manager/src/tests/suite.rs @@ -11,13 +11,13 @@ use cw_multi_test::{ use white_whale_std::fee::PoolFee; use white_whale_testing::multi_test::stargate_mock::StargateMock; -use crate::state::{CONFIG, EPOCHS}; +use crate::state::{CONFIG, REWARD_BUCKETS}; use cw_multi_test::{Contract, ContractWrapper}; use white_whale_std::bonding_manager::{ BondedResponse, BondingWeightResponse, Config, ExecuteMsg, InstantiateMsg, QueryMsg, UnbondingResponse, WithdrawableResponse, }; -use white_whale_std::bonding_manager::{ClaimableEpochsResponse, Epoch}; +use white_whale_std::bonding_manager::{ClaimableRewardBucketsResponse, RewardBucket}; use white_whale_std::epoch_manager::epoch_manager::{Epoch as EpochV2, EpochConfig}; use white_whale_std::pool_manager::PoolType; @@ -370,12 +370,12 @@ impl TestingSuite { self } - pub(crate) fn add_epochs_to_state(&mut self, epochs: Vec) -> &mut Self { + pub(crate) fn add_epochs_to_state(&mut self, epochs: Vec) -> &mut Self { for epoch in epochs { - EPOCHS + REWARD_BUCKETS .save( &mut self.owned_deps.storage, - &epoch.id.to_be_bytes(), + &epoch.epoch_id.to_be_bytes(), &epoch, ) .unwrap(); @@ -470,7 +470,7 @@ impl TestingSuite { pub(crate) fn query_claimable_epochs( &mut self, address: Option, - response: impl Fn(StdResult<(&mut Self, Vec)>), + response: impl Fn(StdResult<(&mut Self, Vec)>), ) -> &mut Self { let address = if let Some(address) = address { Some(address.to_string()) @@ -478,13 +478,13 @@ impl TestingSuite { None }; - let query_res: ClaimableEpochsResponse = self + let query_res: ClaimableRewardBucketsResponse = self .app .wrap() .query_wasm_smart(&self.bonding_manager_addr, &QueryMsg::Claimable { address }) .unwrap(); - response(Ok((self, query_res.epochs))); + response(Ok((self, query_res.reward_buckets))); self } diff --git a/packages/white-whale-std/src/bonding_manager.rs b/packages/white-whale-std/src/bonding_manager.rs index 953a2404..df437cf1 100644 --- a/packages/white-whale-std/src/bonding_manager.rs +++ b/packages/white-whale-std/src/bonding_manager.rs @@ -1,4 +1,4 @@ -use crate::epoch_manager::epoch_manager::Epoch as EpochV2; +use crate::epoch_manager::epoch_manager::Epoch; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{ @@ -22,25 +22,26 @@ pub struct Config { pub growth_rate: Decimal, /// Denom of the asset to be bonded. Can't only be set at instantiation. pub bonding_assets: Vec, - /// Grace period the maximum age of a epoch bucket before it's considered expired and fees + /// Grace period the maximum age of a reward bucket before it's considered expired and fees /// are forwarded from it pub grace_period: u64, } #[cw_serde] #[derive(Default)] -pub struct Epoch { - // Epoch identifier - pub id: u64, +pub struct RewardBucket { + // Epoch id the reward bucket is associated with + pub epoch_id: u64, // Epoch start time - pub start_time: Timestamp, - // Initial fees to be distributed in this epoch. + pub epoch_start_time: Timestamp, + // Initial fees to be distributed in this reward bucket. pub total: Vec, - // Fees left to be claimed on this epoch. These available fees are forwarded when the epoch expires. + // Fees left to be claimed on this reward bucket. These available fees are forwarded when the + // reward bucket expires. pub available: Vec, - // Fees that were claimed on this epoch. For keeping record on the total fees claimed. + // Fees that were claimed on this reward bucket. For keeping record on the total fees claimed. pub claimed: Vec, - // Global index taken at the time of Epoch Creation + // Global index snapshot taken at the time of reward bucket creation pub global_index: GlobalIndex, } @@ -94,7 +95,7 @@ pub struct InstantiateMsg { pub growth_rate: Decimal, /// [String] denoms of the assets that can be bonded. pub bonding_assets: Vec, - /// Grace period the maximum age of a epoch bucket before it's considered expired and fees + /// Grace period the maximum age of a reward bucket before it's considered expired and fees /// are forwarded from it pub grace_period: u64, /// The epoch manager contract @@ -103,7 +104,7 @@ pub struct InstantiateMsg { #[cw_serde] pub struct EpochChangedHookMsg { - pub current_epoch: EpochV2, + pub current_epoch: Epoch, } #[cw_ownable_execute] @@ -138,11 +139,12 @@ pub enum ExecuteMsg { /// Fills the contract with new rewards. FillRewards, - /// Creates a new bucket for the rewards flowing from this time on, i.e. to be distributed in - /// the upcoming epoch. Also, forwards the expiring epoch (only 21 epochs are live at a given moment) + /// Epoch Changed hook implementation. Creates a new reward bucket for the rewards flowing from + /// this time on, i.e. to be distributed in the upcoming epoch. Also, forwards the expiring + /// reward bucket (only 21 of them are live at a given moment) EpochChangedHook { /// The current epoch, the one that was newly created. - current_epoch: EpochV2, + current_epoch: Epoch, }, } @@ -201,11 +203,11 @@ pub enum QueryMsg { #[returns(GlobalIndex)] GlobalIndex, - /// Returns the [Epoch]s that can be claimed by an address. - #[returns(ClaimableEpochsResponse)] + /// Returns the [RewardBucket]s that can be claimed by an address. + #[returns(ClaimableRewardBucketsResponse)] Claimable { - /// The address to check for claimable epochs. If none is provided, all possible epochs - /// stored in the contract that can potentially be claimed are returned. + /// The address to check for claimable reward buckets. If none is provided, all possible + /// reward buckets stored in the contract that can potentially be claimed are returned. address: Option, }, } @@ -267,7 +269,7 @@ pub fn fill_rewards_msg(contract_addr: String, assets: Vec) -> StdResult, +pub struct ClaimableRewardBucketsResponse { + /// The reward buckets that can be claimed by the address. + pub reward_buckets: Vec, }