check for 0 input sats and tokens and filter out, and fix potential overflow issues
This commit is contained in:
parent
1b7801dff8
commit
c247541410
2 changed files with 49 additions and 9 deletions
|
|
@ -3,15 +3,16 @@
|
|||
// This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later.
|
||||
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
use log::warn;
|
||||
use poolperiod::PoolPeriod;
|
||||
use rocket::{get, http::Status, response::status::Custom, serde::json::Json, State};
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{
|
||||
db::{cauldron::pool::get_pool_period_snapshot, DB},
|
||||
timeutil::time_now,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
pub mod apyaggregator;
|
||||
pub mod poolperiod;
|
||||
|
|
@ -81,14 +82,17 @@ pub fn aggregate_apy(
|
|||
.get()
|
||||
.map_err(|e| Custom(Status::InternalServerError, format!("DB error: {e}")))?;
|
||||
|
||||
let pools: anyhow::Result<Vec<PoolPeriod>> =
|
||||
get_pool_period_snapshot(&conn, token, pkh, start, end)
|
||||
.map_err(|e| Custom(Status::InternalServerError, format!("Error: {e}")))?
|
||||
.into_iter()
|
||||
.map(|(start, end)| PoolPeriod::new(start, end))
|
||||
.collect();
|
||||
|
||||
let pools = pools.map_err(|e| Custom(Status::InternalServerError, format!("Error: {e}")))?;
|
||||
let pools: Vec<PoolPeriod> = get_pool_period_snapshot(&conn, token, pkh, start, end)
|
||||
.map_err(|e| Custom(Status::InternalServerError, format!("Error: {e}")))?
|
||||
.into_iter()
|
||||
.filter_map(|(start, end)| match PoolPeriod::new(start.clone(), end) {
|
||||
Ok(period) => Some(period),
|
||||
Err(e) => {
|
||||
warn!("Skipping invalid pool {}: {e}", start.pool_id);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let pools_count = pools.len();
|
||||
let apy = apyaggregator::APYAggregator::aggregate_apy(pools.into_iter(), Some(start as u64))
|
||||
|
|
|
|||
|
|
@ -177,4 +177,40 @@ mod tests {
|
|||
"expected {expected_apy} != actual {pool_apy}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_sats_rejected() {
|
||||
let start = PoolSnapshot::dummy(1000, 0, 100); // zero sats
|
||||
let end = PoolSnapshot::dummy(2000, 100, 100);
|
||||
let result = PoolPeriod::new(start, end);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_token_amount_rejected() {
|
||||
let start = PoolSnapshot::dummy(1000, 100, 0); // zero token_amount
|
||||
let end = PoolSnapshot::dummy(2000, 100, 100);
|
||||
let result = PoolPeriod::new(start, end);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_large_k_no_overflow() {
|
||||
// Values that would overflow u64 if multiplied directly
|
||||
// 10^10 * 10^10 = 10^20 > u64::MAX (~1.8 * 10^19)
|
||||
let start = PoolSnapshot::dummy(1000, 10_000_000_000, 10_000_000_000);
|
||||
let end = PoolSnapshot::dummy(2000, 10_000_000_000, 10_000_000_000);
|
||||
let result = PoolPeriod::new(start, end);
|
||||
assert!(result.is_ok(), "Should handle large values without overflow");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_yield_calculation_valid() {
|
||||
let start = PoolSnapshot::dummy(1000, 1000, 1000);
|
||||
let end = PoolSnapshot::dummy(2000, 1100, 1100); // 10% increase each
|
||||
let period = PoolPeriod::new(start, end).unwrap();
|
||||
let yield_result = period.pool_yield().unwrap();
|
||||
// sqrt(1.1 * 1.1) - 1 = 1.1 - 1 = 0.1 = 10%
|
||||
assert!((yield_result - dec!(10)).abs() < dec!(0.01));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue